├── .gitignore ├── .gitmodules ├── .travis.yml ├── LICENSE.txt ├── Makefile ├── README.md ├── build_all_configs.sh ├── format.sh ├── include ├── sdkconfig.h └── spiffs_config.h ├── main.cpp └── tclap ├── Arg.h ├── ArgException.h ├── ArgTraits.h ├── COPYING ├── CmdLine.h ├── CmdLineInterface.h ├── CmdLineOutput.h ├── Constraint.h ├── DocBookOutput.h ├── HelpVisitor.h ├── IgnoreRestVisitor.h ├── MultiArg.h ├── MultiSwitchArg.h ├── OptionalUnlabeledTracker.h ├── StandardTraits.h ├── StdOutput.h ├── SwitchArg.h ├── UnlabeledMultiArg.h ├── UnlabeledValueArg.h ├── ValueArg.h ├── ValuesConstraint.h ├── VersionVisitor.h ├── Visitor.h ├── XorHandler.h └── ZshCompletionOutput.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | mkspiffs 3 | mkspiffs.exe 4 | out.* 5 | *.tar.gz 6 | 7 | # eclipse wokspace files and dirs 8 | .project 9 | .cproject 10 | .settings 11 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "spiffs"] 2 | path = spiffs 3 | url = https://github.com/pellepl/spiffs.git 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | sudo: required 3 | services: 4 | - docker 5 | 6 | env: 7 | global: 8 | - BUILD_CMD=./build_all_configs.sh 9 | - BUILD_DIR=/workdir 10 | - DOCKER_IMAGE=multiarch/crossbuild 11 | 12 | matrix: 13 | include: 14 | - env: 15 | - TARGET_OS=linux64 16 | - CROSS_TRIPLE=x86_64-linux-gnu 17 | - env: 18 | - TARGET_OS=linux32 19 | # multiarch/crossbuild doesn't come with 32-bit compilers, use a different image 20 | - DOCKER_IMAGE=dockcross/linux-x86 21 | - CROSS_TRIPLE=i686-linux-gnu 22 | - BUILD_DIR=/work 23 | - env: 24 | - TARGET_OS=linux-armhf 25 | - CROSS_TRIPLE=arm-linux-gnueabihf 26 | - EXTRA_ARGS='-e SKIP_TESTS=1' 27 | - env: 28 | - TARGET_OS=linux-arm64 29 | - CROSS_TRIPLE=aarch64-linux-gnu 30 | - EXTRA_ARGS='-e SKIP_TESTS=1' 31 | - env: 32 | - TARGET_OS=win32 33 | - CROSS_TRIPLE=i686-w64-mingw32 34 | # multiarch/crossbuild doesn't come with 'zip', 35 | # so we build a tgz archive in the container, and re-package it later in the script. 36 | - EXTRA_ARGS='-e ARCHIVE=tar -e SKIP_TESTS=1' 37 | - env: 38 | - TARGET_OS=osx 39 | - CROSS_TRIPLE=x86_64-apple-darwin 40 | - EXTRA_ARGS='-e SKIP_TESTS=1 -e CXX=c++' 41 | 42 | script: 43 | - export VER=$(git describe) 44 | - echo ${VER} 45 | 46 | - >- 47 | docker run --rm 48 | -v ${PWD}:${BUILD_DIR} 49 | -e TARGET_OS=${TARGET_OS} 50 | -e CROSS_TRIPLE=${CROSS_TRIPLE} 51 | ${EXTRA_ARGS} 52 | ${DOCKER_IMAGE} 53 | ${BUILD_CMD} 54 | 55 | # Diagnostics 56 | - ls -l 57 | 58 | # for windows, prepare zip archives 59 | - | 60 | if [ $TARGET_OS = "win32" ]; then 61 | for dirname in $(ls -d mkspiffs-*/); do 62 | name=${dirname%/} 63 | zip -r $name.zip $dirname 64 | rm -f $name.tar.gz 65 | done 66 | fi 67 | 68 | # Prepare files with sizes and sha256 hashes 69 | - | 70 | for name in $(ls -1 mkspiffs-*-${TARGET_OS}.*); do 71 | DIST_SIZE=$(wc -c <${name} 2>/dev/null | tr -d ' ') 72 | DIST_SHA256=$(shasum -a 256 ${name} | cut -d ' ' -f1) 73 | echo ${name} ${DIST_SIZE} ${DIST_SHA256} 74 | echo ${name} ${DIST_SIZE} ${DIST_SHA256} >${name}.sha256.txt 75 | done 76 | 77 | notifications: 78 | email: 79 | recipients: 80 | - ivan@espressif.com 81 | on_success: change 82 | on_failure: always 83 | deploy: 84 | provider: releases 85 | skip_cleanup: true 86 | api_key: 87 | secure: "AdgaAHsU3xkyKqcZu6Yp3njmWTXFm/Ggsq9n6cC9byHTDdcQ6UqdX1gPzud53YkSDbUjst5vok0i9xywH2pFWVt6G+FAD5uI/h1IiacQQ9rjnDef++nz+KkZtsPUhAD8LOdKPvJ7TmNNnkN35VFqyQETr/18bdzGC0tEZQK2BFQQrdz6cOGeez1ADYal0LAVHHcfolnwZb9jCT51nPEpSMlhxwSNNFncG2Y8MLDT2Q1y0xR3iI6aSSkMxqWCYYIdEC12rffwyRbC2P+JXp+AXNayLuKjCFnWB/QIyvrvoXtwbAEfW1pZzrWZAI5fI6zQaKKjixhf3Kr1f7y/xSPSdsPemdakRgANRTZW0R6wiXxUsTEjVGV6fWqUKT9pm335k8vWq2i+6exSrIVmYyxz4J3u6+Mgdbij5hI1NLVLq+It0KUVt99IOWaTOy01y6a0m1AprYYPgyw7fwlgChMPsLcaRrq1gtjtJr7wQKLaIlfYdEB4b0DtE/fx+b78mMQqXS/WvwSUGkJ5C2poLX2zdUxFe3phjeL3P0Daa0gLDQ2tCf/VmvPy20//b7MaO10URoeeV16fs+2BFzLjh38kzLRrPaRcBcwQFlzI1P+4mWPRDMuKvBn6i0sodFEzlUQMFSa8xyVtE5wIDLqepeG/9roW8woKIAmwG1k1YtM3XeE=" 88 | file_glob: true 89 | file: mkspiffs-*-$TARGET_OS.* 90 | on: 91 | repo: igrr/mkspiffs 92 | tags: true 93 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2017 Ivan Grokhotkov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # OS detection. Not used in CI builds 2 | ifndef TARGET_OS 3 | ifeq ($(OS),Windows_NT) 4 | TARGET_OS := win32 5 | else 6 | UNAME_S := $(shell uname -s) 7 | ifeq ($(UNAME_S),Linux) 8 | UNAME_M := $(shell uname -m) 9 | ifeq ($(UNAME_M),x86_64) 10 | TARGET_OS := linux64 11 | endif 12 | ifeq ($(UNAME_M),i686) 13 | TARGET_OS := linux32 14 | endif 15 | ifeq ($(UNAME_M),armv6l) 16 | TARGET_OS := linux-armhf 17 | endif 18 | endif 19 | ifeq ($(UNAME_S),Darwin) 20 | TARGET_OS := osx 21 | endif 22 | ifeq ($(UNAME_S),FreeBSD) 23 | TARGET_OS := freebsd 24 | endif 25 | endif 26 | endif # TARGET_OS 27 | 28 | # OS-specific settings and build flags 29 | ifeq ($(TARGET_OS),win32) 30 | ARCHIVE ?= zip 31 | TARGET := mkspiffs.exe 32 | TARGET_CFLAGS = -mno-ms-bitfields 33 | TARGET_LDFLAGS = -Wl,-static -static-libgcc -static-libstdc++ 34 | else 35 | ARCHIVE ?= tar 36 | TARGET := mkspiffs 37 | endif 38 | 39 | ifeq ($(TARGET_OS),osx) 40 | TARGET_CFLAGS = -mmacosx-version-min=10.7 -arch i386 -arch x86_64 41 | TARGET_CXXFLAGS = -mmacosx-version-min=10.7 -arch i386 -arch x86_64 -stdlib=libc++ 42 | TARGET_LDFLAGS = -mmacosx-version-min=10.7 -arch i386 -arch x86_64 -stdlib=libc++ 43 | endif 44 | 45 | # Packaging into archive (for 'dist' target) 46 | ifeq ($(ARCHIVE), zip) 47 | ARCHIVE_CMD := zip -r 48 | ARCHIVE_EXTENSION := zip 49 | endif 50 | ifeq ($(ARCHIVE), tar) 51 | ARCHIVE_CMD := tar czf 52 | ARCHIVE_EXTENSION := tar.gz 53 | endif 54 | 55 | 56 | VERSION ?= $(shell git describe --always) 57 | SPIFFS_VERSION := $(shell git -C spiffs describe --tags || echo "unknown") 58 | BUILD_CONFIG_NAME ?= -generic 59 | 60 | OBJ := main.o \ 61 | spiffs/src/spiffs_cache.o \ 62 | spiffs/src/spiffs_check.o \ 63 | spiffs/src/spiffs_gc.o \ 64 | spiffs/src/spiffs_hydrogen.o \ 65 | spiffs/src/spiffs_nucleus.o \ 66 | 67 | INCLUDES := -Itclap -Iinclude -Ispiffs/src -I. 68 | 69 | FILES_TO_FORMAT := $(shell find . -not -path './spiffs/*' \( -name '*.c' -o -name '*.cpp' \)) 70 | 71 | DIFF_FILES := $(addsuffix .diff,$(FILES_TO_FORMAT)) 72 | 73 | # clang doesn't seem to handle -D "ARG=\"foo bar\"" correctly, so replace spaces with \x20: 74 | BUILD_CONFIG_STR := $(shell echo $(CPPFLAGS) | sed 's- -\\\\x20-g') 75 | 76 | override CPPFLAGS := \ 77 | $(INCLUDES) \ 78 | -D VERSION=\"$(VERSION)\" \ 79 | -D SPIFFS_VERSION=\"$(SPIFFS_VERSION)\" \ 80 | -D BUILD_CONFIG=\"$(BUILD_CONFIG_STR)\" \ 81 | -D BUILD_CONFIG_NAME=\"$(BUILD_CONFIG_NAME)\" \ 82 | -D __NO_INLINE__ \ 83 | $(CPPFLAGS) 84 | 85 | override CFLAGS := -std=gnu99 -Os -Wall $(TARGET_CFLAGS) $(CFLAGS) 86 | override CXXFLAGS := -std=gnu++11 -Os -Wall $(TARGET_CXXFLAGS) $(CXXFLAGS) 87 | override LDFLAGS := $(TARGET_LDFLAGS) $(LDFLAGS) 88 | 89 | DIST_NAME := mkspiffs-$(VERSION)$(BUILD_CONFIG_NAME)-$(TARGET_OS) 90 | DIST_DIR := $(DIST_NAME) 91 | DIST_ARCHIVE := $(DIST_NAME).$(ARCHIVE_EXTENSION) 92 | 93 | all: $(TARGET) 94 | 95 | dist: $(DIST_ARCHIVE) 96 | 97 | ifndef SKIP_TESTS 98 | dist: test 99 | endif 100 | 101 | $(DIST_ARCHIVE): $(TARGET) $(DIST_DIR) 102 | cp $(TARGET) $(DIST_DIR)/ 103 | $(ARCHIVE_CMD) $(DIST_ARCHIVE) $(DIST_DIR) 104 | 105 | $(TARGET): $(OBJ) 106 | $(CXX) $^ -o $@ $(LDFLAGS) 107 | strip $(TARGET) 108 | 109 | $(DIST_DIR): 110 | @mkdir -p $@ 111 | 112 | clean: 113 | @rm -f $(TARGET) $(OBJ) $(DIFF_FILES) 114 | 115 | SPIFFS_TEST_FS_CONFIG := -s 0x100000 -p 512 -b 0x2000 116 | 117 | test: $(TARGET) 118 | mkdir -p spiffs_t 119 | cp spiffs/src/*.h spiffs_t/ 120 | cp spiffs/src/*.c spiffs_t/ 121 | rm -rf spiffs_t/.git 122 | rm -f spiffs_t/.DS_Store 123 | ls -1 spiffs_t > out.list0 124 | touch spiffs_t/.DS_Store 125 | mkdir -p spiffs_t/.git 126 | touch spiffs_t/.git/foo 127 | ./mkspiffs -c spiffs_t $(SPIFFS_TEST_FS_CONFIG) out.spiffs_t | sort | sed s/^\\/// > out.list1 128 | ./mkspiffs -u spiffs_u $(SPIFFS_TEST_FS_CONFIG) out.spiffs_t | sort | sed s/^\\/// > out.list_u 129 | ./mkspiffs -l $(SPIFFS_TEST_FS_CONFIG) out.spiffs_t | cut -f 2 | sort | sed s/^\\/// > out.list2 130 | awk 'BEGIN{RS="\1";ORS="";getline;gsub("\r","");print>ARGV[1]}' out.list0 out.list1 out.list2 131 | diff out.list0 out.list1 132 | diff out.list0 out.list2 133 | rm -rf spiffs_t/.git 134 | rm -f spiffs_t/.DS_Store 135 | diff spiffs_t spiffs_u 136 | rm -f out.{list0,list1,list2,list_u,spiffs_t} 137 | rm -R spiffs_u spiffs_t 138 | 139 | format-check: $(DIFF_FILES) 140 | @rm -f $(DIFF_FILES) 141 | 142 | $(DIFF_FILES): %.diff: % 143 | @./format.sh < $< >$<.new 144 | @diff $<.new $< >$@ || ( \ 145 | echo "File $^ not formatted correctly. Please use format.sh to re-format it." && \ 146 | echo "Here's the diff that caused an error:" && \ 147 | echo "" && \ 148 | cat $@ && \ 149 | rm $@ $<.new && \ 150 | exit 1 ) 151 | @rm -f $@ $<.new 152 | 153 | .PHONY: all clean dist format-check 154 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mkspiffs 2 | Tool to build and unpack [SPIFFS](https://github.com/pellepl/spiffs) images. 3 | 4 | 5 | ## Usage 6 | 7 | ``` 8 | 9 | mkspiffs {-c |-u |-l|-i} [-d <0-5>] [-b ] 10 | [-p ] [-s ] [--] [--version] [-h] 11 | 12 | 13 | 14 | Where: 15 | 16 | -c , --create 17 | (OR required) create spiffs image from a directory 18 | -- OR -- 19 | -u , --unpack 20 | (OR required) unpack spiffs image to a directory 21 | -- OR -- 22 | -l, --list 23 | (OR required) list files in spiffs image 24 | -- OR -- 25 | -i, --visualize 26 | (OR required) visualize spiffs image 27 | 28 | 29 | -d <0-5>, --debug <0-5> 30 | Debug level. 0 means no debug output. 31 | 32 | -b , --block 33 | fs block size, in bytes 34 | 35 | -p , --page 36 | fs page size, in bytes 37 | 38 | -s , --size 39 | fs image size, in bytes 40 | 41 | --, --ignore_rest 42 | Ignores the rest of the labeled arguments following this flag. 43 | 44 | --version 45 | Displays version information and exits. 46 | 47 | -h, --help 48 | Displays usage information and exits. 49 | 50 | 51 | (required) spiffs image file 52 | 53 | 54 | ``` 55 | ## Build 56 | 57 | 58 | [![Build status](http://img.shields.io/travis/igrr/mkspiffs.svg)](https://travis-ci.org/igrr/mkspiffs) 59 | 60 | 61 | You need gcc (≥4.8) or clang(≥600.0.57), and make. On Windows, use MinGW. 62 | 63 | Run: 64 | ```bash 65 | $ git submodule update --init 66 | $ make dist 67 | ``` 68 | 69 | ## SPIFFS configuration 70 | 71 | Some SPIFFS options which are set at mkspiffs build time affect the format of the generated filesystem image. Make sure such options are set to the same values when builing mkspiffs and when building the application which uses SPIFFS. 72 | 73 | These options include: 74 | 75 | - SPIFFS_OBJ_NAME_LEN 76 | - SPIFFS_OBJ_META_LEN 77 | - SPIFFS_USE_MAGIC 78 | - SPIFFS_USE_MAGIC_LENGTH 79 | - SPIFFS_ALIGNED_OBJECT_INDEX_TABLES 80 | - possibly others 81 | 82 | To see the default values of these options, check `include/spiffs_config.h` file in this repository. 83 | 84 | To override some options at build time, pass extra `CPPFLAGS` to `make`. You can also set `BUILD_CONFIG_NAME` variable to distinguish the built binary: 85 | 86 | ```bash 87 | $ make clean 88 | $ make dist CPPFLAGS="-DSPIFFS_OBJ_META_LEN=4" BUILD_CONFIG_NAME=-custom 89 | ``` 90 | 91 | To check which options were set when building mkspiffs, use `--version` command: 92 | 93 | ``` 94 | $ mkspiffs --version 95 | mkspiffs ver. 0.2.2 96 | Build configuration name: custom 97 | SPIFFS ver. 0.3.7-5-gf5e26c4 98 | Extra build flags: -DSPIFFS_OBJ_META_LEN=4 99 | SPIFFS configuration: 100 | SPIFFS_OBJ_NAME_LEN: 32 101 | SPIFFS_OBJ_META_LEN: 4 102 | SPIFFS_USE_MAGIC: 1 103 | SPIFFS_USE_MAGIC_LENGTH: 1 104 | SPIFFS_ALIGNED_OBJECT_INDEX_TABLES: 0 105 | ``` 106 | 107 | 108 | ## License 109 | 110 | MIT 111 | 112 | ## To do 113 | 114 | - [ ] Add more debug output and print SPIFFS debug output 115 | - [ ] Error handling 116 | - [ ] Code cleanup 117 | -------------------------------------------------------------------------------- /build_all_configs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Script used in CI to build all configurations of mkspiffs 4 | # 5 | 6 | set -e 7 | 8 | # Generic (default options) 9 | make dist 10 | 11 | # Arduino ESP8266 12 | make clean 13 | make dist BUILD_CONFIG_NAME="-arduino-esp8266" \ 14 | CPPFLAGS="-DSPIFFS_USE_MAGIC_LENGTH=0 -DSPIFFS_ALIGNED_OBJECT_INDEX_TABLES=1" 15 | 16 | # Build configuration for arduino-esp32 17 | make clean 18 | make dist BUILD_CONFIG_NAME="-arduino-esp32" \ 19 | CPPFLAGS="-DSPIFFS_OBJ_META_LEN=4" 20 | 21 | # Build configuration for ESP-IDF (esp32) 22 | make clean 23 | make dist BUILD_CONFIG_NAME="-esp-idf" \ 24 | CPPFLAGS="-DSPIFFS_OBJ_META_LEN=4" 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /format.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Runs astyle with the full set of formatting options 3 | astyle \ 4 | --style=otbs \ 5 | --indent=spaces=4 \ 6 | --convert-tabs \ 7 | --keep-one-line-statements \ 8 | --pad-header \ 9 | --pad-oper \ 10 | "$@" 11 | -------------------------------------------------------------------------------- /include/sdkconfig.h: -------------------------------------------------------------------------------- 1 | // Dummy file to be replaced by build script. 2 | -------------------------------------------------------------------------------- /include/spiffs_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * spiffs_config.h 3 | * 4 | * Created on: Jul 3, 2013 5 | * Author: petera 6 | */ 7 | 8 | #ifndef SPIFFS_CONFIG_H_ 9 | #define SPIFFS_CONFIG_H_ 10 | 11 | // ----------- 8< ------------ 12 | // Following includes are for the linux test build of spiffs 13 | // These may/should/must be removed/altered/replaced in your target 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | // Rename defines from menuconfig if present from sdkconfig.h 24 | #ifdef CONFIG_SPIFFS_USE_MAGIC_LENGTH 25 | #define SPIFFS_USE_MAGIC_LENGTH CONFIG_SPIFFS_USE_MAGIC_LENGTH 26 | #endif 27 | #ifdef CONFIG_SPIFFS_CACHE_WR 28 | #define SPIFFS_CACHE_WR CONFIG_SPIFFS_CACHE_WR 29 | #endif 30 | #ifdef CONFIG_SPIFFS_CACHE 31 | #define SPIFFS_CACHE CONFIG_SPIFFS_CACHE 32 | #endif 33 | #ifdef CONFIG_SPIFFS_META_LENGTH 34 | #define SPIFFS_OBJ_META_LEN CONFIG_SPIFFS_META_LENGTH 35 | #endif 36 | #ifdef CONFIG_SPIFFS_USE_MAGIC 37 | #define SPIFFS_USE_MAGIC CONFIG_SPIFFS_USE_MAGIC 38 | #endif 39 | #ifdef CONFIG_SPIFFS_PAGE_CHECK 40 | #define SPIFFS_PAGE_CHECK CONFIG_SPIFFS_PAGE_CHECK 41 | #endif 42 | #ifdef CONFIG_SPIFFS_USE_MTIME 43 | #define SPIFFS_USE_MTIME CONFIG_SPIFFS_USE_MTIME 44 | #endif 45 | #ifdef CONFIG_SPIFFS_GC_MAX_RUNS 46 | #define SPIFFS_GC_MAX_RUNS CONFIG_SPIFFS_GC_MAX_RUNS 47 | #endif 48 | #ifdef CONFIG_SPIFFS_MAX_PARTITIONS 49 | #define SPIFFS_MAX_PARTITIONS CONFIG_SPIFFS_MAX_PARTITIONS 50 | #endif 51 | #ifdef CONFIG_SPIFFS_OBJ_NAME_LEN 52 | #define SPIFFS_OBJ_NAME_LEN CONFIG_SPIFFS_OBJ_NAME_LEN 53 | #endif 54 | #ifdef CONFIG_SPIFFS_PAGE_SIZE 55 | #define SPIFFS_PAGE_SIZE CONFIG_SPIFFS_PAGE_SIZE 56 | #endif 57 | 58 | // Set generic spiffs debug output call. 59 | #ifndef SPIFFS_DBG 60 | #define SPIFFS_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) 61 | #endif 62 | // Set spiffs debug output call for garbage collecting. 63 | #ifndef SPIFFS_GC_DBG 64 | #define SPIFFS_GC_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) 65 | #endif 66 | // Set spiffs debug output call for caching. 67 | #ifndef SPIFFS_CACHE_DBG 68 | #define SPIFFS_CACHE_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) 69 | #endif 70 | // Set spiffs debug output call for system consistency checks. 71 | #ifndef SPIFFS_CHECK_DBG 72 | #define SPIFFS_CHECK_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) 73 | #endif 74 | // Set spiffs debug output call for all api invocations. 75 | #ifndef SPIFFS_API_DBG 76 | #define SPIFFS_API_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) 77 | #endif 78 | 79 | // needed types 80 | typedef int16_t file_t; 81 | typedef int32_t s32_t; 82 | typedef uint32_t u32_t; 83 | typedef int16_t s16_t; 84 | typedef uint16_t u16_t; 85 | typedef int8_t s8_t; 86 | typedef uint8_t u8_t; 87 | 88 | // Defines spiffs debug print formatters 89 | // some general signed number 90 | #define _SPIPRIi "%d" 91 | // address 92 | #define _SPIPRIad "%08x" 93 | // block 94 | #define _SPIPRIbl "%04x" 95 | // page 96 | #define _SPIPRIpg "%04x" 97 | // span index 98 | #define _SPIPRIsp "%04x" 99 | // file descriptor 100 | #define _SPIPRIfd "%d" 101 | // file object id 102 | #define _SPIPRIid "%04x" 103 | // file flags 104 | #define _SPIPRIfl "%02x" 105 | 106 | 107 | // Enable/disable API functions to determine exact number of bytes 108 | // for filedescriptor and cache buffers. Once decided for a configuration, 109 | // this can be disabled to reduce flash. 110 | #ifndef SPIFFS_BUFFER_HELP 111 | #define SPIFFS_BUFFER_HELP 0 112 | #endif 113 | 114 | // Enables/disable memory read caching of nucleus file system operations. 115 | // If enabled, memory area must be provided for cache in SPIFFS_mount. 116 | #ifndef SPIFFS_CACHE 117 | #define SPIFFS_CACHE 1 118 | #endif 119 | #if SPIFFS_CACHE 120 | // Enables memory write caching for file descriptors in hydrogen 121 | #ifndef SPIFFS_CACHE_WR 122 | #define SPIFFS_CACHE_WR 1 123 | #endif 124 | 125 | // Enable/disable statistics on caching. Debug/test purpose only. 126 | #ifndef SPIFFS_CACHE_STATS 127 | #define SPIFFS_CACHE_STATS 0 128 | #endif 129 | #endif 130 | 131 | // Always check header of each accessed page to ensure consistent state. 132 | // If enabled it will increase number of reads, will increase flash. 133 | #ifndef SPIFFS_PAGE_CHECK 134 | #define SPIFFS_PAGE_CHECK 1 135 | #endif 136 | 137 | // Define maximum number of gc runs to perform to reach desired free pages. 138 | #ifndef SPIFFS_GC_MAX_RUNS 139 | #define SPIFFS_GC_MAX_RUNS 10 140 | #endif 141 | 142 | // Enable/disable statistics on gc. Debug/test purpose only. 143 | #ifndef SPIFFS_GC_STATS 144 | #define SPIFFS_GC_STATS 0 145 | #endif 146 | 147 | // Garbage collecting examines all pages in a block which and sums up 148 | // to a block score. Deleted pages normally gives positive score and 149 | // used pages normally gives a negative score (as these must be moved). 150 | // To have a fair wear-leveling, the erase age is also included in score, 151 | // whose factor normally is the most positive. 152 | // The larger the score, the more likely it is that the block will 153 | // picked for garbage collection. 154 | 155 | // Garbage collecting heuristics - weight used for deleted pages. 156 | #define SPIFFS_GC_HEUR_W_DELET (5) 157 | // Garbage collecting heuristics - weight used for used pages. 158 | #define SPIFFS_GC_HEUR_W_USED (-1) 159 | // Garbage collecting heuristics - weight used for time between 160 | // last erased and erase of this block. 161 | #define SPIFFS_GC_HEUR_W_ERASE_AGE (50) 162 | 163 | // Object name maximum length. Note that this length include the 164 | // zero-termination character, meaning maximum string of characters 165 | // can at most be SPIFFS_OBJ_NAME_LEN - 1. 166 | #ifndef SPIFFS_OBJ_NAME_LEN 167 | #define SPIFFS_OBJ_NAME_LEN (32) 168 | #endif 169 | 170 | // Maximum length of the metadata associated with an object. 171 | // Setting to non-zero value enables metadata-related API but also 172 | // changes the on-disk format, so the change is not backward-compatible. 173 | // 174 | // Do note: the meta length must never exceed 175 | // logical_page_size - (SPIFFS_OBJ_NAME_LEN + 64) 176 | // 177 | // This is derived from following: 178 | // logical_page_size - (SPIFFS_OBJ_NAME_LEN + sizeof(spiffs_page_header) + 179 | // spiffs_object_ix_header fields + at least some LUT entries) 180 | #ifndef SPIFFS_OBJ_META_LEN 181 | #define SPIFFS_OBJ_META_LEN (0) 182 | #endif 183 | 184 | // Size of buffer allocated on stack used when copying data. 185 | // Lower value generates more read/writes. No meaning having it bigger 186 | // than logical page size. 187 | #ifndef SPIFFS_COPY_BUFFER_STACK 188 | #define SPIFFS_COPY_BUFFER_STACK (256) 189 | #endif 190 | 191 | // Enable this to have an identifiable spiffs filesystem. This will look for 192 | // a magic in all sectors to determine if this is a valid spiffs system or 193 | // not on mount point. If not, SPIFFS_format must be called prior to mounting 194 | // again. 195 | #ifndef SPIFFS_USE_MAGIC 196 | #define SPIFFS_USE_MAGIC (1) 197 | #endif 198 | 199 | #if SPIFFS_USE_MAGIC 200 | // Only valid when SPIFFS_USE_MAGIC is enabled. If SPIFFS_USE_MAGIC_LENGTH is 201 | // enabled, the magic will also be dependent on the length of the filesystem. 202 | // For example, a filesystem configured and formatted for 4 megabytes will not 203 | // be accepted for mounting with a configuration defining the filesystem as 2 204 | // megabytes. 205 | #ifndef SPIFFS_USE_MAGIC_LENGTH 206 | #define SPIFFS_USE_MAGIC_LENGTH (1) 207 | #endif 208 | #endif 209 | 210 | // SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level 211 | // These should be defined on a multithreaded system 212 | 213 | // define this to enter a mutex if you're running on a multithreaded system 214 | #define SPIFFS_LOCK(fs) 215 | // define this to exit a mutex if you're running on a multithreaded system 216 | #define SPIFFS_UNLOCK(fs) 217 | 218 | // Enable if only one spiffs instance with constant configuration will exist 219 | // on the target. This will reduce calculations, flash and memory accesses. 220 | // Parts of configuration must be defined below instead of at time of mount. 221 | #define SPIFFS_SINGLETON 0 222 | 223 | // Enable this if your target needs aligned data for index tables 224 | #ifndef SPIFFS_ALIGNED_OBJECT_INDEX_TABLES 225 | #define SPIFFS_ALIGNED_OBJECT_INDEX_TABLES 0 226 | #endif 227 | 228 | // Enable this if you want the HAL callbacks to be called with the spiffs struct 229 | #ifndef SPIFFS_HAL_CALLBACK_EXTRA 230 | #define SPIFFS_HAL_CALLBACK_EXTRA 0 231 | #endif 232 | 233 | // Enable this if you want to add an integer offset to all file handles 234 | // (spiffs_file). This is useful if running multiple instances of spiffs on 235 | // same target, in order to recognise to what spiffs instance a file handle 236 | // belongs. 237 | // NB: This adds config field fh_ix_offset in the configuration struct when 238 | // mounting, which must be defined. 239 | #ifndef SPIFFS_FILEHDL_OFFSET 240 | #define SPIFFS_FILEHDL_OFFSET 0 241 | #endif 242 | 243 | // Enable this to compile a read only version of spiffs. 244 | // This will reduce binary size of spiffs. All code comprising modification 245 | // of the file system will not be compiled. Some config will be ignored. 246 | // HAL functions for erasing and writing to spi-flash may be null. Cache 247 | // can be disabled for even further binary size reduction (and ram savings). 248 | // Functions modifying the fs will return SPIFFS_ERR_RO_NOT_IMPL. 249 | // If the file system cannot be mounted due to aborted erase operation and 250 | // SPIFFS_USE_MAGIC is enabled, SPIFFS_ERR_RO_ABORTED_OPERATION will be 251 | // returned. 252 | // Might be useful for e.g. bootloaders and such. 253 | #ifndef SPIFFS_READ_ONLY 254 | #define SPIFFS_READ_ONLY 0 255 | #endif 256 | 257 | // Enable this to add a temporal file cache using the fd buffer. 258 | // The effects of the cache is that SPIFFS_open will find the file faster in 259 | // certain cases. It will make it a lot easier for spiffs to find files 260 | // opened frequently, reducing number of readings from the spi flash for 261 | // finding those files. 262 | // This will grow each fd by 6 bytes. If your files are opened in patterns 263 | // with a degree of temporal locality, the system is optimized. 264 | // Examples can be letting spiffs serve web content, where one file is the css. 265 | // The css is accessed for each html file that is opened, meaning it is 266 | // accessed almost every second time a file is opened. Another example could be 267 | // a log file that is often opened, written, and closed. 268 | // The size of the cache is number of given file descriptors, as it piggybacks 269 | // on the fd update mechanism. The cache lives in the closed file descriptors. 270 | // When closed, the fd know the whereabouts of the file. Instead of forgetting 271 | // this, the temporal cache will keep handling updates to that file even if the 272 | // fd is closed. If the file is opened again, the location of the file is found 273 | // directly. If all available descriptors become opened, all cache memory is 274 | // lost. 275 | #ifndef SPIFFS_TEMPORAL_FD_CACHE 276 | #define SPIFFS_TEMPORAL_FD_CACHE 1 277 | #endif 278 | 279 | // Temporal file cache hit score. Each time a file is opened, all cached files 280 | // will lose one point. If the opened file is found in cache, that entry will 281 | // gain SPIFFS_TEMPORAL_CACHE_HIT_SCORE points. One can experiment with this 282 | // value for the specific access patterns of the application. However, it must 283 | // be between 1 (no gain for hitting a cached entry often) and 255. 284 | #ifndef SPIFFS_TEMPORAL_CACHE_HIT_SCORE 285 | #define SPIFFS_TEMPORAL_CACHE_HIT_SCORE 4 286 | #endif 287 | 288 | // Enable to be able to map object indices to memory. 289 | // This allows for faster and more deterministic reading if cases of reading 290 | // large files and when changing file offset by seeking around a lot. 291 | // When mapping a file's index, the file system will be scanned for index pages 292 | // and the info will be put in memory provided by user. When reading, the 293 | // memory map can be looked up instead of searching for index pages on the 294 | // medium. This way, user can trade memory against performance. 295 | // Whole, parts of, or future parts not being written yet can be mapped. The 296 | // memory array will be owned by spiffs and updated accordingly during garbage 297 | // collecting or when modifying the indices. The latter is invoked by when the 298 | // file is modified in some way. The index buffer is tied to the file 299 | // descriptor. 300 | #ifndef SPIFFS_IX_MAP 301 | #define SPIFFS_IX_MAP 1 302 | #endif 303 | 304 | // Set SPIFFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function 305 | // in the api. This function will visualize all filesystem using given printf 306 | // function.. 307 | #ifndef SPIFFS_TEST_VISUALISATION 308 | #define SPIFFS_TEST_VISUALISATION 1 309 | #endif 310 | #if SPIFFS_TEST_VISUALISATION 311 | #ifndef spiffs_printf 312 | #define spiffs_printf(...) printf(__VA_ARGS__) 313 | #endif 314 | // spiffs_printf argument for a free page 315 | #define SPIFFS_TEST_VIS_FREE_STR "_" 316 | // spiffs_printf argument for a deleted page 317 | #define SPIFFS_TEST_VIS_DELE_STR "/" 318 | // spiffs_printf argument for an index page for given object id 319 | #define SPIFFS_TEST_VIS_INDX_STR(id) "i" 320 | // spiffs_printf argument for a data page for given object id 321 | #define SPIFFS_TEST_VIS_DATA_STR(id) "d" 322 | #endif 323 | 324 | // Types depending on configuration such as the amount of flash bytes 325 | // given to spiffs file system in total (spiffs_file_system_size), 326 | // the logical block size (log_block_size), and the logical page size 327 | // (log_page_size) 328 | 329 | // Block index type. Make sure the size of this type can hold 330 | // the highest number of all blocks - i.e. spiffs_file_system_size / log_block_size 331 | typedef u16_t spiffs_block_ix; 332 | // Page index type. Make sure the size of this type can hold 333 | // the highest page number of all pages - i.e. spiffs_file_system_size / log_page_size 334 | typedef u16_t spiffs_page_ix; 335 | // Object id type - most significant bit is reserved for index flag. Make sure the 336 | // size of this type can hold the highest object id on a full system, 337 | // i.e. 2 + (spiffs_file_system_size / (2*log_page_size))*2 338 | typedef u16_t spiffs_obj_id; 339 | // Object span index type. Make sure the size of this type can 340 | // hold the largest possible span index on the system - 341 | // i.e. (spiffs_file_system_size / log_page_size) - 1 342 | typedef u16_t spiffs_span_ix; 343 | 344 | #endif /* SPIFFS_CONFIG_H_ */ 345 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // main.cpp 3 | // make_spiffs 4 | // 5 | // Created by Ivan Grokhotkov on 13/05/15. 6 | // Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. 7 | // 8 | #define TCLAP_SETBASE_ZERO 1 9 | 10 | #include 11 | #include "spiffs.h" 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "tclap/CmdLine.h" 22 | #include "tclap/UnlabeledValueArg.h" 23 | 24 | #ifdef _WIN32 25 | #include 26 | #endif 27 | 28 | static std::vector s_flashmem; 29 | 30 | static std::string s_dirName; 31 | static std::string s_imageName; 32 | static int s_imageSize; 33 | static int s_pageSize; 34 | static int s_blockSize; 35 | 36 | enum Action { ACTION_NONE, ACTION_PACK, ACTION_UNPACK, ACTION_LIST, ACTION_VISUALIZE }; 37 | static Action s_action = ACTION_NONE; 38 | 39 | static spiffs s_fs; 40 | 41 | static std::vector s_spiffsWorkBuf; 42 | static std::vector s_spiffsFds; 43 | static std::vector s_spiffsCache; 44 | 45 | static int s_debugLevel = 0; 46 | static bool s_addAllFiles; 47 | 48 | // Unless -a flag is given, these files/directories will not be included into the image 49 | static const char* ignored_file_names[] = { 50 | ".DS_Store", 51 | ".git", 52 | ".gitignore", 53 | ".gitmodules" 54 | }; 55 | 56 | static s32_t api_spiffs_read(u32_t addr, u32_t size, u8_t *dst) 57 | { 58 | memcpy(dst, &s_flashmem[0] + addr, size); 59 | return SPIFFS_OK; 60 | } 61 | 62 | static s32_t api_spiffs_write(u32_t addr, u32_t size, u8_t *src) 63 | { 64 | memcpy(&s_flashmem[0] + addr, src, size); 65 | return SPIFFS_OK; 66 | } 67 | 68 | static s32_t api_spiffs_erase(u32_t addr, u32_t size) 69 | { 70 | memset(&s_flashmem[0] + addr, 0xff, size); 71 | return SPIFFS_OK; 72 | } 73 | 74 | static int checkArgs(); 75 | static size_t getFileSize(FILE* fp); 76 | 77 | 78 | //implementation 79 | 80 | int spiffsTryMount() 81 | { 82 | spiffs_config cfg = {0}; 83 | 84 | cfg.phys_addr = 0x0000; 85 | cfg.phys_size = (u32_t) s_flashmem.size(); 86 | 87 | cfg.phys_erase_block = s_blockSize; 88 | cfg.log_block_size = s_blockSize; 89 | cfg.log_page_size = s_pageSize; 90 | 91 | cfg.hal_read_f = api_spiffs_read; 92 | cfg.hal_write_f = api_spiffs_write; 93 | cfg.hal_erase_f = api_spiffs_erase; 94 | 95 | const int maxOpenFiles = 4; 96 | s_spiffsWorkBuf.resize(s_pageSize * 2); 97 | s_spiffsFds.resize(32 * maxOpenFiles); 98 | s_spiffsCache.resize((32 + s_pageSize) * maxOpenFiles); 99 | 100 | return SPIFFS_mount(&s_fs, &cfg, 101 | &s_spiffsWorkBuf[0], 102 | &s_spiffsFds[0], s_spiffsFds.size(), 103 | &s_spiffsCache[0], s_spiffsCache.size(), 104 | NULL); 105 | } 106 | 107 | bool spiffsMount(bool printError = true) 108 | { 109 | if (SPIFFS_mounted(&s_fs)) { 110 | return true; 111 | } 112 | int res = spiffsTryMount(); 113 | if (res != SPIFFS_OK) { 114 | if (printError) { 115 | std::cerr << "SPIFFS mount failed with error: " << res << std::endl; 116 | } 117 | return false; 118 | } 119 | return true; 120 | } 121 | 122 | bool spiffsFormat() 123 | { 124 | spiffsMount(false); 125 | SPIFFS_unmount(&s_fs); 126 | int formated = SPIFFS_format(&s_fs); 127 | if (formated != SPIFFS_OK) { 128 | return false; 129 | } 130 | return (spiffsTryMount() == SPIFFS_OK); 131 | } 132 | 133 | void spiffsUnmount() 134 | { 135 | if (SPIFFS_mounted(&s_fs)) { 136 | SPIFFS_unmount(&s_fs); 137 | } 138 | } 139 | 140 | int addFile(char* name, const char* path) 141 | { 142 | FILE* src = fopen(path, "rb"); 143 | if (!src) { 144 | std::cerr << "error: failed to open " << path << " for reading" << std::endl; 145 | return 1; 146 | } 147 | 148 | spiffs_file dst = SPIFFS_open(&s_fs, name, SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0); 149 | 150 | // read file size 151 | size_t size = getFileSize(src); 152 | 153 | if (s_debugLevel > 0) { 154 | std::cout << "file size: " << size << std::endl; 155 | } 156 | 157 | size_t left = size; 158 | uint8_t data_byte; 159 | while (left > 0) { 160 | if (1 != fread(&data_byte, 1, 1, src)) { 161 | std::cerr << "fread error!" << std::endl; 162 | 163 | fclose(src); 164 | SPIFFS_close(&s_fs, dst); 165 | return 1; 166 | } 167 | int res = SPIFFS_write(&s_fs, dst, &data_byte, 1); 168 | if (res < 0) { 169 | std::cerr << "SPIFFS_write error(" << s_fs.err_code << "): "; 170 | 171 | if (s_fs.err_code == SPIFFS_ERR_FULL) { 172 | std::cerr << "File system is full." << std::endl; 173 | } else { 174 | std::cerr << "unknown"; 175 | } 176 | std::cerr << std::endl; 177 | 178 | if (s_debugLevel > 0) { 179 | std::cout << "data left: " << left << std::endl; 180 | } 181 | 182 | fclose(src); 183 | SPIFFS_close(&s_fs, dst); 184 | return 1; 185 | } 186 | left -= 1; 187 | } 188 | 189 | SPIFFS_close(&s_fs, dst); 190 | fclose(src); 191 | 192 | return 0; 193 | } 194 | 195 | int addFiles(const char* dirname, const char* subPath) 196 | { 197 | DIR *dir; 198 | struct dirent *ent; 199 | bool error = false; 200 | std::string dirPath = dirname; 201 | dirPath += subPath; 202 | 203 | // Open directory 204 | if ((dir = opendir (dirPath.c_str())) != NULL) { 205 | 206 | // Read files from directory. 207 | while ((ent = readdir (dir)) != NULL) { 208 | 209 | // Ignore dir itself. 210 | if ((strcmp(ent->d_name, ".") == 0) || (strcmp(ent->d_name, "..") == 0)) { 211 | continue; 212 | } 213 | 214 | if (!s_addAllFiles) { 215 | bool skip = false; 216 | size_t ignored_file_names_count = sizeof(ignored_file_names) / sizeof(ignored_file_names[0]); 217 | for (size_t i = 0; i < ignored_file_names_count; ++i) { 218 | if (strcmp(ent->d_name, ignored_file_names[i]) == 0) { 219 | std::cerr << "skipping " << ent->d_name << std::endl; 220 | skip = true; 221 | break; 222 | } 223 | } 224 | if (skip) { 225 | continue; 226 | } 227 | } 228 | 229 | std::string fullpath = dirPath; 230 | fullpath += ent->d_name; 231 | struct stat path_stat; 232 | stat (fullpath.c_str(), &path_stat); 233 | 234 | if (!S_ISREG(path_stat.st_mode)) { 235 | // Check if path is a directory. 236 | if (S_ISDIR(path_stat.st_mode)) { 237 | // Prepare new sub path. 238 | std::string newSubPath = subPath; 239 | newSubPath += ent->d_name; 240 | newSubPath += "/"; 241 | 242 | if (addFiles(dirname, newSubPath.c_str()) != 0) { 243 | std::cerr << "Error for adding content from " << ent->d_name << "!" << std::endl; 244 | } 245 | 246 | continue; 247 | } else { 248 | std::cerr << "skipping " << ent->d_name << std::endl; 249 | continue; 250 | } 251 | } 252 | 253 | // Filepath with dirname as root folder. 254 | std::string filepath = subPath; 255 | filepath += ent->d_name; 256 | std::cout << filepath << std::endl; 257 | 258 | // Add File to image. 259 | if (addFile((char*)filepath.c_str(), fullpath.c_str()) != 0) { 260 | std::cerr << "error adding file!" << std::endl; 261 | error = true; 262 | if (s_debugLevel > 0) { 263 | std::cout << std::endl; 264 | } 265 | break; 266 | } 267 | } // end while 268 | closedir (dir); 269 | } else { 270 | std::cerr << "warning: can't read source directory" << std::endl; 271 | return 1; 272 | } 273 | 274 | return (error) ? 1 : 0; 275 | } 276 | 277 | void listFiles() 278 | { 279 | spiffs_DIR dir; 280 | spiffs_dirent ent; 281 | 282 | SPIFFS_opendir(&s_fs, 0, &dir); 283 | spiffs_dirent* it; 284 | while (true) { 285 | it = SPIFFS_readdir(&dir, &ent); 286 | if (!it) { 287 | break; 288 | } 289 | 290 | std::cout << it->size << '\t' << it->name << std::endl; 291 | } 292 | SPIFFS_closedir(&dir); 293 | } 294 | 295 | /** 296 | * @brief Check if directory exists. 297 | * @param path Directory path. 298 | * @return True if exists otherwise false. 299 | * 300 | * @author Pascal Gollor (http://www.pgollor.de/cms/) 301 | */ 302 | bool dirExists(const char* path) 303 | { 304 | DIR *d = opendir(path); 305 | 306 | if (d) { 307 | closedir(d); 308 | return true; 309 | } 310 | 311 | return false; 312 | } 313 | 314 | /** 315 | * @brief Create directory if it not exists. 316 | * @param path Directory path. 317 | * @return True or false. 318 | * 319 | * @author Pascal Gollor (http://www.pgollor.de/cms/) 320 | */ 321 | bool dirCreate(const char* path) 322 | { 323 | // Check if directory also exists. 324 | if (dirExists(path)) { 325 | return false; 326 | } 327 | 328 | // platform stuff... 329 | #if defined(_WIN32) 330 | if (_mkdir(path) != 0) { 331 | #else 332 | if (mkdir(path, S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH) != 0) { 333 | #endif 334 | std::cerr << "Can not create directory!!!" << std::endl; 335 | return false; 336 | } 337 | 338 | return true; 339 | } 340 | 341 | /** 342 | * @brief Unpack file from file system. 343 | * @param spiffsFile SPIFFS dir entry pointer. 344 | * @param destPath Destination file path path. 345 | * @return True or false. 346 | * 347 | * @author Pascal Gollor (http://www.pgollor.de/cms/) 348 | */ 349 | bool unpackFile(spiffs_dirent *spiffsFile, const char *destPath) 350 | { 351 | u8_t buffer[spiffsFile->size]; 352 | std::string filename = (const char*)(spiffsFile->name); 353 | 354 | // Open file from spiffs file system. 355 | spiffs_file src = SPIFFS_open(&s_fs, (char *)(filename.c_str()), SPIFFS_RDONLY, 0); 356 | 357 | // read content into buffer 358 | SPIFFS_read(&s_fs, src, buffer, spiffsFile->size); 359 | 360 | // Close spiffs file. 361 | SPIFFS_close(&s_fs, src); 362 | 363 | // Open file. 364 | FILE* dst = fopen(destPath, "wb"); 365 | 366 | // Write content into file. 367 | fwrite(buffer, sizeof(u8_t), sizeof(buffer), dst); 368 | 369 | // Close file. 370 | fclose(dst); 371 | 372 | 373 | return true; 374 | } 375 | 376 | /** 377 | * @brief Unpack files from file system. 378 | * @param sDest Directory path as std::string. 379 | * @return True or false. 380 | * 381 | * @author Pascal Gollor (http://www.pgollor.de/cms/) 382 | * 383 | * todo: Do unpack stuff for directories. 384 | */ 385 | bool unpackFiles(std::string sDest) 386 | { 387 | spiffs_DIR dir; 388 | spiffs_dirent ent; 389 | 390 | // Add "./" to path if is not given. 391 | if (sDest.find("./") == std::string::npos && sDest.find("/") == std::string::npos) { 392 | sDest = "./" + sDest; 393 | } 394 | 395 | // Check if directory exists. If it does not then try to create it with permissions 755. 396 | if (! dirExists(sDest.c_str())) { 397 | std::cout << "Directory " << sDest << " does not exists. Try to create it." << std::endl; 398 | 399 | // Try to create directory. 400 | if (! dirCreate(sDest.c_str())) { 401 | return false; 402 | } 403 | } 404 | 405 | // Open directory. 406 | SPIFFS_opendir(&s_fs, 0, &dir); 407 | 408 | // Read content from directory. 409 | spiffs_dirent* it = SPIFFS_readdir(&dir, &ent); 410 | while (it) { 411 | // Check if content is a file. 412 | if ((int)(it->type) == 1) { 413 | std::string name = (const char*)(it->name); 414 | std::string sDestFilePath = sDest + name; 415 | size_t pos = name.find_first_of("/", 1); 416 | 417 | // If file is in sub directories? 418 | while (pos != std::string::npos) { 419 | // Subdir path. 420 | std::string path = sDest; 421 | path += name.substr(0, pos); 422 | 423 | // Create subddir if subdir not exists. 424 | if (!dirExists(path.c_str())) { 425 | if (!dirCreate(path.c_str())) { 426 | return false; 427 | } 428 | } 429 | 430 | pos = name.find_first_of("/", pos + 1); 431 | } 432 | 433 | // Unpack file to destination directory. 434 | if (! unpackFile(it, sDestFilePath.c_str()) ) { 435 | std::cout << "Can not unpack " << it->name << "!" << std::endl; 436 | return false; 437 | } 438 | 439 | // Output stuff. 440 | std::cout 441 | << it->name 442 | << '\t' 443 | << " > " << sDestFilePath 444 | << '\t' 445 | << "size: " << it->size << " Bytes" 446 | << std::endl; 447 | } 448 | 449 | // Get next file handle. 450 | it = SPIFFS_readdir(&dir, &ent); 451 | } // end while 452 | 453 | // Close directory. 454 | SPIFFS_closedir(&dir); 455 | 456 | return true; 457 | } 458 | 459 | // Actions 460 | 461 | int actionPack() 462 | { 463 | if (!dirExists(s_dirName.c_str())) { 464 | std::cerr << "error: can't read source directory" << std::endl; 465 | return 1; 466 | } 467 | 468 | if (s_imageSize == 0) { 469 | s_imageSize = 0x10000; 470 | if (s_debugLevel > 0) { 471 | std::cout << "image size not specifed, using default: " << s_imageSize << std::endl; 472 | } 473 | } 474 | 475 | int err = checkArgs(); 476 | if (err != 0) { 477 | return err; 478 | } 479 | 480 | s_flashmem.resize(s_imageSize, 0xff); 481 | 482 | FILE* fdres = fopen(s_imageName.c_str(), "wb"); 483 | if (!fdres) { 484 | std::cerr << "error: failed to open image file" << std::endl; 485 | return 1; 486 | } 487 | 488 | spiffsFormat(); 489 | int result = addFiles(s_dirName.c_str(), "/"); 490 | spiffsUnmount(); 491 | 492 | fwrite(&s_flashmem[0], 4, s_flashmem.size() / 4, fdres); 493 | fclose(fdres); 494 | 495 | return result; 496 | } 497 | 498 | static size_t getFileSize(FILE* fp) 499 | { 500 | fseek(fp, 0L, SEEK_END); 501 | size_t size = (size_t) ftell(fp); 502 | fseek(fp, 0L, SEEK_SET); 503 | return size; 504 | } 505 | 506 | /** 507 | * @brief Unpack action. 508 | * @return 0 success, 1 error 509 | * 510 | * @author Pascal Gollor (http://www.pgollor.de/cms/) 511 | */ 512 | int actionUnpack(void) 513 | { 514 | int ret = 0; 515 | 516 | // open spiffs image 517 | FILE* fdsrc = fopen(s_imageName.c_str(), "rb"); 518 | if (!fdsrc) { 519 | std::cerr << "error: failed to open image file" << std::endl; 520 | return 1; 521 | } 522 | 523 | if (s_imageSize == 0) { 524 | s_imageSize = getFileSize(fdsrc); 525 | } 526 | 527 | int err = checkArgs(); 528 | if (err != 0) { 529 | return err; 530 | } 531 | 532 | s_flashmem.resize(s_imageSize, 0xff); 533 | 534 | // read content into s_flashmem 535 | fread(&s_flashmem[0], 4, s_flashmem.size() / 4, fdsrc); 536 | 537 | // close file handle 538 | fclose(fdsrc); 539 | 540 | // mount file system 541 | if (!spiffsMount()) { 542 | std::cerr << "error: failed to mount image" << std::endl; 543 | return 1; 544 | } 545 | 546 | // unpack files 547 | if (! unpackFiles(s_dirName)) { 548 | ret = 1; 549 | } 550 | 551 | // unmount file system 552 | spiffsUnmount(); 553 | 554 | return ret; 555 | } 556 | 557 | 558 | int actionList() 559 | { 560 | FILE* fdsrc = fopen(s_imageName.c_str(), "rb"); 561 | if (!fdsrc) { 562 | std::cerr << "error: failed to open image file" << std::endl; 563 | return 1; 564 | } 565 | 566 | if (s_imageSize == 0) { 567 | s_imageSize = getFileSize(fdsrc); 568 | } 569 | 570 | int err = checkArgs(); 571 | if (err != 0) { 572 | return err; 573 | } 574 | 575 | s_flashmem.resize(s_imageSize, 0xff); 576 | 577 | fread(&s_flashmem[0], 4, s_flashmem.size() / 4, fdsrc); 578 | fclose(fdsrc); 579 | 580 | if (!spiffsMount()) { 581 | std::cerr << "error: failed to mount image" << std::endl; 582 | return 1; 583 | } 584 | 585 | listFiles(); 586 | spiffsUnmount(); 587 | return 0; 588 | } 589 | 590 | int actionVisualize() 591 | { 592 | FILE* fdsrc = fopen(s_imageName.c_str(), "rb"); 593 | if (!fdsrc) { 594 | std::cerr << "error: failed to open image file" << std::endl; 595 | return 1; 596 | } 597 | 598 | if (s_imageSize == 0) { 599 | s_imageSize = getFileSize(fdsrc); 600 | } 601 | 602 | int err = checkArgs(); 603 | if (err != 0) { 604 | return err; 605 | } 606 | 607 | s_flashmem.resize(s_imageSize, 0xff); 608 | 609 | 610 | fread(&s_flashmem[0], 4, s_flashmem.size() / 4, fdsrc); 611 | fclose(fdsrc); 612 | 613 | if (!spiffsMount()) { 614 | std::cerr << "error: failed to mount image" << std::endl; 615 | return 1; 616 | } 617 | 618 | SPIFFS_vis(&s_fs); 619 | uint32_t total, used; 620 | SPIFFS_info(&s_fs, &total, &used); 621 | std::cout << "total: " << total << std::endl << "used: " << used << std::endl; 622 | spiffsUnmount(); 623 | 624 | return 0; 625 | } 626 | 627 | #define PRINT_INT_MACRO(def_name) \ 628 | std::cout << " " # def_name ": " << def_name << std::endl; 629 | 630 | class CustomOutput : public TCLAP::StdOutput 631 | { 632 | public: 633 | virtual void version(TCLAP::CmdLineInterface& c) 634 | { 635 | std::cout << "mkspiffs ver. " VERSION << std::endl; 636 | const char* configName = BUILD_CONFIG_NAME; 637 | if (configName[0] == '-') { 638 | configName += 1; 639 | } 640 | std::cout << "Build configuration name: " << configName << std::endl; 641 | std::cout << "SPIFFS ver. " SPIFFS_VERSION << std::endl; 642 | const char* buildConfig = BUILD_CONFIG; 643 | std::cout << "Extra build flags: " << (strlen(buildConfig) ? buildConfig : "(none)") << std::endl; 644 | std::cout << "SPIFFS configuration:" << std::endl; 645 | PRINT_INT_MACRO(SPIFFS_OBJ_NAME_LEN); 646 | PRINT_INT_MACRO(SPIFFS_OBJ_META_LEN); 647 | PRINT_INT_MACRO(SPIFFS_USE_MAGIC); 648 | #if SPIFFS_USE_MAGIC == 1 649 | PRINT_INT_MACRO(SPIFFS_USE_MAGIC_LENGTH); 650 | #endif 651 | PRINT_INT_MACRO(SPIFFS_ALIGNED_OBJECT_INDEX_TABLES); 652 | } 653 | }; 654 | 655 | #undef PRINT_INT_MACRO 656 | 657 | void processArgs(int argc, const char** argv) 658 | { 659 | TCLAP::CmdLine cmd("", ' ', VERSION); 660 | CustomOutput output; 661 | cmd.setOutput(&output); 662 | 663 | TCLAP::ValueArg packArg( "c", "create", "create spiffs image from a directory", true, "", "pack_dir"); 664 | TCLAP::ValueArg unpackArg( "u", "unpack", "unpack spiffs image to a directory", true, "", "dest_dir"); 665 | TCLAP::SwitchArg listArg( "l", "list", "list files in spiffs image", false); 666 | TCLAP::SwitchArg visualizeArg( "i", "visualize", "visualize spiffs image", false); 667 | TCLAP::UnlabeledValueArg outNameArg( "image_file", "spiffs image file", true, "", "image_file" ); 668 | TCLAP::ValueArg imageSizeArg( "s", "size", "fs image size, in bytes", false, 0, "number" ); 669 | TCLAP::ValueArg pageSizeArg( "p", "page", "fs page size, in bytes", false, 256, "number" ); 670 | TCLAP::ValueArg blockSizeArg( "b", "block", "fs block size, in bytes", false, 4096, "number" ); 671 | TCLAP::SwitchArg addAllFilesArg( "a", "all-files", "when creating an image, include files which are normally ignored; currently only applies to '.DS_Store' files and '.git' directories", false); 672 | TCLAP::ValueArg debugArg( "d", "debug", "Debug level. 0 means no debug output.", false, 0, "0-5" ); 673 | 674 | cmd.add( imageSizeArg ); 675 | cmd.add( pageSizeArg ); 676 | cmd.add( blockSizeArg ); 677 | cmd.add( addAllFilesArg ); 678 | cmd.add( debugArg ); 679 | std::vector args = {&packArg, &unpackArg, &listArg, &visualizeArg}; 680 | cmd.xorAdd( args ); 681 | cmd.add( outNameArg ); 682 | cmd.parse( argc, argv ); 683 | 684 | if (debugArg.getValue() > 0) { 685 | std::cerr << "Debug output enabled" << std::endl; 686 | s_debugLevel = debugArg.getValue(); 687 | } 688 | 689 | if (packArg.isSet()) { 690 | s_dirName = packArg.getValue(); 691 | s_action = ACTION_PACK; 692 | } else if (unpackArg.isSet()) { 693 | s_dirName = unpackArg.getValue(); 694 | s_action = ACTION_UNPACK; 695 | } else if (listArg.isSet()) { 696 | s_action = ACTION_LIST; 697 | } else if (visualizeArg.isSet()) { 698 | s_action = ACTION_VISUALIZE; 699 | } 700 | 701 | s_imageName = outNameArg.getValue(); 702 | s_imageSize = imageSizeArg.getValue(); 703 | s_pageSize = pageSizeArg.getValue(); 704 | s_blockSize = blockSizeArg.getValue(); 705 | s_addAllFiles = addAllFilesArg.isSet(); 706 | } 707 | 708 | static int checkArgs() 709 | { 710 | // Argument checks don't use TCLAP's Constraint interface because 711 | // a) we need to check one argument against another, while Constraints only check 712 | // each argument individually, and b) image size might only be known when image 713 | // file is opened. 714 | 715 | if (s_imageSize < 0 || s_pageSize < 0 || s_blockSize < 0) { 716 | std::cerr << "error: Image, block, page sizes should not be negative" << std::endl; 717 | return 1; 718 | } 719 | 720 | if (s_imageSize % s_blockSize != 0) { 721 | std::cerr << "error: Image size should be a multiple of block size" << std::endl; 722 | return 1; 723 | } 724 | 725 | if (s_blockSize % s_pageSize != 0) { 726 | std::cerr << "error: Block size should be a multiple of page size" << std::endl; 727 | return 1; 728 | } 729 | 730 | const int physicalFlashEraseBlockSize = 4096; 731 | if (s_blockSize % physicalFlashEraseBlockSize != 0) { 732 | std::cerr << "error: Block size should be multiple of flash erase block size (" << 733 | physicalFlashEraseBlockSize << ")" << std::endl; 734 | return 1; 735 | } 736 | 737 | return 0; 738 | } 739 | 740 | int main(int argc, const char * argv[]) 741 | { 742 | 743 | try { 744 | processArgs(argc, argv); 745 | } catch (...) { 746 | std::cerr << "error: Invalid arguments" << std::endl; 747 | return 1; 748 | } 749 | 750 | switch (s_action) { 751 | case ACTION_PACK: 752 | return actionPack(); 753 | break; 754 | case ACTION_UNPACK: 755 | return actionUnpack(); 756 | break; 757 | case ACTION_LIST: 758 | return actionList(); 759 | break; 760 | case ACTION_VISUALIZE: 761 | return actionVisualize(); 762 | break; 763 | default: 764 | break; 765 | } 766 | 767 | return 1; 768 | } 769 | -------------------------------------------------------------------------------- /tclap/Arg.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: Arg.h 6 | * 7 | * Copyright (c) 2003, Michael E. Smoot . 8 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno . 9 | * All rights reverved. 10 | * 11 | * See the file COPYING in the top directory of this distribution for 12 | * more information. 13 | * 14 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | *****************************************************************************/ 23 | 24 | 25 | #ifndef TCLAP_ARGUMENT_H 26 | #define TCLAP_ARGUMENT_H 27 | 28 | #ifdef HAVE_CONFIG_H 29 | #include 30 | #else 31 | #define HAVE_SSTREAM 32 | #endif 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #if defined(HAVE_SSTREAM) 42 | #include 43 | typedef std::istringstream istringstream; 44 | #elif defined(HAVE_STRSTREAM) 45 | #include 46 | typedef std::istrstream istringstream; 47 | #else 48 | #error "Need a stringstream (sstream or strstream) to compile!" 49 | #endif 50 | 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | 57 | namespace TCLAP { 58 | 59 | /** 60 | * A virtual base class that defines the essential data for all arguments. 61 | * This class, or one of its existing children, must be subclassed to do 62 | * anything. 63 | */ 64 | class Arg 65 | { 66 | private: 67 | /** 68 | * Prevent accidental copying. 69 | */ 70 | Arg(const Arg& rhs); 71 | 72 | /** 73 | * Prevent accidental copying. 74 | */ 75 | Arg& operator=(const Arg& rhs); 76 | 77 | /** 78 | * Indicates whether the rest of the arguments should be ignored. 79 | */ 80 | static bool& ignoreRestRef() { static bool ign = false; return ign; } 81 | 82 | /** 83 | * The delimiter that separates an argument flag/name from the 84 | * value. 85 | */ 86 | static char& delimiterRef() { static char delim = ' '; return delim; } 87 | 88 | protected: 89 | 90 | /** 91 | * The single char flag used to identify the argument. 92 | * This value (preceded by a dash {-}), can be used to identify 93 | * an argument on the command line. The _flag can be blank, 94 | * in fact this is how unlabeled args work. Unlabeled args must 95 | * override appropriate functions to get correct handling. Note 96 | * that the _flag does NOT include the dash as part of the flag. 97 | */ 98 | std::string _flag; 99 | 100 | /** 101 | * A single work namd indentifying the argument. 102 | * This value (preceded by two dashed {--}) can also be used 103 | * to identify an argument on the command line. Note that the 104 | * _name does NOT include the two dashes as part of the _name. The 105 | * _name cannot be blank. 106 | */ 107 | std::string _name; 108 | 109 | /** 110 | * Description of the argument. 111 | */ 112 | std::string _description; 113 | 114 | /** 115 | * Indicating whether the argument is required. 116 | */ 117 | bool _required; 118 | 119 | /** 120 | * Label to be used in usage description. Normally set to 121 | * "required", but can be changed when necessary. 122 | */ 123 | std::string _requireLabel; 124 | 125 | /** 126 | * Indicates whether a value is required for the argument. 127 | * Note that the value may be required but the argument/value 128 | * combination may not be, as specified by _required. 129 | */ 130 | bool _valueRequired; 131 | 132 | /** 133 | * Indicates whether the argument has been set. 134 | * Indicates that a value on the command line has matched the 135 | * name/flag of this argument and the values have been set accordingly. 136 | */ 137 | bool _alreadySet; 138 | 139 | /** 140 | * A pointer to a vistitor object. 141 | * The visitor allows special handling to occur as soon as the 142 | * argument is matched. This defaults to NULL and should not 143 | * be used unless absolutely necessary. 144 | */ 145 | Visitor* _visitor; 146 | 147 | /** 148 | * Whether this argument can be ignored, if desired. 149 | */ 150 | bool _ignoreable; 151 | 152 | /** 153 | * Indicates that the arg was set as part of an XOR and not on the 154 | * command line. 155 | */ 156 | bool _xorSet; 157 | 158 | bool _acceptsMultipleValues; 159 | 160 | /** 161 | * Performs the special handling described by the Vistitor. 162 | */ 163 | void _checkWithVisitor() const; 164 | 165 | /** 166 | * Primary constructor. YOU (yes you) should NEVER construct an Arg 167 | * directly, this is a base class that is extended by various children 168 | * that are meant to be used. Use SwitchArg, ValueArg, MultiArg, 169 | * UnlabeledValueArg, or UnlabeledMultiArg instead. 170 | * 171 | * \param flag - The flag identifying the argument. 172 | * \param name - The name identifying the argument. 173 | * \param desc - The description of the argument, used in the usage. 174 | * \param req - Whether the argument is required. 175 | * \param valreq - Whether the a value is required for the argument. 176 | * \param v - The visitor checked by the argument. Defaults to NULL. 177 | */ 178 | Arg( const std::string& flag, 179 | const std::string& name, 180 | const std::string& desc, 181 | bool req, 182 | bool valreq, 183 | Visitor* v = NULL ); 184 | 185 | public: 186 | /** 187 | * Destructor. 188 | */ 189 | virtual ~Arg(); 190 | 191 | /** 192 | * Adds this to the specified list of Args. 193 | * \param argList - The list to add this to. 194 | */ 195 | virtual void addToList( std::list& argList ) const; 196 | 197 | /** 198 | * Begin ignoring arguments since the "--" argument was specified. 199 | */ 200 | static void beginIgnoring() { ignoreRestRef() = true; } 201 | 202 | /** 203 | * Whether to ignore the rest. 204 | */ 205 | static bool ignoreRest() { return ignoreRestRef(); } 206 | 207 | /** 208 | * The delimiter that separates an argument flag/name from the 209 | * value. 210 | */ 211 | static char delimiter() { return delimiterRef(); } 212 | 213 | /** 214 | * The char used as a place holder when SwitchArgs are combined. 215 | * Currently set to the bell char (ASCII 7). 216 | */ 217 | static char blankChar() { return (char)7; } 218 | 219 | /** 220 | * The char that indicates the beginning of a flag. Defaults to '-', but 221 | * clients can define TCLAP_FLAGSTARTCHAR to override. 222 | */ 223 | #ifndef TCLAP_FLAGSTARTCHAR 224 | #define TCLAP_FLAGSTARTCHAR '-' 225 | #endif 226 | static char flagStartChar() { return TCLAP_FLAGSTARTCHAR; } 227 | 228 | /** 229 | * The sting that indicates the beginning of a flag. Defaults to "-", but 230 | * clients can define TCLAP_FLAGSTARTSTRING to override. Should be the same 231 | * as TCLAP_FLAGSTARTCHAR. 232 | */ 233 | #ifndef TCLAP_FLAGSTARTSTRING 234 | #define TCLAP_FLAGSTARTSTRING "-" 235 | #endif 236 | static const std::string flagStartString() { return TCLAP_FLAGSTARTSTRING; } 237 | 238 | /** 239 | * The sting that indicates the beginning of a name. Defaults to "--", but 240 | * clients can define TCLAP_NAMESTARTSTRING to override. 241 | */ 242 | #ifndef TCLAP_NAMESTARTSTRING 243 | #define TCLAP_NAMESTARTSTRING "--" 244 | #endif 245 | static const std::string nameStartString() { return TCLAP_NAMESTARTSTRING; } 246 | 247 | /** 248 | * The name used to identify the ignore rest argument. 249 | */ 250 | static const std::string ignoreNameString() { return "ignore_rest"; } 251 | 252 | /** 253 | * Sets the delimiter for all arguments. 254 | * \param c - The character that delimits flags/names from values. 255 | */ 256 | static void setDelimiter( char c ) { delimiterRef() = c; } 257 | 258 | /** 259 | * Pure virtual method meant to handle the parsing and value assignment 260 | * of the string on the command line. 261 | * \param i - Pointer the the current argument in the list. 262 | * \param args - Mutable list of strings. What is 263 | * passed in from main. 264 | */ 265 | virtual bool processArg(int *i, std::vector& args) = 0; 266 | 267 | /** 268 | * Operator ==. 269 | * Equality operator. Must be virtual to handle unlabeled args. 270 | * \param a - The Arg to be compared to this. 271 | */ 272 | virtual bool operator==(const Arg& a) const; 273 | 274 | /** 275 | * Returns the argument flag. 276 | */ 277 | const std::string& getFlag() const; 278 | 279 | /** 280 | * Returns the argument name. 281 | */ 282 | const std::string& getName() const; 283 | 284 | /** 285 | * Returns the argument description. 286 | */ 287 | std::string getDescription() const; 288 | 289 | /** 290 | * Indicates whether the argument is required. 291 | */ 292 | virtual bool isRequired() const; 293 | 294 | /** 295 | * Sets _required to true. This is used by the XorHandler. 296 | * You really have no reason to ever use it. 297 | */ 298 | void forceRequired(); 299 | 300 | /** 301 | * Sets the _alreadySet value to true. This is used by the XorHandler. 302 | * You really have no reason to ever use it. 303 | */ 304 | void xorSet(); 305 | 306 | /** 307 | * Indicates whether a value must be specified for argument. 308 | */ 309 | bool isValueRequired() const; 310 | 311 | /** 312 | * Indicates whether the argument has already been set. Only true 313 | * if the arg has been matched on the command line. 314 | */ 315 | bool isSet() const; 316 | 317 | /** 318 | * Indicates whether the argument can be ignored, if desired. 319 | */ 320 | bool isIgnoreable() const; 321 | 322 | /** 323 | * A method that tests whether a string matches this argument. 324 | * This is generally called by the processArg() method. This 325 | * method could be re-implemented by a child to change how 326 | * arguments are specified on the command line. 327 | * \param s - The string to be compared to the flag/name to determine 328 | * whether the arg matches. 329 | */ 330 | virtual bool argMatches( const std::string& s ) const; 331 | 332 | /** 333 | * Returns a simple string representation of the argument. 334 | * Primarily for debugging. 335 | */ 336 | virtual std::string toString() const; 337 | 338 | /** 339 | * Returns a short ID for the usage. 340 | * \param valueId - The value used in the id. 341 | */ 342 | virtual std::string shortID( const std::string& valueId = "val" ) const; 343 | 344 | /** 345 | * Returns a long ID for the usage. 346 | * \param valueId - The value used in the id. 347 | */ 348 | virtual std::string longID( const std::string& valueId = "val" ) const; 349 | 350 | /** 351 | * Trims a value off of the flag. 352 | * \param flag - The string from which the flag and value will be 353 | * trimmed. Contains the flag once the value has been trimmed. 354 | * \param value - Where the value trimmed from the string will 355 | * be stored. 356 | */ 357 | virtual void trimFlag( std::string& flag, std::string& value ) const; 358 | 359 | /** 360 | * Checks whether a given string has blank chars, indicating that 361 | * it is a combined SwitchArg. If so, return true, otherwise return 362 | * false. 363 | * \param s - string to be checked. 364 | */ 365 | bool _hasBlanks( const std::string& s ) const; 366 | 367 | /** 368 | * Sets the requireLabel. Used by XorHandler. You shouldn't ever 369 | * use this. 370 | * \param s - Set the requireLabel to this value. 371 | */ 372 | void setRequireLabel( const std::string& s ); 373 | 374 | /** 375 | * Used for MultiArgs and XorHandler to determine whether args 376 | * can still be set. 377 | */ 378 | virtual bool allowMore(); 379 | 380 | /** 381 | * Use by output classes to determine whether an Arg accepts 382 | * multiple values. 383 | */ 384 | virtual bool acceptsMultipleValues(); 385 | 386 | /** 387 | * Clears the Arg object and allows it to be reused by new 388 | * command lines. 389 | */ 390 | virtual void reset(); 391 | }; 392 | 393 | /** 394 | * Typedef of an Arg list iterator. 395 | */ 396 | typedef std::list::iterator ArgListIterator; 397 | 398 | /** 399 | * Typedef of an Arg vector iterator. 400 | */ 401 | typedef std::vector::iterator ArgVectorIterator; 402 | 403 | /** 404 | * Typedef of a Visitor list iterator. 405 | */ 406 | typedef std::list::iterator VisitorListIterator; 407 | 408 | /* 409 | * Extract a value of type T from it's string representation contained 410 | * in strVal. The ValueLike parameter used to select the correct 411 | * specialization of ExtractValue depending on the value traits of T. 412 | * ValueLike traits use operator>> to assign the value from strVal. 413 | */ 414 | template void 415 | ExtractValue(T &destVal, const std::string& strVal, ValueLike vl) 416 | { 417 | static_cast(vl); // Avoid warning about unused vl 418 | std::istringstream is(strVal); 419 | 420 | int valuesRead = 0; 421 | while ( is.good() ) { 422 | if ( is.peek() != EOF ) 423 | #ifdef TCLAP_SETBASE_ZERO 424 | is >> std::setbase(0) >> destVal; 425 | #else 426 | is >> destVal; 427 | #endif 428 | else 429 | break; 430 | 431 | valuesRead++; 432 | } 433 | 434 | if ( is.fail() ) 435 | throw( ArgParseException("Couldn't read argument value " 436 | "from string '" + strVal + "'")); 437 | 438 | 439 | if ( valuesRead > 1 ) 440 | throw( ArgParseException("More than one valid value parsed from " 441 | "string '" + strVal + "'")); 442 | 443 | } 444 | 445 | /* 446 | * Extract a value of type T from it's string representation contained 447 | * in strVal. The ValueLike parameter used to select the correct 448 | * specialization of ExtractValue depending on the value traits of T. 449 | * StringLike uses assignment (operator=) to assign from strVal. 450 | */ 451 | template void 452 | ExtractValue(T &destVal, const std::string& strVal, StringLike sl) 453 | { 454 | static_cast(sl); // Avoid warning about unused sl 455 | SetString(destVal, strVal); 456 | } 457 | 458 | ////////////////////////////////////////////////////////////////////// 459 | //BEGIN Arg.cpp 460 | ////////////////////////////////////////////////////////////////////// 461 | 462 | inline Arg::Arg(const std::string& flag, 463 | const std::string& name, 464 | const std::string& desc, 465 | bool req, 466 | bool valreq, 467 | Visitor* v) : 468 | _flag(flag), 469 | _name(name), 470 | _description(desc), 471 | _required(req), 472 | _requireLabel("required"), 473 | _valueRequired(valreq), 474 | _alreadySet(false), 475 | _visitor( v ), 476 | _ignoreable(true), 477 | _xorSet(false), 478 | _acceptsMultipleValues(false) 479 | { 480 | if ( _flag.length() > 1 ) 481 | throw(SpecificationException( 482 | "Argument flag can only be one character long", toString() ) ); 483 | 484 | if ( _name != ignoreNameString() && 485 | ( _flag == Arg::flagStartString() || 486 | _flag == Arg::nameStartString() || 487 | _flag == " " ) ) 488 | throw(SpecificationException("Argument flag cannot be either '" + 489 | Arg::flagStartString() + "' or '" + 490 | Arg::nameStartString() + "' or a space.", 491 | toString() ) ); 492 | 493 | if ( ( _name.substr( 0, Arg::flagStartString().length() ) == Arg::flagStartString() ) || 494 | ( _name.substr( 0, Arg::nameStartString().length() ) == Arg::nameStartString() ) || 495 | ( _name.find( " ", 0 ) != std::string::npos ) ) 496 | throw(SpecificationException("Argument name begin with either '" + 497 | Arg::flagStartString() + "' or '" + 498 | Arg::nameStartString() + "' or space.", 499 | toString() ) ); 500 | 501 | } 502 | 503 | inline Arg::~Arg() { } 504 | 505 | inline std::string Arg::shortID( const std::string& valueId ) const 506 | { 507 | std::string id = ""; 508 | 509 | if ( _flag != "" ) 510 | id = Arg::flagStartString() + _flag; 511 | else 512 | id = Arg::nameStartString() + _name; 513 | 514 | if ( _valueRequired ) 515 | id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; 516 | 517 | if ( !_required ) 518 | id = "[" + id + "]"; 519 | 520 | return id; 521 | } 522 | 523 | inline std::string Arg::longID( const std::string& valueId ) const 524 | { 525 | std::string id = ""; 526 | 527 | if ( _flag != "" ) 528 | { 529 | id += Arg::flagStartString() + _flag; 530 | 531 | if ( _valueRequired ) 532 | id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; 533 | 534 | id += ", "; 535 | } 536 | 537 | id += Arg::nameStartString() + _name; 538 | 539 | if ( _valueRequired ) 540 | id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; 541 | 542 | return id; 543 | 544 | } 545 | 546 | inline bool Arg::operator==(const Arg& a) const 547 | { 548 | if ( ( _flag != "" && _flag == a._flag ) || _name == a._name) 549 | return true; 550 | else 551 | return false; 552 | } 553 | 554 | inline std::string Arg::getDescription() const 555 | { 556 | std::string desc = ""; 557 | if ( _required ) 558 | desc = "(" + _requireLabel + ") "; 559 | 560 | // if ( _valueRequired ) 561 | // desc += "(value required) "; 562 | 563 | desc += _description; 564 | return desc; 565 | } 566 | 567 | inline const std::string& Arg::getFlag() const { return _flag; } 568 | 569 | inline const std::string& Arg::getName() const { return _name; } 570 | 571 | inline bool Arg::isRequired() const { return _required; } 572 | 573 | inline bool Arg::isValueRequired() const { return _valueRequired; } 574 | 575 | inline bool Arg::isSet() const 576 | { 577 | if ( _alreadySet && !_xorSet ) 578 | return true; 579 | else 580 | return false; 581 | } 582 | 583 | inline bool Arg::isIgnoreable() const { return _ignoreable; } 584 | 585 | inline void Arg::setRequireLabel( const std::string& s) 586 | { 587 | _requireLabel = s; 588 | } 589 | 590 | inline bool Arg::argMatches( const std::string& argFlag ) const 591 | { 592 | if ( ( argFlag == Arg::flagStartString() + _flag && _flag != "" ) || 593 | argFlag == Arg::nameStartString() + _name ) 594 | return true; 595 | else 596 | return false; 597 | } 598 | 599 | inline std::string Arg::toString() const 600 | { 601 | std::string s = ""; 602 | 603 | if ( _flag != "" ) 604 | s += Arg::flagStartString() + _flag + " "; 605 | 606 | s += "(" + Arg::nameStartString() + _name + ")"; 607 | 608 | return s; 609 | } 610 | 611 | inline void Arg::_checkWithVisitor() const 612 | { 613 | if ( _visitor != NULL ) 614 | _visitor->visit(); 615 | } 616 | 617 | /** 618 | * Implementation of trimFlag. 619 | */ 620 | inline void Arg::trimFlag(std::string& flag, std::string& value) const 621 | { 622 | int stop = 0; 623 | for ( int i = 0; static_cast(i) < flag.length(); i++ ) 624 | if ( flag[i] == Arg::delimiter() ) 625 | { 626 | stop = i; 627 | break; 628 | } 629 | 630 | if ( stop > 1 ) 631 | { 632 | value = flag.substr(stop+1); 633 | flag = flag.substr(0,stop); 634 | } 635 | 636 | } 637 | 638 | /** 639 | * Implementation of _hasBlanks. 640 | */ 641 | inline bool Arg::_hasBlanks( const std::string& s ) const 642 | { 643 | for ( int i = 1; static_cast(i) < s.length(); i++ ) 644 | if ( s[i] == Arg::blankChar() ) 645 | return true; 646 | 647 | return false; 648 | } 649 | 650 | inline void Arg::forceRequired() 651 | { 652 | _required = true; 653 | } 654 | 655 | inline void Arg::xorSet() 656 | { 657 | _alreadySet = true; 658 | _xorSet = true; 659 | } 660 | 661 | /** 662 | * Overridden by Args that need to added to the end of the list. 663 | */ 664 | inline void Arg::addToList( std::list& argList ) const 665 | { 666 | argList.push_front( const_cast(this) ); 667 | } 668 | 669 | inline bool Arg::allowMore() 670 | { 671 | return false; 672 | } 673 | 674 | inline bool Arg::acceptsMultipleValues() 675 | { 676 | return _acceptsMultipleValues; 677 | } 678 | 679 | inline void Arg::reset() 680 | { 681 | _xorSet = false; 682 | _alreadySet = false; 683 | } 684 | 685 | ////////////////////////////////////////////////////////////////////// 686 | //END Arg.cpp 687 | ////////////////////////////////////////////////////////////////////// 688 | 689 | } //namespace TCLAP 690 | 691 | #endif 692 | 693 | -------------------------------------------------------------------------------- /tclap/ArgException.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: ArgException.h 6 | * 7 | * Copyright (c) 2003, Michael E. Smoot . 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | 24 | #ifndef TCLAP_ARG_EXCEPTION_H 25 | #define TCLAP_ARG_EXCEPTION_H 26 | 27 | #include 28 | #include 29 | 30 | namespace TCLAP { 31 | 32 | /** 33 | * A simple class that defines and argument exception. Should be caught 34 | * whenever a CmdLine is created and parsed. 35 | */ 36 | class ArgException : public std::exception 37 | { 38 | public: 39 | 40 | /** 41 | * Constructor. 42 | * \param text - The text of the exception. 43 | * \param id - The text identifying the argument source. 44 | * \param td - Text describing the type of ArgException it is. 45 | * of the exception. 46 | */ 47 | ArgException( const std::string& text = "undefined exception", 48 | const std::string& id = "undefined", 49 | const std::string& td = "Generic ArgException") 50 | : std::exception(), 51 | _errorText(text), 52 | _argId( id ), 53 | _typeDescription(td) 54 | { } 55 | 56 | /** 57 | * Destructor. 58 | */ 59 | virtual ~ArgException() throw() { } 60 | 61 | /** 62 | * Returns the error text. 63 | */ 64 | std::string error() const { return ( _errorText ); } 65 | 66 | /** 67 | * Returns the argument id. 68 | */ 69 | std::string argId() const 70 | { 71 | if ( _argId == "undefined" ) 72 | return " "; 73 | else 74 | return ( "Argument: " + _argId ); 75 | } 76 | 77 | /** 78 | * Returns the arg id and error text. 79 | */ 80 | const char* what() const throw() 81 | { 82 | static std::string ex; 83 | ex = _argId + " -- " + _errorText; 84 | return ex.c_str(); 85 | } 86 | 87 | /** 88 | * Returns the type of the exception. Used to explain and distinguish 89 | * between different child exceptions. 90 | */ 91 | std::string typeDescription() const 92 | { 93 | return _typeDescription; 94 | } 95 | 96 | 97 | private: 98 | 99 | /** 100 | * The text of the exception message. 101 | */ 102 | std::string _errorText; 103 | 104 | /** 105 | * The argument related to this exception. 106 | */ 107 | std::string _argId; 108 | 109 | /** 110 | * Describes the type of the exception. Used to distinguish 111 | * between different child exceptions. 112 | */ 113 | std::string _typeDescription; 114 | 115 | }; 116 | 117 | /** 118 | * Thrown from within the child Arg classes when it fails to properly 119 | * parse the argument it has been passed. 120 | */ 121 | class ArgParseException : public ArgException 122 | { 123 | public: 124 | /** 125 | * Constructor. 126 | * \param text - The text of the exception. 127 | * \param id - The text identifying the argument source 128 | * of the exception. 129 | */ 130 | ArgParseException( const std::string& text = "undefined exception", 131 | const std::string& id = "undefined" ) 132 | : ArgException( text, 133 | id, 134 | std::string( "Exception found while parsing " ) + 135 | std::string( "the value the Arg has been passed." )) 136 | { } 137 | }; 138 | 139 | /** 140 | * Thrown from CmdLine when the arguments on the command line are not 141 | * properly specified, e.g. too many arguments, required argument missing, etc. 142 | */ 143 | class CmdLineParseException : public ArgException 144 | { 145 | public: 146 | /** 147 | * Constructor. 148 | * \param text - The text of the exception. 149 | * \param id - The text identifying the argument source 150 | * of the exception. 151 | */ 152 | CmdLineParseException( const std::string& text = "undefined exception", 153 | const std::string& id = "undefined" ) 154 | : ArgException( text, 155 | id, 156 | std::string( "Exception found when the values ") + 157 | std::string( "on the command line do not meet ") + 158 | std::string( "the requirements of the defined ") + 159 | std::string( "Args." )) 160 | { } 161 | }; 162 | 163 | /** 164 | * Thrown from Arg and CmdLine when an Arg is improperly specified, e.g. 165 | * same flag as another Arg, same name, etc. 166 | */ 167 | class SpecificationException : public ArgException 168 | { 169 | public: 170 | /** 171 | * Constructor. 172 | * \param text - The text of the exception. 173 | * \param id - The text identifying the argument source 174 | * of the exception. 175 | */ 176 | SpecificationException( const std::string& text = "undefined exception", 177 | const std::string& id = "undefined" ) 178 | : ArgException( text, 179 | id, 180 | std::string("Exception found when an Arg object ")+ 181 | std::string("is improperly defined by the ") + 182 | std::string("developer." )) 183 | { } 184 | 185 | }; 186 | 187 | class ExitException { 188 | public: 189 | ExitException(int estat) : _estat(estat) {} 190 | 191 | int getExitStatus() const { return _estat; } 192 | 193 | private: 194 | int _estat; 195 | }; 196 | 197 | } // namespace TCLAP 198 | 199 | #endif 200 | 201 | -------------------------------------------------------------------------------- /tclap/ArgTraits.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: ArgTraits.h 6 | * 7 | * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | // This is an internal tclap file, you should probably not have to 24 | // include this directly 25 | 26 | #ifndef TCLAP_ARGTRAITS_H 27 | #define TCLAP_ARGTRAITS_H 28 | 29 | namespace TCLAP { 30 | 31 | // We use two empty structs to get compile type specialization 32 | // function to work 33 | 34 | /** 35 | * A value like argument value type is a value that can be set using 36 | * operator>>. This is the default value type. 37 | */ 38 | struct ValueLike { 39 | typedef ValueLike ValueCategory; 40 | virtual ~ValueLike() {} 41 | }; 42 | 43 | /** 44 | * A string like argument value type is a value that can be set using 45 | * operator=(string). Usefull if the value type contains spaces which 46 | * will be broken up into individual tokens by operator>>. 47 | */ 48 | struct StringLike { 49 | virtual ~StringLike() {} 50 | }; 51 | 52 | /** 53 | * A class can inherit from this object to make it have string like 54 | * traits. This is a compile time thing and does not add any overhead 55 | * to the inherenting class. 56 | */ 57 | struct StringLikeTrait { 58 | typedef StringLike ValueCategory; 59 | virtual ~StringLikeTrait() {} 60 | }; 61 | 62 | /** 63 | * A class can inherit from this object to make it have value like 64 | * traits. This is a compile time thing and does not add any overhead 65 | * to the inherenting class. 66 | */ 67 | struct ValueLikeTrait { 68 | typedef ValueLike ValueCategory; 69 | virtual ~ValueLikeTrait() {} 70 | }; 71 | 72 | /** 73 | * Arg traits are used to get compile type specialization when parsing 74 | * argument values. Using an ArgTraits you can specify the way that 75 | * values gets assigned to any particular type during parsing. The two 76 | * supported types are StringLike and ValueLike. 77 | */ 78 | template 79 | struct ArgTraits { 80 | typedef typename T::ValueCategory ValueCategory; 81 | virtual ~ArgTraits() {} 82 | //typedef ValueLike ValueCategory; 83 | }; 84 | 85 | #endif 86 | 87 | } // namespace 88 | -------------------------------------------------------------------------------- /tclap/COPYING: -------------------------------------------------------------------------------- 1 | 2 | 3 | Copyright (c) 2003 Michael E. Smoot 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without restriction, 8 | including without limitation the rights to use, copy, modify, merge, 9 | publish, distribute, sublicense, and/or sell copies of the Software, 10 | and to permit persons to whom the Software is furnished to do so, 11 | subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | 25 | 26 | -------------------------------------------------------------------------------- /tclap/CmdLine.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: CmdLine.h 6 | * 7 | * Copyright (c) 2003, Michael E. Smoot . 8 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 9 | * All rights reverved. 10 | * 11 | * See the file COPYING in the top directory of this distribution for 12 | * more information. 13 | * 14 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | *****************************************************************************/ 23 | 24 | #ifndef TCLAP_CMDLINE_H 25 | #define TCLAP_CMDLINE_H 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | 40 | #include 41 | #include 42 | 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include // Needed for exit(), which isn't defined in some envs. 50 | 51 | namespace TCLAP { 52 | 53 | template void DelPtr(T ptr) 54 | { 55 | delete ptr; 56 | } 57 | 58 | template void ClearContainer(C &c) 59 | { 60 | typedef typename C::value_type value_type; 61 | std::for_each(c.begin(), c.end(), DelPtr); 62 | c.clear(); 63 | } 64 | 65 | 66 | /** 67 | * The base class that manages the command line definition and passes 68 | * along the parsing to the appropriate Arg classes. 69 | */ 70 | class CmdLine : public CmdLineInterface 71 | { 72 | protected: 73 | 74 | /** 75 | * The list of arguments that will be tested against the 76 | * command line. 77 | */ 78 | std::list _argList; 79 | 80 | /** 81 | * The name of the program. Set to argv[0]. 82 | */ 83 | std::string _progName; 84 | 85 | /** 86 | * A message used to describe the program. Used in the usage output. 87 | */ 88 | std::string _message; 89 | 90 | /** 91 | * The version to be displayed with the --version switch. 92 | */ 93 | std::string _version; 94 | 95 | /** 96 | * The number of arguments that are required to be present on 97 | * the command line. This is set dynamically, based on the 98 | * Args added to the CmdLine object. 99 | */ 100 | int _numRequired; 101 | 102 | /** 103 | * The character that is used to separate the argument flag/name 104 | * from the value. Defaults to ' ' (space). 105 | */ 106 | char _delimiter; 107 | 108 | /** 109 | * The handler that manages xoring lists of args. 110 | */ 111 | XorHandler _xorHandler; 112 | 113 | /** 114 | * A list of Args to be explicitly deleted when the destructor 115 | * is called. At the moment, this only includes the three default 116 | * Args. 117 | */ 118 | std::list _argDeleteOnExitList; 119 | 120 | /** 121 | * A list of Visitors to be explicitly deleted when the destructor 122 | * is called. At the moment, these are the Vistors created for the 123 | * default Args. 124 | */ 125 | std::list _visitorDeleteOnExitList; 126 | 127 | /** 128 | * Object that handles all output for the CmdLine. 129 | */ 130 | CmdLineOutput* _output; 131 | 132 | /** 133 | * Should CmdLine handle parsing exceptions internally? 134 | */ 135 | bool _handleExceptions; 136 | 137 | /** 138 | * Throws an exception listing the missing args. 139 | */ 140 | void missingArgsException(); 141 | 142 | /** 143 | * Checks whether a name/flag string matches entirely matches 144 | * the Arg::blankChar. Used when multiple switches are combined 145 | * into a single argument. 146 | * \param s - The message to be used in the usage. 147 | */ 148 | bool _emptyCombined(const std::string& s); 149 | 150 | /** 151 | * Perform a delete ptr; operation on ptr when this object is deleted. 152 | */ 153 | void deleteOnExit(Arg* ptr); 154 | 155 | /** 156 | * Perform a delete ptr; operation on ptr when this object is deleted. 157 | */ 158 | void deleteOnExit(Visitor* ptr); 159 | 160 | private: 161 | 162 | /** 163 | * Prevent accidental copying. 164 | */ 165 | CmdLine(const CmdLine& rhs); 166 | CmdLine& operator=(const CmdLine& rhs); 167 | 168 | /** 169 | * Encapsulates the code common to the constructors 170 | * (which is all of it). 171 | */ 172 | void _constructor(); 173 | 174 | 175 | /** 176 | * Is set to true when a user sets the output object. We use this so 177 | * that we don't delete objects that are created outside of this lib. 178 | */ 179 | bool _userSetOutput; 180 | 181 | /** 182 | * Whether or not to automatically create help and version switches. 183 | */ 184 | bool _helpAndVersion; 185 | 186 | public: 187 | 188 | /** 189 | * Command line constructor. Defines how the arguments will be 190 | * parsed. 191 | * \param message - The message to be used in the usage 192 | * output. 193 | * \param delimiter - The character that is used to separate 194 | * the argument flag/name from the value. Defaults to ' ' (space). 195 | * \param version - The version number to be used in the 196 | * --version switch. 197 | * \param helpAndVersion - Whether or not to create the Help and 198 | * Version switches. Defaults to true. 199 | */ 200 | CmdLine(const std::string& message, 201 | const char delimiter = ' ', 202 | const std::string& version = "none", 203 | bool helpAndVersion = true); 204 | 205 | /** 206 | * Deletes any resources allocated by a CmdLine object. 207 | */ 208 | virtual ~CmdLine(); 209 | 210 | /** 211 | * Adds an argument to the list of arguments to be parsed. 212 | * \param a - Argument to be added. 213 | */ 214 | void add( Arg& a ); 215 | 216 | /** 217 | * An alternative add. Functionally identical. 218 | * \param a - Argument to be added. 219 | */ 220 | void add( Arg* a ); 221 | 222 | /** 223 | * Add two Args that will be xor'd. If this method is used, add does 224 | * not need to be called. 225 | * \param a - Argument to be added and xor'd. 226 | * \param b - Argument to be added and xor'd. 227 | */ 228 | void xorAdd( Arg& a, Arg& b ); 229 | 230 | /** 231 | * Add a list of Args that will be xor'd. If this method is used, 232 | * add does not need to be called. 233 | * \param xors - List of Args to be added and xor'd. 234 | */ 235 | void xorAdd( std::vector& xors ); 236 | 237 | /** 238 | * Parses the command line. 239 | * \param argc - Number of arguments. 240 | * \param argv - Array of arguments. 241 | */ 242 | void parse(int argc, const char * const * argv); 243 | 244 | /** 245 | * Parses the command line. 246 | * \param args - A vector of strings representing the args. 247 | * args[0] is still the program name. 248 | */ 249 | void parse(std::vector& args); 250 | 251 | /** 252 | * 253 | */ 254 | CmdLineOutput* getOutput(); 255 | 256 | /** 257 | * 258 | */ 259 | void setOutput(CmdLineOutput* co); 260 | 261 | /** 262 | * 263 | */ 264 | std::string& getVersion(); 265 | 266 | /** 267 | * 268 | */ 269 | std::string& getProgramName(); 270 | 271 | /** 272 | * 273 | */ 274 | std::list& getArgList(); 275 | 276 | /** 277 | * 278 | */ 279 | XorHandler& getXorHandler(); 280 | 281 | /** 282 | * 283 | */ 284 | char getDelimiter(); 285 | 286 | /** 287 | * 288 | */ 289 | std::string& getMessage(); 290 | 291 | /** 292 | * 293 | */ 294 | bool hasHelpAndVersion(); 295 | 296 | /** 297 | * Disables or enables CmdLine's internal parsing exception handling. 298 | * 299 | * @param state Should CmdLine handle parsing exceptions internally? 300 | */ 301 | void setExceptionHandling(const bool state); 302 | 303 | /** 304 | * Returns the current state of the internal exception handling. 305 | * 306 | * @retval true Parsing exceptions are handled internally. 307 | * @retval false Parsing exceptions are propagated to the caller. 308 | */ 309 | bool getExceptionHandling() const; 310 | 311 | /** 312 | * Allows the CmdLine object to be reused. 313 | */ 314 | void reset(); 315 | 316 | }; 317 | 318 | 319 | /////////////////////////////////////////////////////////////////////////////// 320 | //Begin CmdLine.cpp 321 | /////////////////////////////////////////////////////////////////////////////// 322 | 323 | inline CmdLine::CmdLine(const std::string& m, 324 | char delim, 325 | const std::string& v, 326 | bool help ) 327 | : 328 | _argList(std::list()), 329 | _progName("not_set_yet"), 330 | _message(m), 331 | _version(v), 332 | _numRequired(0), 333 | _delimiter(delim), 334 | _xorHandler(XorHandler()), 335 | _argDeleteOnExitList(std::list()), 336 | _visitorDeleteOnExitList(std::list()), 337 | _output(0), 338 | _handleExceptions(true), 339 | _userSetOutput(false), 340 | _helpAndVersion(help) 341 | { 342 | _constructor(); 343 | } 344 | 345 | inline CmdLine::~CmdLine() 346 | { 347 | ClearContainer(_argDeleteOnExitList); 348 | ClearContainer(_visitorDeleteOnExitList); 349 | 350 | if ( !_userSetOutput ) { 351 | delete _output; 352 | _output = 0; 353 | } 354 | } 355 | 356 | inline void CmdLine::_constructor() 357 | { 358 | _output = new StdOutput; 359 | 360 | Arg::setDelimiter( _delimiter ); 361 | 362 | Visitor* v; 363 | 364 | if ( _helpAndVersion ) 365 | { 366 | v = new HelpVisitor( this, &_output ); 367 | SwitchArg* help = new SwitchArg("h","help", 368 | "Displays usage information and exits.", 369 | false, v); 370 | add( help ); 371 | deleteOnExit(help); 372 | deleteOnExit(v); 373 | 374 | v = new VersionVisitor( this, &_output ); 375 | SwitchArg* vers = new SwitchArg("","version", 376 | "Displays version information and exits.", 377 | false, v); 378 | add( vers ); 379 | deleteOnExit(vers); 380 | deleteOnExit(v); 381 | } 382 | 383 | v = new IgnoreRestVisitor(); 384 | SwitchArg* ignore = new SwitchArg(Arg::flagStartString(), 385 | Arg::ignoreNameString(), 386 | "Ignores the rest of the labeled arguments following this flag.", 387 | false, v); 388 | add( ignore ); 389 | deleteOnExit(ignore); 390 | deleteOnExit(v); 391 | } 392 | 393 | inline void CmdLine::xorAdd( std::vector& ors ) 394 | { 395 | _xorHandler.add( ors ); 396 | 397 | for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++) 398 | { 399 | (*it)->forceRequired(); 400 | (*it)->setRequireLabel( "OR required" ); 401 | add( *it ); 402 | } 403 | } 404 | 405 | inline void CmdLine::xorAdd( Arg& a, Arg& b ) 406 | { 407 | std::vector ors; 408 | ors.push_back( &a ); 409 | ors.push_back( &b ); 410 | xorAdd( ors ); 411 | } 412 | 413 | inline void CmdLine::add( Arg& a ) 414 | { 415 | add( &a ); 416 | } 417 | 418 | inline void CmdLine::add( Arg* a ) 419 | { 420 | for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ ) 421 | if ( *a == *(*it) ) 422 | throw( SpecificationException( 423 | "Argument with same flag/name already exists!", 424 | a->longID() ) ); 425 | 426 | a->addToList( _argList ); 427 | 428 | if ( a->isRequired() ) 429 | _numRequired++; 430 | } 431 | 432 | 433 | inline void CmdLine::parse(int argc, const char * const * argv) 434 | { 435 | // this step is necessary so that we have easy access to 436 | // mutable strings. 437 | std::vector args; 438 | for (int i = 0; i < argc; i++) 439 | args.push_back(argv[i]); 440 | 441 | parse(args); 442 | } 443 | 444 | inline void CmdLine::parse(std::vector& args) 445 | { 446 | bool shouldExit = false; 447 | int estat = 0; 448 | 449 | try { 450 | _progName = args.front(); 451 | args.erase(args.begin()); 452 | 453 | int requiredCount = 0; 454 | 455 | for (int i = 0; static_cast(i) < args.size(); i++) 456 | { 457 | bool matched = false; 458 | for (ArgListIterator it = _argList.begin(); 459 | it != _argList.end(); it++) { 460 | if ( (*it)->processArg( &i, args ) ) 461 | { 462 | requiredCount += _xorHandler.check( *it ); 463 | matched = true; 464 | break; 465 | } 466 | } 467 | 468 | // checks to see if the argument is an empty combined 469 | // switch and if so, then we've actually matched it 470 | if ( !matched && _emptyCombined( args[i] ) ) 471 | matched = true; 472 | 473 | if ( !matched && !Arg::ignoreRest() ) 474 | throw(CmdLineParseException("Couldn't find match " 475 | "for argument", 476 | args[i])); 477 | } 478 | 479 | if ( requiredCount < _numRequired ) 480 | missingArgsException(); 481 | 482 | if ( requiredCount > _numRequired ) 483 | throw(CmdLineParseException("Too many arguments!")); 484 | 485 | } catch ( ArgException& e ) { 486 | // If we're not handling the exceptions, rethrow. 487 | if ( !_handleExceptions) { 488 | throw; 489 | } 490 | 491 | try { 492 | _output->failure(*this,e); 493 | } catch ( ExitException &ee ) { 494 | estat = ee.getExitStatus(); 495 | shouldExit = true; 496 | } 497 | } catch (ExitException &ee) { 498 | // If we're not handling the exceptions, rethrow. 499 | if ( !_handleExceptions) { 500 | throw; 501 | } 502 | 503 | estat = ee.getExitStatus(); 504 | shouldExit = true; 505 | } 506 | 507 | if (shouldExit) 508 | exit(estat); 509 | } 510 | 511 | inline bool CmdLine::_emptyCombined(const std::string& s) 512 | { 513 | if ( s.length() > 0 && s[0] != Arg::flagStartChar() ) 514 | return false; 515 | 516 | for ( int i = 1; static_cast(i) < s.length(); i++ ) 517 | if ( s[i] != Arg::blankChar() ) 518 | return false; 519 | 520 | return true; 521 | } 522 | 523 | inline void CmdLine::missingArgsException() 524 | { 525 | int count = 0; 526 | 527 | std::string missingArgList; 528 | for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++) 529 | { 530 | if ( (*it)->isRequired() && !(*it)->isSet() ) 531 | { 532 | missingArgList += (*it)->getName(); 533 | missingArgList += ", "; 534 | count++; 535 | } 536 | } 537 | missingArgList = missingArgList.substr(0,missingArgList.length()-2); 538 | 539 | std::string msg; 540 | if ( count > 1 ) 541 | msg = "Required arguments missing: "; 542 | else 543 | msg = "Required argument missing: "; 544 | 545 | msg += missingArgList; 546 | 547 | throw(CmdLineParseException(msg)); 548 | } 549 | 550 | inline void CmdLine::deleteOnExit(Arg* ptr) 551 | { 552 | _argDeleteOnExitList.push_back(ptr); 553 | } 554 | 555 | inline void CmdLine::deleteOnExit(Visitor* ptr) 556 | { 557 | _visitorDeleteOnExitList.push_back(ptr); 558 | } 559 | 560 | inline CmdLineOutput* CmdLine::getOutput() 561 | { 562 | return _output; 563 | } 564 | 565 | inline void CmdLine::setOutput(CmdLineOutput* co) 566 | { 567 | if ( !_userSetOutput ) 568 | delete _output; 569 | _userSetOutput = true; 570 | _output = co; 571 | } 572 | 573 | inline std::string& CmdLine::getVersion() 574 | { 575 | return _version; 576 | } 577 | 578 | inline std::string& CmdLine::getProgramName() 579 | { 580 | return _progName; 581 | } 582 | 583 | inline std::list& CmdLine::getArgList() 584 | { 585 | return _argList; 586 | } 587 | 588 | inline XorHandler& CmdLine::getXorHandler() 589 | { 590 | return _xorHandler; 591 | } 592 | 593 | inline char CmdLine::getDelimiter() 594 | { 595 | return _delimiter; 596 | } 597 | 598 | inline std::string& CmdLine::getMessage() 599 | { 600 | return _message; 601 | } 602 | 603 | inline bool CmdLine::hasHelpAndVersion() 604 | { 605 | return _helpAndVersion; 606 | } 607 | 608 | inline void CmdLine::setExceptionHandling(const bool state) 609 | { 610 | _handleExceptions = state; 611 | } 612 | 613 | inline bool CmdLine::getExceptionHandling() const 614 | { 615 | return _handleExceptions; 616 | } 617 | 618 | inline void CmdLine::reset() 619 | { 620 | for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ ) 621 | (*it)->reset(); 622 | 623 | _progName.clear(); 624 | } 625 | 626 | /////////////////////////////////////////////////////////////////////////////// 627 | //End CmdLine.cpp 628 | /////////////////////////////////////////////////////////////////////////////// 629 | 630 | 631 | 632 | } //namespace TCLAP 633 | #endif 634 | -------------------------------------------------------------------------------- /tclap/CmdLineInterface.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: CmdLineInterface.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_COMMANDLINE_INTERFACE_H 24 | #define TCLAP_COMMANDLINE_INTERFACE_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | 33 | namespace TCLAP { 34 | 35 | class Arg; 36 | class CmdLineOutput; 37 | class XorHandler; 38 | 39 | /** 40 | * The base class that manages the command line definition and passes 41 | * along the parsing to the appropriate Arg classes. 42 | */ 43 | class CmdLineInterface 44 | { 45 | public: 46 | 47 | /** 48 | * Destructor 49 | */ 50 | virtual ~CmdLineInterface() {} 51 | 52 | /** 53 | * Adds an argument to the list of arguments to be parsed. 54 | * \param a - Argument to be added. 55 | */ 56 | virtual void add( Arg& a )=0; 57 | 58 | /** 59 | * An alternative add. Functionally identical. 60 | * \param a - Argument to be added. 61 | */ 62 | virtual void add( Arg* a )=0; 63 | 64 | /** 65 | * Add two Args that will be xor'd. 66 | * If this method is used, add does 67 | * not need to be called. 68 | * \param a - Argument to be added and xor'd. 69 | * \param b - Argument to be added and xor'd. 70 | */ 71 | virtual void xorAdd( Arg& a, Arg& b )=0; 72 | 73 | /** 74 | * Add a list of Args that will be xor'd. If this method is used, 75 | * add does not need to be called. 76 | * \param xors - List of Args to be added and xor'd. 77 | */ 78 | virtual void xorAdd( std::vector& xors )=0; 79 | 80 | /** 81 | * Parses the command line. 82 | * \param argc - Number of arguments. 83 | * \param argv - Array of arguments. 84 | */ 85 | virtual void parse(int argc, const char * const * argv)=0; 86 | 87 | /** 88 | * Parses the command line. 89 | * \param args - A vector of strings representing the args. 90 | * args[0] is still the program name. 91 | */ 92 | void parse(std::vector& args); 93 | 94 | /** 95 | * Returns the CmdLineOutput object. 96 | */ 97 | virtual CmdLineOutput* getOutput()=0; 98 | 99 | /** 100 | * \param co - CmdLineOutput object that we want to use instead. 101 | */ 102 | virtual void setOutput(CmdLineOutput* co)=0; 103 | 104 | /** 105 | * Returns the version string. 106 | */ 107 | virtual std::string& getVersion()=0; 108 | 109 | /** 110 | * Returns the program name string. 111 | */ 112 | virtual std::string& getProgramName()=0; 113 | 114 | /** 115 | * Returns the argList. 116 | */ 117 | virtual std::list& getArgList()=0; 118 | 119 | /** 120 | * Returns the XorHandler. 121 | */ 122 | virtual XorHandler& getXorHandler()=0; 123 | 124 | /** 125 | * Returns the delimiter string. 126 | */ 127 | virtual char getDelimiter()=0; 128 | 129 | /** 130 | * Returns the message string. 131 | */ 132 | virtual std::string& getMessage()=0; 133 | 134 | /** 135 | * Indicates whether or not the help and version switches were created 136 | * automatically. 137 | */ 138 | virtual bool hasHelpAndVersion()=0; 139 | 140 | /** 141 | * Resets the instance as if it had just been constructed so that the 142 | * instance can be reused. 143 | */ 144 | virtual void reset()=0; 145 | }; 146 | 147 | } //namespace 148 | 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /tclap/CmdLineOutput.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | /****************************************************************************** 4 | * 5 | * file: CmdLineOutput.h 6 | * 7 | * Copyright (c) 2004, Michael E. Smoot 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_CMDLINEOUTPUT_H 24 | #define TCLAP_CMDLINEOUTPUT_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | namespace TCLAP { 34 | 35 | class CmdLineInterface; 36 | class ArgException; 37 | 38 | /** 39 | * The interface that any output object must implement. 40 | */ 41 | class CmdLineOutput 42 | { 43 | 44 | public: 45 | 46 | /** 47 | * Virtual destructor. 48 | */ 49 | virtual ~CmdLineOutput() {} 50 | 51 | /** 52 | * Generates some sort of output for the USAGE. 53 | * \param c - The CmdLine object the output is generated for. 54 | */ 55 | virtual void usage(CmdLineInterface& c)=0; 56 | 57 | /** 58 | * Generates some sort of output for the version. 59 | * \param c - The CmdLine object the output is generated for. 60 | */ 61 | virtual void version(CmdLineInterface& c)=0; 62 | 63 | /** 64 | * Generates some sort of output for a failure. 65 | * \param c - The CmdLine object the output is generated for. 66 | * \param e - The ArgException that caused the failure. 67 | */ 68 | virtual void failure( CmdLineInterface& c, 69 | ArgException& e )=0; 70 | 71 | }; 72 | 73 | } //namespace TCLAP 74 | #endif 75 | -------------------------------------------------------------------------------- /tclap/Constraint.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: Constraint.h 5 | * 6 | * Copyright (c) 2005, Michael E. Smoot 7 | * All rights reverved. 8 | * 9 | * See the file COPYING in the top directory of this distribution for 10 | * more information. 11 | * 12 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 18 | * DEALINGS IN THE SOFTWARE. 19 | * 20 | *****************************************************************************/ 21 | 22 | #ifndef TCLAP_CONSTRAINT_H 23 | #define TCLAP_CONSTRAINT_H 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace TCLAP { 33 | 34 | /** 35 | * The interface that defines the interaction between the Arg and Constraint. 36 | */ 37 | template 38 | class Constraint 39 | { 40 | 41 | public: 42 | /** 43 | * Returns a description of the Constraint. 44 | */ 45 | virtual std::string description() const =0; 46 | 47 | /** 48 | * Returns the short ID for the Constraint. 49 | */ 50 | virtual std::string shortID() const =0; 51 | 52 | /** 53 | * The method used to verify that the value parsed from the command 54 | * line meets the constraint. 55 | * \param value - The value that will be checked. 56 | */ 57 | virtual bool check(const T& value) const =0; 58 | 59 | /** 60 | * Destructor. 61 | * Silences warnings about Constraint being a base class with virtual 62 | * functions but without a virtual destructor. 63 | */ 64 | virtual ~Constraint() { ; } 65 | }; 66 | 67 | } //namespace TCLAP 68 | #endif 69 | -------------------------------------------------------------------------------- /tclap/DocBookOutput.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: DocBookOutput.h 6 | * 7 | * Copyright (c) 2004, Michael E. Smoot 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_DOCBOOKOUTPUT_H 24 | #define TCLAP_DOCBOOKOUTPUT_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | namespace TCLAP { 38 | 39 | /** 40 | * A class that generates DocBook output for usage() method for the 41 | * given CmdLine and its Args. 42 | */ 43 | class DocBookOutput : public CmdLineOutput 44 | { 45 | 46 | public: 47 | 48 | /** 49 | * Prints the usage to stdout. Can be overridden to 50 | * produce alternative behavior. 51 | * \param c - The CmdLine object the output is generated for. 52 | */ 53 | virtual void usage(CmdLineInterface& c); 54 | 55 | /** 56 | * Prints the version to stdout. Can be overridden 57 | * to produce alternative behavior. 58 | * \param c - The CmdLine object the output is generated for. 59 | */ 60 | virtual void version(CmdLineInterface& c); 61 | 62 | /** 63 | * Prints (to stderr) an error message, short usage 64 | * Can be overridden to produce alternative behavior. 65 | * \param c - The CmdLine object the output is generated for. 66 | * \param e - The ArgException that caused the failure. 67 | */ 68 | virtual void failure(CmdLineInterface& c, 69 | ArgException& e ); 70 | 71 | protected: 72 | 73 | /** 74 | * Substitutes the char r for string x in string s. 75 | * \param s - The string to operate on. 76 | * \param r - The char to replace. 77 | * \param x - What to replace r with. 78 | */ 79 | void substituteSpecialChars( std::string& s, char r, std::string& x ); 80 | void removeChar( std::string& s, char r); 81 | void basename( std::string& s ); 82 | 83 | void printShortArg(Arg* it); 84 | void printLongArg(Arg* it); 85 | 86 | char theDelimiter; 87 | }; 88 | 89 | 90 | inline void DocBookOutput::version(CmdLineInterface& _cmd) 91 | { 92 | std::cout << _cmd.getVersion() << std::endl; 93 | } 94 | 95 | inline void DocBookOutput::usage(CmdLineInterface& _cmd ) 96 | { 97 | std::list argList = _cmd.getArgList(); 98 | std::string progName = _cmd.getProgramName(); 99 | std::string xversion = _cmd.getVersion(); 100 | theDelimiter = _cmd.getDelimiter(); 101 | XorHandler xorHandler = _cmd.getXorHandler(); 102 | std::vector< std::vector > xorList = xorHandler.getXorList(); 103 | basename(progName); 104 | 105 | std::cout << "" << std::endl; 106 | std::cout << "" << std::endl << std::endl; 108 | 109 | std::cout << "" << std::endl; 110 | 111 | std::cout << "" << std::endl; 112 | std::cout << "" << progName << "" << std::endl; 113 | std::cout << "1" << std::endl; 114 | std::cout << "" << std::endl; 115 | 116 | std::cout << "" << std::endl; 117 | std::cout << "" << progName << "" << std::endl; 118 | std::cout << "" << _cmd.getMessage() << "" << std::endl; 119 | std::cout << "" << std::endl; 120 | 121 | std::cout << "" << std::endl; 122 | std::cout << "" << std::endl; 123 | 124 | std::cout << "" << progName << "" << std::endl; 125 | 126 | // xor 127 | for ( int i = 0; (unsigned int)i < xorList.size(); i++ ) 128 | { 129 | std::cout << "" << std::endl; 130 | for ( ArgVectorIterator it = xorList[i].begin(); 131 | it != xorList[i].end(); it++ ) 132 | printShortArg((*it)); 133 | 134 | std::cout << "" << std::endl; 135 | } 136 | 137 | // rest of args 138 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 139 | if ( !xorHandler.contains( (*it) ) ) 140 | printShortArg((*it)); 141 | 142 | std::cout << "" << std::endl; 143 | std::cout << "" << std::endl; 144 | 145 | std::cout << "" << std::endl; 146 | std::cout << "Description" << std::endl; 147 | std::cout << "" << std::endl; 148 | std::cout << _cmd.getMessage() << std::endl; 149 | std::cout << "" << std::endl; 150 | std::cout << "" << std::endl; 151 | 152 | std::cout << "" << std::endl; 153 | std::cout << "Options" << std::endl; 154 | 155 | std::cout << "" << std::endl; 156 | 157 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 158 | printLongArg((*it)); 159 | 160 | std::cout << "" << std::endl; 161 | std::cout << "" << std::endl; 162 | 163 | std::cout << "" << std::endl; 164 | std::cout << "Version" << std::endl; 165 | std::cout << "" << std::endl; 166 | std::cout << xversion << std::endl; 167 | std::cout << "" << std::endl; 168 | std::cout << "" << std::endl; 169 | 170 | std::cout << "" << std::endl; 171 | 172 | } 173 | 174 | inline void DocBookOutput::failure( CmdLineInterface& _cmd, 175 | ArgException& e ) 176 | { 177 | static_cast(_cmd); // unused 178 | std::cout << e.what() << std::endl; 179 | throw ExitException(1); 180 | } 181 | 182 | inline void DocBookOutput::substituteSpecialChars( std::string& s, 183 | char r, 184 | std::string& x ) 185 | { 186 | size_t p; 187 | while ( (p = s.find_first_of(r)) != std::string::npos ) 188 | { 189 | s.erase(p,1); 190 | s.insert(p,x); 191 | } 192 | } 193 | 194 | inline void DocBookOutput::removeChar( std::string& s, char r) 195 | { 196 | size_t p; 197 | while ( (p = s.find_first_of(r)) != std::string::npos ) 198 | { 199 | s.erase(p,1); 200 | } 201 | } 202 | 203 | inline void DocBookOutput::basename( std::string& s ) 204 | { 205 | size_t p = s.find_last_of('/'); 206 | if ( p != std::string::npos ) 207 | { 208 | s.erase(0, p + 1); 209 | } 210 | } 211 | 212 | inline void DocBookOutput::printShortArg(Arg* a) 213 | { 214 | std::string lt = "<"; 215 | std::string gt = ">"; 216 | 217 | std::string id = a->shortID(); 218 | substituteSpecialChars(id,'<',lt); 219 | substituteSpecialChars(id,'>',gt); 220 | removeChar(id,'['); 221 | removeChar(id,']'); 222 | 223 | std::string choice = "opt"; 224 | if ( a->isRequired() ) 225 | choice = "plain"; 226 | 227 | std::cout << "acceptsMultipleValues() ) 229 | std::cout << " rep='repeat'"; 230 | 231 | 232 | std::cout << '>'; 233 | if ( !a->getFlag().empty() ) 234 | std::cout << a->flagStartChar() << a->getFlag(); 235 | else 236 | std::cout << a->nameStartString() << a->getName(); 237 | if ( a->isValueRequired() ) 238 | { 239 | std::string arg = a->shortID(); 240 | removeChar(arg,'['); 241 | removeChar(arg,']'); 242 | removeChar(arg,'<'); 243 | removeChar(arg,'>'); 244 | arg.erase(0, arg.find_last_of(theDelimiter) + 1); 245 | std::cout << theDelimiter; 246 | std::cout << "" << arg << ""; 247 | } 248 | std::cout << "" << std::endl; 249 | 250 | } 251 | 252 | inline void DocBookOutput::printLongArg(Arg* a) 253 | { 254 | std::string lt = "<"; 255 | std::string gt = ">"; 256 | 257 | std::string desc = a->getDescription(); 258 | substituteSpecialChars(desc,'<',lt); 259 | substituteSpecialChars(desc,'>',gt); 260 | 261 | std::cout << "" << std::endl; 262 | 263 | if ( !a->getFlag().empty() ) 264 | { 265 | std::cout << "" << std::endl; 266 | std::cout << "" << std::endl; 269 | std::cout << "" << std::endl; 270 | } 271 | 272 | std::cout << "" << std::endl; 273 | std::cout << "" << std::endl; 287 | std::cout << "" << std::endl; 288 | 289 | std::cout << "" << std::endl; 290 | std::cout << "" << std::endl; 291 | std::cout << desc << std::endl; 292 | std::cout << "" << std::endl; 293 | std::cout << "" << std::endl; 294 | 295 | std::cout << "" << std::endl; 296 | } 297 | 298 | } //namespace TCLAP 299 | #endif 300 | -------------------------------------------------------------------------------- /tclap/HelpVisitor.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: HelpVisitor.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * All rights reverved. 8 | * 9 | * See the file COPYING in the top directory of this distribution for 10 | * more information. 11 | * 12 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 18 | * DEALINGS IN THE SOFTWARE. 19 | * 20 | *****************************************************************************/ 21 | 22 | #ifndef TCLAP_HELP_VISITOR_H 23 | #define TCLAP_HELP_VISITOR_H 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | namespace TCLAP { 30 | 31 | /** 32 | * A Visitor object that calls the usage method of the given CmdLineOutput 33 | * object for the specified CmdLine object. 34 | */ 35 | class HelpVisitor: public Visitor 36 | { 37 | private: 38 | /** 39 | * Prevent accidental copying. 40 | */ 41 | HelpVisitor(const HelpVisitor& rhs); 42 | HelpVisitor& operator=(const HelpVisitor& rhs); 43 | 44 | protected: 45 | 46 | /** 47 | * The CmdLine the output will be generated for. 48 | */ 49 | CmdLineInterface* _cmd; 50 | 51 | /** 52 | * The output object. 53 | */ 54 | CmdLineOutput** _out; 55 | 56 | public: 57 | 58 | /** 59 | * Constructor. 60 | * \param cmd - The CmdLine the output will be generated for. 61 | * \param out - The type of output. 62 | */ 63 | HelpVisitor(CmdLineInterface* cmd, CmdLineOutput** out) 64 | : Visitor(), _cmd( cmd ), _out( out ) { } 65 | 66 | /** 67 | * Calls the usage method of the CmdLineOutput for the 68 | * specified CmdLine. 69 | */ 70 | void visit() { (*_out)->usage(*_cmd); throw ExitException(0); } 71 | 72 | }; 73 | 74 | } 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /tclap/IgnoreRestVisitor.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: IgnoreRestVisitor.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * All rights reverved. 8 | * 9 | * See the file COPYING in the top directory of this distribution for 10 | * more information. 11 | * 12 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 18 | * DEALINGS IN THE SOFTWARE. 19 | * 20 | *****************************************************************************/ 21 | 22 | 23 | #ifndef TCLAP_IGNORE_REST_VISITOR_H 24 | #define TCLAP_IGNORE_REST_VISITOR_H 25 | 26 | #include 27 | #include 28 | 29 | namespace TCLAP { 30 | 31 | /** 32 | * A Vistor that tells the CmdLine to begin ignoring arguments after 33 | * this one is parsed. 34 | */ 35 | class IgnoreRestVisitor: public Visitor 36 | { 37 | public: 38 | 39 | /** 40 | * Constructor. 41 | */ 42 | IgnoreRestVisitor() : Visitor() {} 43 | 44 | /** 45 | * Sets Arg::_ignoreRest. 46 | */ 47 | void visit() { Arg::beginIgnoring(); } 48 | }; 49 | 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /tclap/MultiArg.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * file: MultiArg.h 4 | * 5 | * Copyright (c) 2003, Michael E. Smoot . 6 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 7 | * All rights reverved. 8 | * 9 | * See the file COPYING in the top directory of this distribution for 10 | * more information. 11 | * 12 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 18 | * DEALINGS IN THE SOFTWARE. 19 | * 20 | *****************************************************************************/ 21 | 22 | 23 | #ifndef TCLAP_MULTIPLE_ARGUMENT_H 24 | #define TCLAP_MULTIPLE_ARGUMENT_H 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | namespace TCLAP { 33 | /** 34 | * An argument that allows multiple values of type T to be specified. Very 35 | * similar to a ValueArg, except a vector of values will be returned 36 | * instead of just one. 37 | */ 38 | template 39 | class MultiArg : public Arg 40 | { 41 | public: 42 | typedef std::vector container_type; 43 | typedef typename container_type::iterator iterator; 44 | typedef typename container_type::const_iterator const_iterator; 45 | 46 | protected: 47 | 48 | /** 49 | * The list of values parsed from the CmdLine. 50 | */ 51 | std::vector _values; 52 | 53 | /** 54 | * The description of type T to be used in the usage. 55 | */ 56 | std::string _typeDesc; 57 | 58 | /** 59 | * A list of constraint on this Arg. 60 | */ 61 | Constraint* _constraint; 62 | 63 | /** 64 | * Extracts the value from the string. 65 | * Attempts to parse string as type T, if this fails an exception 66 | * is thrown. 67 | * \param val - The string to be read. 68 | */ 69 | void _extractValue( const std::string& val ); 70 | 71 | /** 72 | * Used by XorHandler to decide whether to keep parsing for this arg. 73 | */ 74 | bool _allowMore; 75 | 76 | public: 77 | 78 | /** 79 | * Constructor. 80 | * \param flag - The one character flag that identifies this 81 | * argument on the command line. 82 | * \param name - A one word name for the argument. Can be 83 | * used as a long flag on the command line. 84 | * \param desc - A description of what the argument is for or 85 | * does. 86 | * \param req - Whether the argument is required on the command 87 | * line. 88 | * \param typeDesc - A short, human readable description of the 89 | * type that this object expects. This is used in the generation 90 | * of the USAGE statement. The goal is to be helpful to the end user 91 | * of the program. 92 | * \param v - An optional visitor. You probably should not 93 | * use this unless you have a very good reason. 94 | */ 95 | MultiArg( const std::string& flag, 96 | const std::string& name, 97 | const std::string& desc, 98 | bool req, 99 | const std::string& typeDesc, 100 | Visitor* v = NULL); 101 | 102 | /** 103 | * Constructor. 104 | * \param flag - The one character flag that identifies this 105 | * argument on the command line. 106 | * \param name - A one word name for the argument. Can be 107 | * used as a long flag on the command line. 108 | * \param desc - A description of what the argument is for or 109 | * does. 110 | * \param req - Whether the argument is required on the command 111 | * line. 112 | * \param typeDesc - A short, human readable description of the 113 | * type that this object expects. This is used in the generation 114 | * of the USAGE statement. The goal is to be helpful to the end user 115 | * of the program. 116 | * \param parser - A CmdLine parser object to add this Arg to 117 | * \param v - An optional visitor. You probably should not 118 | * use this unless you have a very good reason. 119 | */ 120 | MultiArg( const std::string& flag, 121 | const std::string& name, 122 | const std::string& desc, 123 | bool req, 124 | const std::string& typeDesc, 125 | CmdLineInterface& parser, 126 | Visitor* v = NULL ); 127 | 128 | /** 129 | * Constructor. 130 | * \param flag - The one character flag that identifies this 131 | * argument on the command line. 132 | * \param name - A one word name for the argument. Can be 133 | * used as a long flag on the command line. 134 | * \param desc - A description of what the argument is for or 135 | * does. 136 | * \param req - Whether the argument is required on the command 137 | * line. 138 | * \param constraint - A pointer to a Constraint object used 139 | * to constrain this Arg. 140 | * \param v - An optional visitor. You probably should not 141 | * use this unless you have a very good reason. 142 | */ 143 | MultiArg( const std::string& flag, 144 | const std::string& name, 145 | const std::string& desc, 146 | bool req, 147 | Constraint* constraint, 148 | Visitor* v = NULL ); 149 | 150 | /** 151 | * Constructor. 152 | * \param flag - The one character flag that identifies this 153 | * argument on the command line. 154 | * \param name - A one word name for the argument. Can be 155 | * used as a long flag on the command line. 156 | * \param desc - A description of what the argument is for or 157 | * does. 158 | * \param req - Whether the argument is required on the command 159 | * line. 160 | * \param constraint - A pointer to a Constraint object used 161 | * to constrain this Arg. 162 | * \param parser - A CmdLine parser object to add this Arg to 163 | * \param v - An optional visitor. You probably should not 164 | * use this unless you have a very good reason. 165 | */ 166 | MultiArg( const std::string& flag, 167 | const std::string& name, 168 | const std::string& desc, 169 | bool req, 170 | Constraint* constraint, 171 | CmdLineInterface& parser, 172 | Visitor* v = NULL ); 173 | 174 | /** 175 | * Handles the processing of the argument. 176 | * This re-implements the Arg version of this method to set the 177 | * _value of the argument appropriately. It knows the difference 178 | * between labeled and unlabeled. 179 | * \param i - Pointer the the current argument in the list. 180 | * \param args - Mutable list of strings. Passed from main(). 181 | */ 182 | virtual bool processArg(int* i, std::vector& args); 183 | 184 | /** 185 | * Returns a vector of type T containing the values parsed from 186 | * the command line. 187 | */ 188 | const std::vector& getValue(); 189 | 190 | /** 191 | * Returns an iterator over the values parsed from the command 192 | * line. 193 | */ 194 | const_iterator begin() const { return _values.begin(); } 195 | 196 | /** 197 | * Returns the end of the values parsed from the command 198 | * line. 199 | */ 200 | const_iterator end() const { return _values.end(); } 201 | 202 | /** 203 | * Returns the a short id string. Used in the usage. 204 | * \param val - value to be used. 205 | */ 206 | virtual std::string shortID(const std::string& val="val") const; 207 | 208 | /** 209 | * Returns the a long id string. Used in the usage. 210 | * \param val - value to be used. 211 | */ 212 | virtual std::string longID(const std::string& val="val") const; 213 | 214 | /** 215 | * Once we've matched the first value, then the arg is no longer 216 | * required. 217 | */ 218 | virtual bool isRequired() const; 219 | 220 | virtual bool allowMore(); 221 | 222 | virtual void reset(); 223 | 224 | private: 225 | /** 226 | * Prevent accidental copying 227 | */ 228 | MultiArg(const MultiArg& rhs); 229 | MultiArg& operator=(const MultiArg& rhs); 230 | 231 | }; 232 | 233 | template 234 | MultiArg::MultiArg(const std::string& flag, 235 | const std::string& name, 236 | const std::string& desc, 237 | bool req, 238 | const std::string& typeDesc, 239 | Visitor* v) : 240 | Arg( flag, name, desc, req, true, v ), 241 | _values(std::vector()), 242 | _typeDesc( typeDesc ), 243 | _constraint( NULL ), 244 | _allowMore(false) 245 | { 246 | _acceptsMultipleValues = true; 247 | } 248 | 249 | template 250 | MultiArg::MultiArg(const std::string& flag, 251 | const std::string& name, 252 | const std::string& desc, 253 | bool req, 254 | const std::string& typeDesc, 255 | CmdLineInterface& parser, 256 | Visitor* v) 257 | : Arg( flag, name, desc, req, true, v ), 258 | _values(std::vector()), 259 | _typeDesc( typeDesc ), 260 | _constraint( NULL ), 261 | _allowMore(false) 262 | { 263 | parser.add( this ); 264 | _acceptsMultipleValues = true; 265 | } 266 | 267 | /** 268 | * 269 | */ 270 | template 271 | MultiArg::MultiArg(const std::string& flag, 272 | const std::string& name, 273 | const std::string& desc, 274 | bool req, 275 | Constraint* constraint, 276 | Visitor* v) 277 | : Arg( flag, name, desc, req, true, v ), 278 | _values(std::vector()), 279 | _typeDesc( constraint->shortID() ), 280 | _constraint( constraint ), 281 | _allowMore(false) 282 | { 283 | _acceptsMultipleValues = true; 284 | } 285 | 286 | template 287 | MultiArg::MultiArg(const std::string& flag, 288 | const std::string& name, 289 | const std::string& desc, 290 | bool req, 291 | Constraint* constraint, 292 | CmdLineInterface& parser, 293 | Visitor* v) 294 | : Arg( flag, name, desc, req, true, v ), 295 | _values(std::vector()), 296 | _typeDesc( constraint->shortID() ), 297 | _constraint( constraint ), 298 | _allowMore(false) 299 | { 300 | parser.add( this ); 301 | _acceptsMultipleValues = true; 302 | } 303 | 304 | template 305 | const std::vector& MultiArg::getValue() { return _values; } 306 | 307 | template 308 | bool MultiArg::processArg(int *i, std::vector& args) 309 | { 310 | if ( _ignoreable && Arg::ignoreRest() ) 311 | return false; 312 | 313 | if ( _hasBlanks( args[*i] ) ) 314 | return false; 315 | 316 | std::string flag = args[*i]; 317 | std::string value = ""; 318 | 319 | trimFlag( flag, value ); 320 | 321 | if ( argMatches( flag ) ) 322 | { 323 | if ( Arg::delimiter() != ' ' && value == "" ) 324 | throw( ArgParseException( 325 | "Couldn't find delimiter for this argument!", 326 | toString() ) ); 327 | 328 | // always take the first one, regardless of start string 329 | if ( value == "" ) 330 | { 331 | (*i)++; 332 | if ( static_cast(*i) < args.size() ) 333 | _extractValue( args[*i] ); 334 | else 335 | throw( ArgParseException("Missing a value for this argument!", 336 | toString() ) ); 337 | } 338 | else 339 | _extractValue( value ); 340 | 341 | /* 342 | // continuing taking the args until we hit one with a start string 343 | while ( (unsigned int)(*i)+1 < args.size() && 344 | args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && 345 | args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) 346 | _extractValue( args[++(*i)] ); 347 | */ 348 | 349 | _alreadySet = true; 350 | _checkWithVisitor(); 351 | 352 | return true; 353 | } 354 | else 355 | return false; 356 | } 357 | 358 | /** 359 | * 360 | */ 361 | template 362 | std::string MultiArg::shortID(const std::string& val) const 363 | { 364 | static_cast(val); // Ignore input, don't warn 365 | return Arg::shortID(_typeDesc) + " ... "; 366 | } 367 | 368 | /** 369 | * 370 | */ 371 | template 372 | std::string MultiArg::longID(const std::string& val) const 373 | { 374 | static_cast(val); // Ignore input, don't warn 375 | return Arg::longID(_typeDesc) + " (accepted multiple times)"; 376 | } 377 | 378 | /** 379 | * Once we've matched the first value, then the arg is no longer 380 | * required. 381 | */ 382 | template 383 | bool MultiArg::isRequired() const 384 | { 385 | if ( _required ) 386 | { 387 | if ( _values.size() > 1 ) 388 | return false; 389 | else 390 | return true; 391 | } 392 | else 393 | return false; 394 | 395 | } 396 | 397 | template 398 | void MultiArg::_extractValue( const std::string& val ) 399 | { 400 | try { 401 | T tmp; 402 | ExtractValue(tmp, val, typename ArgTraits::ValueCategory()); 403 | _values.push_back(tmp); 404 | } catch( ArgParseException &e) { 405 | throw ArgParseException(e.error(), toString()); 406 | } 407 | 408 | if ( _constraint != NULL ) 409 | if ( ! _constraint->check( _values.back() ) ) 410 | throw( CmdLineParseException( "Value '" + val + 411 | "' does not meet constraint: " + 412 | _constraint->description(), 413 | toString() ) ); 414 | } 415 | 416 | template 417 | bool MultiArg::allowMore() 418 | { 419 | bool am = _allowMore; 420 | _allowMore = true; 421 | return am; 422 | } 423 | 424 | template 425 | void MultiArg::reset() 426 | { 427 | Arg::reset(); 428 | _values.clear(); 429 | } 430 | 431 | } // namespace TCLAP 432 | 433 | #endif 434 | -------------------------------------------------------------------------------- /tclap/MultiSwitchArg.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: MultiSwitchArg.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 8 | * Copyright (c) 2005, Michael E. Smoot, Daniel Aarno, Erik Zeek. 9 | * All rights reverved. 10 | * 11 | * See the file COPYING in the top directory of this distribution for 12 | * more information. 13 | * 14 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | *****************************************************************************/ 23 | 24 | 25 | #ifndef TCLAP_MULTI_SWITCH_ARG_H 26 | #define TCLAP_MULTI_SWITCH_ARG_H 27 | 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | namespace TCLAP { 34 | 35 | /** 36 | * A multiple switch argument. If the switch is set on the command line, then 37 | * the getValue method will return the number of times the switch appears. 38 | */ 39 | class MultiSwitchArg : public SwitchArg 40 | { 41 | protected: 42 | 43 | /** 44 | * The value of the switch. 45 | */ 46 | int _value; 47 | 48 | /** 49 | * Used to support the reset() method so that ValueArg can be 50 | * reset to their constructed value. 51 | */ 52 | int _default; 53 | 54 | public: 55 | 56 | /** 57 | * MultiSwitchArg constructor. 58 | * \param flag - The one character flag that identifies this 59 | * argument on the command line. 60 | * \param name - A one word name for the argument. Can be 61 | * used as a long flag on the command line. 62 | * \param desc - A description of what the argument is for or 63 | * does. 64 | * \param init - Optional. The initial/default value of this Arg. 65 | * Defaults to 0. 66 | * \param v - An optional visitor. You probably should not 67 | * use this unless you have a very good reason. 68 | */ 69 | MultiSwitchArg(const std::string& flag, 70 | const std::string& name, 71 | const std::string& desc, 72 | int init = 0, 73 | Visitor* v = NULL); 74 | 75 | 76 | /** 77 | * MultiSwitchArg constructor. 78 | * \param flag - The one character flag that identifies this 79 | * argument on the command line. 80 | * \param name - A one word name for the argument. Can be 81 | * used as a long flag on the command line. 82 | * \param desc - A description of what the argument is for or 83 | * does. 84 | * \param parser - A CmdLine parser object to add this Arg to 85 | * \param init - Optional. The initial/default value of this Arg. 86 | * Defaults to 0. 87 | * \param v - An optional visitor. You probably should not 88 | * use this unless you have a very good reason. 89 | */ 90 | MultiSwitchArg(const std::string& flag, 91 | const std::string& name, 92 | const std::string& desc, 93 | CmdLineInterface& parser, 94 | int init = 0, 95 | Visitor* v = NULL); 96 | 97 | 98 | /** 99 | * Handles the processing of the argument. 100 | * This re-implements the SwitchArg version of this method to set the 101 | * _value of the argument appropriately. 102 | * \param i - Pointer the the current argument in the list. 103 | * \param args - Mutable list of strings. Passed 104 | * in from main(). 105 | */ 106 | virtual bool processArg(int* i, std::vector& args); 107 | 108 | /** 109 | * Returns int, the number of times the switch has been set. 110 | */ 111 | int getValue(); 112 | 113 | /** 114 | * Returns the shortID for this Arg. 115 | */ 116 | std::string shortID(const std::string& val) const; 117 | 118 | /** 119 | * Returns the longID for this Arg. 120 | */ 121 | std::string longID(const std::string& val) const; 122 | 123 | void reset(); 124 | 125 | }; 126 | 127 | ////////////////////////////////////////////////////////////////////// 128 | //BEGIN MultiSwitchArg.cpp 129 | ////////////////////////////////////////////////////////////////////// 130 | inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, 131 | const std::string& name, 132 | const std::string& desc, 133 | int init, 134 | Visitor* v ) 135 | : SwitchArg(flag, name, desc, false, v), 136 | _value( init ), 137 | _default( init ) 138 | { } 139 | 140 | inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, 141 | const std::string& name, 142 | const std::string& desc, 143 | CmdLineInterface& parser, 144 | int init, 145 | Visitor* v ) 146 | : SwitchArg(flag, name, desc, false, v), 147 | _value( init ), 148 | _default( init ) 149 | { 150 | parser.add( this ); 151 | } 152 | 153 | inline int MultiSwitchArg::getValue() { return _value; } 154 | 155 | inline bool MultiSwitchArg::processArg(int *i, std::vector& args) 156 | { 157 | if ( _ignoreable && Arg::ignoreRest() ) 158 | return false; 159 | 160 | if ( argMatches( args[*i] )) 161 | { 162 | // so the isSet() method will work 163 | _alreadySet = true; 164 | 165 | // Matched argument: increment value. 166 | ++_value; 167 | 168 | _checkWithVisitor(); 169 | 170 | return true; 171 | } 172 | else if ( combinedSwitchesMatch( args[*i] ) ) 173 | { 174 | // so the isSet() method will work 175 | _alreadySet = true; 176 | 177 | // Matched argument: increment value. 178 | ++_value; 179 | 180 | // Check for more in argument and increment value. 181 | while ( combinedSwitchesMatch( args[*i] ) ) 182 | ++_value; 183 | 184 | _checkWithVisitor(); 185 | 186 | return false; 187 | } 188 | else 189 | return false; 190 | } 191 | 192 | inline std::string 193 | MultiSwitchArg::shortID(const std::string& val) const 194 | { 195 | return Arg::shortID(val) + " ... "; 196 | } 197 | 198 | inline std::string 199 | MultiSwitchArg::longID(const std::string& val) const 200 | { 201 | return Arg::longID(val) + " (accepted multiple times)"; 202 | } 203 | 204 | inline void 205 | MultiSwitchArg::reset() 206 | { 207 | MultiSwitchArg::_value = MultiSwitchArg::_default; 208 | } 209 | 210 | ////////////////////////////////////////////////////////////////////// 211 | //END MultiSwitchArg.cpp 212 | ////////////////////////////////////////////////////////////////////// 213 | 214 | } //namespace TCLAP 215 | 216 | #endif 217 | -------------------------------------------------------------------------------- /tclap/OptionalUnlabeledTracker.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | /****************************************************************************** 4 | * 5 | * file: OptionalUnlabeledTracker.h 6 | * 7 | * Copyright (c) 2005, Michael E. Smoot . 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | 24 | #ifndef TCLAP_OPTIONAL_UNLABELED_TRACKER_H 25 | #define TCLAP_OPTIONAL_UNLABELED_TRACKER_H 26 | 27 | #include 28 | 29 | namespace TCLAP { 30 | 31 | class OptionalUnlabeledTracker 32 | { 33 | 34 | public: 35 | 36 | static void check( bool req, const std::string& argName ); 37 | 38 | static void gotOptional() { alreadyOptionalRef() = true; } 39 | 40 | static bool& alreadyOptional() { return alreadyOptionalRef(); } 41 | 42 | private: 43 | 44 | static bool& alreadyOptionalRef() { static bool ct = false; return ct; } 45 | }; 46 | 47 | 48 | inline void OptionalUnlabeledTracker::check( bool req, const std::string& argName ) 49 | { 50 | if ( OptionalUnlabeledTracker::alreadyOptional() ) 51 | throw( SpecificationException( 52 | "You can't specify ANY Unlabeled Arg following an optional Unlabeled Arg", 53 | argName ) ); 54 | 55 | if ( !req ) 56 | OptionalUnlabeledTracker::gotOptional(); 57 | } 58 | 59 | 60 | } // namespace TCLAP 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /tclap/StandardTraits.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: StandardTraits.h 6 | * 7 | * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | // This is an internal tclap file, you should probably not have to 24 | // include this directly 25 | 26 | #ifndef TCLAP_STANDARD_TRAITS_H 27 | #define TCLAP_STANDARD_TRAITS_H 28 | 29 | #ifdef HAVE_CONFIG_H 30 | #include // To check for long long 31 | #endif 32 | 33 | // If Microsoft has already typedef'd wchar_t as an unsigned 34 | // short, then compiles will break because it's as if we're 35 | // creating ArgTraits twice for unsigned short. Thus... 36 | #ifdef _MSC_VER 37 | #ifndef _NATIVE_WCHAR_T_DEFINED 38 | #define TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS 39 | #endif 40 | #endif 41 | 42 | namespace TCLAP { 43 | 44 | // ====================================================================== 45 | // Integer types 46 | // ====================================================================== 47 | 48 | /** 49 | * longs have value-like semantics. 50 | */ 51 | template<> 52 | struct ArgTraits { 53 | typedef ValueLike ValueCategory; 54 | }; 55 | 56 | /** 57 | * ints have value-like semantics. 58 | */ 59 | template<> 60 | struct ArgTraits { 61 | typedef ValueLike ValueCategory; 62 | }; 63 | 64 | /** 65 | * shorts have value-like semantics. 66 | */ 67 | template<> 68 | struct ArgTraits { 69 | typedef ValueLike ValueCategory; 70 | }; 71 | 72 | /** 73 | * chars have value-like semantics. 74 | */ 75 | template<> 76 | struct ArgTraits { 77 | typedef ValueLike ValueCategory; 78 | }; 79 | 80 | #ifdef HAVE_LONG_LONG 81 | /** 82 | * long longs have value-like semantics. 83 | */ 84 | template<> 85 | struct ArgTraits { 86 | typedef ValueLike ValueCategory; 87 | }; 88 | #endif 89 | 90 | // ====================================================================== 91 | // Unsigned integer types 92 | // ====================================================================== 93 | 94 | /** 95 | * unsigned longs have value-like semantics. 96 | */ 97 | template<> 98 | struct ArgTraits { 99 | typedef ValueLike ValueCategory; 100 | }; 101 | 102 | /** 103 | * unsigned ints have value-like semantics. 104 | */ 105 | template<> 106 | struct ArgTraits { 107 | typedef ValueLike ValueCategory; 108 | }; 109 | 110 | /** 111 | * unsigned shorts have value-like semantics. 112 | */ 113 | template<> 114 | struct ArgTraits { 115 | typedef ValueLike ValueCategory; 116 | }; 117 | 118 | /** 119 | * unsigned chars have value-like semantics. 120 | */ 121 | template<> 122 | struct ArgTraits { 123 | typedef ValueLike ValueCategory; 124 | }; 125 | 126 | // Microsoft implements size_t awkwardly. 127 | #if defined(_MSC_VER) && defined(_M_X64) 128 | /** 129 | * size_ts have value-like semantics. 130 | */ 131 | template<> 132 | struct ArgTraits { 133 | typedef ValueLike ValueCategory; 134 | }; 135 | #endif 136 | 137 | 138 | #ifdef HAVE_LONG_LONG 139 | /** 140 | * unsigned long longs have value-like semantics. 141 | */ 142 | template<> 143 | struct ArgTraits { 144 | typedef ValueLike ValueCategory; 145 | }; 146 | #endif 147 | 148 | // ====================================================================== 149 | // Float types 150 | // ====================================================================== 151 | 152 | /** 153 | * floats have value-like semantics. 154 | */ 155 | template<> 156 | struct ArgTraits { 157 | typedef ValueLike ValueCategory; 158 | }; 159 | 160 | /** 161 | * doubles have value-like semantics. 162 | */ 163 | template<> 164 | struct ArgTraits { 165 | typedef ValueLike ValueCategory; 166 | }; 167 | 168 | // ====================================================================== 169 | // Other types 170 | // ====================================================================== 171 | 172 | /** 173 | * bools have value-like semantics. 174 | */ 175 | template<> 176 | struct ArgTraits { 177 | typedef ValueLike ValueCategory; 178 | }; 179 | 180 | 181 | /** 182 | * wchar_ts have value-like semantics. 183 | */ 184 | #ifndef TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS 185 | template<> 186 | struct ArgTraits { 187 | typedef ValueLike ValueCategory; 188 | }; 189 | #endif 190 | 191 | /** 192 | * Strings have string like argument traits. 193 | */ 194 | template<> 195 | struct ArgTraits { 196 | typedef StringLike ValueCategory; 197 | }; 198 | 199 | template 200 | void SetString(T &dst, const std::string &src) 201 | { 202 | dst = src; 203 | } 204 | 205 | } // namespace 206 | 207 | #endif 208 | 209 | -------------------------------------------------------------------------------- /tclap/StdOutput.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: StdOutput.h 6 | * 7 | * Copyright (c) 2004, Michael E. Smoot 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_STDCMDLINEOUTPUT_H 24 | #define TCLAP_STDCMDLINEOUTPUT_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | namespace TCLAP { 38 | 39 | /** 40 | * A class that isolates any output from the CmdLine object so that it 41 | * may be easily modified. 42 | */ 43 | class StdOutput : public CmdLineOutput 44 | { 45 | 46 | public: 47 | 48 | /** 49 | * Prints the usage to stdout. Can be overridden to 50 | * produce alternative behavior. 51 | * \param c - The CmdLine object the output is generated for. 52 | */ 53 | virtual void usage(CmdLineInterface& c); 54 | 55 | /** 56 | * Prints the version to stdout. Can be overridden 57 | * to produce alternative behavior. 58 | * \param c - The CmdLine object the output is generated for. 59 | */ 60 | virtual void version(CmdLineInterface& c); 61 | 62 | /** 63 | * Prints (to stderr) an error message, short usage 64 | * Can be overridden to produce alternative behavior. 65 | * \param c - The CmdLine object the output is generated for. 66 | * \param e - The ArgException that caused the failure. 67 | */ 68 | virtual void failure(CmdLineInterface& c, 69 | ArgException& e ); 70 | 71 | protected: 72 | 73 | /** 74 | * Writes a brief usage message with short args. 75 | * \param c - The CmdLine object the output is generated for. 76 | * \param os - The stream to write the message to. 77 | */ 78 | void _shortUsage( CmdLineInterface& c, std::ostream& os ) const; 79 | 80 | /** 81 | * Writes a longer usage message with long and short args, 82 | * provides descriptions and prints message. 83 | * \param c - The CmdLine object the output is generated for. 84 | * \param os - The stream to write the message to. 85 | */ 86 | void _longUsage( CmdLineInterface& c, std::ostream& os ) const; 87 | 88 | /** 89 | * This function inserts line breaks and indents long strings 90 | * according the params input. It will only break lines at spaces, 91 | * commas and pipes. 92 | * \param os - The stream to be printed to. 93 | * \param s - The string to be printed. 94 | * \param maxWidth - The maxWidth allowed for the output line. 95 | * \param indentSpaces - The number of spaces to indent the first line. 96 | * \param secondLineOffset - The number of spaces to indent the second 97 | * and all subsequent lines in addition to indentSpaces. 98 | */ 99 | void spacePrint( std::ostream& os, 100 | const std::string& s, 101 | int maxWidth, 102 | int indentSpaces, 103 | int secondLineOffset ) const; 104 | 105 | }; 106 | 107 | 108 | inline void StdOutput::version(CmdLineInterface& _cmd) 109 | { 110 | std::string progName = _cmd.getProgramName(); 111 | std::string xversion = _cmd.getVersion(); 112 | 113 | std::cout << std::endl << progName << " version: " 114 | << xversion << std::endl << std::endl; 115 | } 116 | 117 | inline void StdOutput::usage(CmdLineInterface& _cmd ) 118 | { 119 | std::cout << std::endl << "USAGE: " << std::endl << std::endl; 120 | 121 | _shortUsage( _cmd, std::cout ); 122 | 123 | std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl; 124 | 125 | _longUsage( _cmd, std::cout ); 126 | 127 | std::cout << std::endl; 128 | 129 | } 130 | 131 | inline void StdOutput::failure( CmdLineInterface& _cmd, 132 | ArgException& e ) 133 | { 134 | std::string progName = _cmd.getProgramName(); 135 | 136 | std::cerr << "PARSE ERROR: " << e.argId() << std::endl 137 | << " " << e.error() << std::endl << std::endl; 138 | 139 | if ( _cmd.hasHelpAndVersion() ) 140 | { 141 | std::cerr << "Brief USAGE: " << std::endl; 142 | 143 | _shortUsage( _cmd, std::cerr ); 144 | 145 | std::cerr << std::endl << "For complete USAGE and HELP type: " 146 | << std::endl << " " << progName << " --help" 147 | << std::endl << std::endl; 148 | } 149 | else 150 | usage(_cmd); 151 | 152 | throw ExitException(1); 153 | } 154 | 155 | inline void 156 | StdOutput::_shortUsage( CmdLineInterface& _cmd, 157 | std::ostream& os ) const 158 | { 159 | std::list argList = _cmd.getArgList(); 160 | std::string progName = _cmd.getProgramName(); 161 | XorHandler xorHandler = _cmd.getXorHandler(); 162 | std::vector< std::vector > xorList = xorHandler.getXorList(); 163 | 164 | std::string s = progName + " "; 165 | 166 | // first the xor 167 | for ( int i = 0; static_cast(i) < xorList.size(); i++ ) 168 | { 169 | s += " {"; 170 | for ( ArgVectorIterator it = xorList[i].begin(); 171 | it != xorList[i].end(); it++ ) 172 | s += (*it)->shortID() + "|"; 173 | 174 | s[s.length()-1] = '}'; 175 | } 176 | 177 | // then the rest 178 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 179 | if ( !xorHandler.contains( (*it) ) ) 180 | s += " " + (*it)->shortID(); 181 | 182 | // if the program name is too long, then adjust the second line offset 183 | int secondLineOffset = static_cast(progName.length()) + 2; 184 | if ( secondLineOffset > 75/2 ) 185 | secondLineOffset = static_cast(75/2); 186 | 187 | spacePrint( os, s, 75, 3, secondLineOffset ); 188 | } 189 | 190 | inline void 191 | StdOutput::_longUsage( CmdLineInterface& _cmd, 192 | std::ostream& os ) const 193 | { 194 | std::list argList = _cmd.getArgList(); 195 | std::string message = _cmd.getMessage(); 196 | XorHandler xorHandler = _cmd.getXorHandler(); 197 | std::vector< std::vector > xorList = xorHandler.getXorList(); 198 | 199 | // first the xor 200 | for ( int i = 0; static_cast(i) < xorList.size(); i++ ) 201 | { 202 | for ( ArgVectorIterator it = xorList[i].begin(); 203 | it != xorList[i].end(); 204 | it++ ) 205 | { 206 | spacePrint( os, (*it)->longID(), 75, 3, 3 ); 207 | spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); 208 | 209 | if ( it+1 != xorList[i].end() ) 210 | spacePrint(os, "-- OR --", 75, 9, 0); 211 | } 212 | os << std::endl << std::endl; 213 | } 214 | 215 | // then the rest 216 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 217 | if ( !xorHandler.contains( (*it) ) ) 218 | { 219 | spacePrint( os, (*it)->longID(), 75, 3, 3 ); 220 | spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); 221 | os << std::endl; 222 | } 223 | 224 | os << std::endl; 225 | 226 | spacePrint( os, message, 75, 3, 0 ); 227 | } 228 | 229 | inline void StdOutput::spacePrint( std::ostream& os, 230 | const std::string& s, 231 | int maxWidth, 232 | int indentSpaces, 233 | int secondLineOffset ) const 234 | { 235 | int len = static_cast(s.length()); 236 | 237 | if ( (len + indentSpaces > maxWidth) && maxWidth > 0 ) 238 | { 239 | int allowedLen = maxWidth - indentSpaces; 240 | int start = 0; 241 | while ( start < len ) 242 | { 243 | // find the substring length 244 | // int stringLen = std::min( len - start, allowedLen ); 245 | // doing it this way to support a VisualC++ 2005 bug 246 | using namespace std; 247 | int stringLen = min( len - start, allowedLen ); 248 | 249 | // trim the length so it doesn't end in middle of a word 250 | if ( stringLen == allowedLen ) 251 | while ( stringLen >= 0 && 252 | s[stringLen+start] != ' ' && 253 | s[stringLen+start] != ',' && 254 | s[stringLen+start] != '|' ) 255 | stringLen--; 256 | 257 | // ok, the word is longer than the line, so just split 258 | // wherever the line ends 259 | if ( stringLen <= 0 ) 260 | stringLen = allowedLen; 261 | 262 | // check for newlines 263 | for ( int i = 0; i < stringLen; i++ ) 264 | if ( s[start+i] == '\n' ) 265 | stringLen = i+1; 266 | 267 | // print the indent 268 | for ( int i = 0; i < indentSpaces; i++ ) 269 | os << " "; 270 | 271 | if ( start == 0 ) 272 | { 273 | // handle second line offsets 274 | indentSpaces += secondLineOffset; 275 | 276 | // adjust allowed len 277 | allowedLen -= secondLineOffset; 278 | } 279 | 280 | os << s.substr(start,stringLen) << std::endl; 281 | 282 | // so we don't start a line with a space 283 | while ( s[stringLen+start] == ' ' && start < len ) 284 | start++; 285 | 286 | start += stringLen; 287 | } 288 | } 289 | else 290 | { 291 | for ( int i = 0; i < indentSpaces; i++ ) 292 | os << " "; 293 | os << s << std::endl; 294 | } 295 | } 296 | 297 | } //namespace TCLAP 298 | #endif 299 | -------------------------------------------------------------------------------- /tclap/SwitchArg.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: SwitchArg.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | 24 | #ifndef TCLAP_SWITCH_ARG_H 25 | #define TCLAP_SWITCH_ARG_H 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | namespace TCLAP { 33 | 34 | /** 35 | * A simple switch argument. If the switch is set on the command line, then 36 | * the getValue method will return the opposite of the default value for the 37 | * switch. 38 | */ 39 | class SwitchArg : public Arg 40 | { 41 | protected: 42 | 43 | /** 44 | * The value of the switch. 45 | */ 46 | bool _value; 47 | 48 | /** 49 | * Used to support the reset() method so that ValueArg can be 50 | * reset to their constructed value. 51 | */ 52 | bool _default; 53 | 54 | public: 55 | 56 | /** 57 | * SwitchArg constructor. 58 | * \param flag - The one character flag that identifies this 59 | * argument on the command line. 60 | * \param name - A one word name for the argument. Can be 61 | * used as a long flag on the command line. 62 | * \param desc - A description of what the argument is for or 63 | * does. 64 | * \param def - The default value for this Switch. 65 | * \param v - An optional visitor. You probably should not 66 | * use this unless you have a very good reason. 67 | */ 68 | SwitchArg(const std::string& flag, 69 | const std::string& name, 70 | const std::string& desc, 71 | bool def = false, 72 | Visitor* v = NULL); 73 | 74 | 75 | /** 76 | * SwitchArg constructor. 77 | * \param flag - The one character flag that identifies this 78 | * argument on the command line. 79 | * \param name - A one word name for the argument. Can be 80 | * used as a long flag on the command line. 81 | * \param desc - A description of what the argument is for or 82 | * does. 83 | * \param parser - A CmdLine parser object to add this Arg to 84 | * \param def - The default value for this Switch. 85 | * \param v - An optional visitor. You probably should not 86 | * use this unless you have a very good reason. 87 | */ 88 | SwitchArg(const std::string& flag, 89 | const std::string& name, 90 | const std::string& desc, 91 | CmdLineInterface& parser, 92 | bool def = false, 93 | Visitor* v = NULL); 94 | 95 | 96 | /** 97 | * Handles the processing of the argument. 98 | * This re-implements the Arg version of this method to set the 99 | * _value of the argument appropriately. 100 | * \param i - Pointer the the current argument in the list. 101 | * \param args - Mutable list of strings. Passed 102 | * in from main(). 103 | */ 104 | virtual bool processArg(int* i, std::vector& args); 105 | 106 | /** 107 | * Checks a string to see if any of the chars in the string 108 | * match the flag for this Switch. 109 | */ 110 | bool combinedSwitchesMatch(std::string& combined); 111 | 112 | /** 113 | * Returns bool, whether or not the switch has been set. 114 | */ 115 | bool getValue(); 116 | 117 | virtual void reset(); 118 | 119 | private: 120 | /** 121 | * Checks to see if we've found the last match in 122 | * a combined string. 123 | */ 124 | bool lastCombined(std::string& combined); 125 | 126 | /** 127 | * Does the common processing of processArg. 128 | */ 129 | void commonProcessing(); 130 | }; 131 | 132 | ////////////////////////////////////////////////////////////////////// 133 | //BEGIN SwitchArg.cpp 134 | ////////////////////////////////////////////////////////////////////// 135 | inline SwitchArg::SwitchArg(const std::string& flag, 136 | const std::string& name, 137 | const std::string& desc, 138 | bool default_val, 139 | Visitor* v ) 140 | : Arg(flag, name, desc, false, false, v), 141 | _value( default_val ), 142 | _default( default_val ) 143 | { } 144 | 145 | inline SwitchArg::SwitchArg(const std::string& flag, 146 | const std::string& name, 147 | const std::string& desc, 148 | CmdLineInterface& parser, 149 | bool default_val, 150 | Visitor* v ) 151 | : Arg(flag, name, desc, false, false, v), 152 | _value( default_val ), 153 | _default(default_val) 154 | { 155 | parser.add( this ); 156 | } 157 | 158 | inline bool SwitchArg::getValue() { return _value; } 159 | 160 | inline bool SwitchArg::lastCombined(std::string& combinedSwitches ) 161 | { 162 | for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) 163 | if ( combinedSwitches[i] != Arg::blankChar() ) 164 | return false; 165 | 166 | return true; 167 | } 168 | 169 | inline bool SwitchArg::combinedSwitchesMatch(std::string& combinedSwitches ) 170 | { 171 | // make sure this is actually a combined switch 172 | if ( combinedSwitches.length() > 0 && 173 | combinedSwitches[0] != Arg::flagStartString()[0] ) 174 | return false; 175 | 176 | // make sure it isn't a long name 177 | if ( combinedSwitches.substr( 0, Arg::nameStartString().length() ) == 178 | Arg::nameStartString() ) 179 | return false; 180 | 181 | // make sure the delimiter isn't in the string 182 | if ( combinedSwitches.find_first_of( Arg::delimiter() ) != std::string::npos ) 183 | return false; 184 | 185 | // ok, we're not specifying a ValueArg, so we know that we have 186 | // a combined switch list. 187 | for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) 188 | if ( _flag.length() > 0 && 189 | combinedSwitches[i] == _flag[0] && 190 | _flag[0] != Arg::flagStartString()[0] ) 191 | { 192 | // update the combined switches so this one is no longer present 193 | // this is necessary so that no unlabeled args are matched 194 | // later in the processing. 195 | //combinedSwitches.erase(i,1); 196 | combinedSwitches[i] = Arg::blankChar(); 197 | return true; 198 | } 199 | 200 | // none of the switches passed in the list match. 201 | return false; 202 | } 203 | 204 | inline void SwitchArg::commonProcessing() 205 | { 206 | if ( _xorSet ) 207 | throw(CmdLineParseException( 208 | "Mutually exclusive argument already set!", toString())); 209 | 210 | if ( _alreadySet ) 211 | throw(CmdLineParseException("Argument already set!", toString())); 212 | 213 | _alreadySet = true; 214 | 215 | if ( _value == true ) 216 | _value = false; 217 | else 218 | _value = true; 219 | 220 | _checkWithVisitor(); 221 | } 222 | 223 | inline bool SwitchArg::processArg(int *i, std::vector& args) 224 | { 225 | if ( _ignoreable && Arg::ignoreRest() ) 226 | return false; 227 | 228 | // if the whole string matches the flag or name string 229 | if ( argMatches( args[*i] ) ) 230 | { 231 | commonProcessing(); 232 | 233 | return true; 234 | } 235 | // if a substring matches the flag as part of a combination 236 | else if ( combinedSwitchesMatch( args[*i] ) ) 237 | { 238 | // check again to ensure we don't misinterpret 239 | // this as a MultiSwitchArg 240 | if ( combinedSwitchesMatch( args[*i] ) ) 241 | throw(CmdLineParseException("Argument already set!", 242 | toString())); 243 | 244 | commonProcessing(); 245 | 246 | // We only want to return true if we've found the last combined 247 | // match in the string, otherwise we return true so that other 248 | // switches in the combination will have a chance to match. 249 | return lastCombined( args[*i] ); 250 | } 251 | else 252 | return false; 253 | } 254 | 255 | inline void SwitchArg::reset() 256 | { 257 | Arg::reset(); 258 | _value = _default; 259 | } 260 | ////////////////////////////////////////////////////////////////////// 261 | //End SwitchArg.cpp 262 | ////////////////////////////////////////////////////////////////////// 263 | 264 | } //namespace TCLAP 265 | 266 | #endif 267 | -------------------------------------------------------------------------------- /tclap/UnlabeledMultiArg.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: UnlabeledMultiArg.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot. 7 | * All rights reverved. 8 | * 9 | * See the file COPYING in the top directory of this distribution for 10 | * more information. 11 | * 12 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 18 | * DEALINGS IN THE SOFTWARE. 19 | * 20 | *****************************************************************************/ 21 | 22 | 23 | #ifndef TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H 24 | #define TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | namespace TCLAP { 33 | 34 | /** 35 | * Just like a MultiArg, except that the arguments are unlabeled. Basically, 36 | * this Arg will slurp up everything that hasn't been matched to another 37 | * Arg. 38 | */ 39 | template 40 | class UnlabeledMultiArg : public MultiArg 41 | { 42 | 43 | // If compiler has two stage name lookup (as gcc >= 3.4 does) 44 | // this is requried to prevent undef. symbols 45 | using MultiArg::_ignoreable; 46 | using MultiArg::_hasBlanks; 47 | using MultiArg::_extractValue; 48 | using MultiArg::_typeDesc; 49 | using MultiArg::_name; 50 | using MultiArg::_description; 51 | using MultiArg::_alreadySet; 52 | using MultiArg::toString; 53 | 54 | public: 55 | 56 | /** 57 | * Constructor. 58 | * \param name - The name of the Arg. Note that this is used for 59 | * identification, not as a long flag. 60 | * \param desc - A description of what the argument is for or 61 | * does. 62 | * \param req - Whether the argument is required on the command 63 | * line. 64 | * \param typeDesc - A short, human readable description of the 65 | * type that this object expects. This is used in the generation 66 | * of the USAGE statement. The goal is to be helpful to the end user 67 | * of the program. 68 | * \param ignoreable - Whether or not this argument can be ignored 69 | * using the "--" flag. 70 | * \param v - An optional visitor. You probably should not 71 | * use this unless you have a very good reason. 72 | */ 73 | UnlabeledMultiArg( const std::string& name, 74 | const std::string& desc, 75 | bool req, 76 | const std::string& typeDesc, 77 | bool ignoreable = false, 78 | Visitor* v = NULL ); 79 | /** 80 | * Constructor. 81 | * \param name - The name of the Arg. Note that this is used for 82 | * identification, not as a long flag. 83 | * \param desc - A description of what the argument is for or 84 | * does. 85 | * \param req - Whether the argument is required on the command 86 | * line. 87 | * \param typeDesc - A short, human readable description of the 88 | * type that this object expects. This is used in the generation 89 | * of the USAGE statement. The goal is to be helpful to the end user 90 | * of the program. 91 | * \param parser - A CmdLine parser object to add this Arg to 92 | * \param ignoreable - Whether or not this argument can be ignored 93 | * using the "--" flag. 94 | * \param v - An optional visitor. You probably should not 95 | * use this unless you have a very good reason. 96 | */ 97 | UnlabeledMultiArg( const std::string& name, 98 | const std::string& desc, 99 | bool req, 100 | const std::string& typeDesc, 101 | CmdLineInterface& parser, 102 | bool ignoreable = false, 103 | Visitor* v = NULL ); 104 | 105 | /** 106 | * Constructor. 107 | * \param name - The name of the Arg. Note that this is used for 108 | * identification, not as a long flag. 109 | * \param desc - A description of what the argument is for or 110 | * does. 111 | * \param req - Whether the argument is required on the command 112 | * line. 113 | * \param constraint - A pointer to a Constraint object used 114 | * to constrain this Arg. 115 | * \param ignoreable - Whether or not this argument can be ignored 116 | * using the "--" flag. 117 | * \param v - An optional visitor. You probably should not 118 | * use this unless you have a very good reason. 119 | */ 120 | UnlabeledMultiArg( const std::string& name, 121 | const std::string& desc, 122 | bool req, 123 | Constraint* constraint, 124 | bool ignoreable = false, 125 | Visitor* v = NULL ); 126 | 127 | /** 128 | * Constructor. 129 | * \param name - The name of the Arg. Note that this is used for 130 | * identification, not as a long flag. 131 | * \param desc - A description of what the argument is for or 132 | * does. 133 | * \param req - Whether the argument is required on the command 134 | * line. 135 | * \param constraint - A pointer to a Constraint object used 136 | * to constrain this Arg. 137 | * \param parser - A CmdLine parser object to add this Arg to 138 | * \param ignoreable - Whether or not this argument can be ignored 139 | * using the "--" flag. 140 | * \param v - An optional visitor. You probably should not 141 | * use this unless you have a very good reason. 142 | */ 143 | UnlabeledMultiArg( const std::string& name, 144 | const std::string& desc, 145 | bool req, 146 | Constraint* constraint, 147 | CmdLineInterface& parser, 148 | bool ignoreable = false, 149 | Visitor* v = NULL ); 150 | 151 | /** 152 | * Handles the processing of the argument. 153 | * This re-implements the Arg version of this method to set the 154 | * _value of the argument appropriately. It knows the difference 155 | * between labeled and unlabeled. 156 | * \param i - Pointer the the current argument in the list. 157 | * \param args - Mutable list of strings. Passed from main(). 158 | */ 159 | virtual bool processArg(int* i, std::vector& args); 160 | 161 | /** 162 | * Returns the a short id string. Used in the usage. 163 | * \param val - value to be used. 164 | */ 165 | virtual std::string shortID(const std::string& val="val") const; 166 | 167 | /** 168 | * Returns the a long id string. Used in the usage. 169 | * \param val - value to be used. 170 | */ 171 | virtual std::string longID(const std::string& val="val") const; 172 | 173 | /** 174 | * Opertor ==. 175 | * \param a - The Arg to be compared to this. 176 | */ 177 | virtual bool operator==(const Arg& a) const; 178 | 179 | /** 180 | * Pushes this to back of list rather than front. 181 | * \param argList - The list this should be added to. 182 | */ 183 | virtual void addToList( std::list& argList ) const; 184 | }; 185 | 186 | template 187 | UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, 188 | const std::string& desc, 189 | bool req, 190 | const std::string& typeDesc, 191 | bool ignoreable, 192 | Visitor* v) 193 | : MultiArg("", name, desc, req, typeDesc, v) 194 | { 195 | _ignoreable = ignoreable; 196 | OptionalUnlabeledTracker::check(true, toString()); 197 | } 198 | 199 | template 200 | UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, 201 | const std::string& desc, 202 | bool req, 203 | const std::string& typeDesc, 204 | CmdLineInterface& parser, 205 | bool ignoreable, 206 | Visitor* v) 207 | : MultiArg("", name, desc, req, typeDesc, v) 208 | { 209 | _ignoreable = ignoreable; 210 | OptionalUnlabeledTracker::check(true, toString()); 211 | parser.add( this ); 212 | } 213 | 214 | 215 | template 216 | UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, 217 | const std::string& desc, 218 | bool req, 219 | Constraint* constraint, 220 | bool ignoreable, 221 | Visitor* v) 222 | : MultiArg("", name, desc, req, constraint, v) 223 | { 224 | _ignoreable = ignoreable; 225 | OptionalUnlabeledTracker::check(true, toString()); 226 | } 227 | 228 | template 229 | UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, 230 | const std::string& desc, 231 | bool req, 232 | Constraint* constraint, 233 | CmdLineInterface& parser, 234 | bool ignoreable, 235 | Visitor* v) 236 | : MultiArg("", name, desc, req, constraint, v) 237 | { 238 | _ignoreable = ignoreable; 239 | OptionalUnlabeledTracker::check(true, toString()); 240 | parser.add( this ); 241 | } 242 | 243 | 244 | template 245 | bool UnlabeledMultiArg::processArg(int *i, std::vector& args) 246 | { 247 | 248 | if ( _hasBlanks( args[*i] ) ) 249 | return false; 250 | 251 | // never ignore an unlabeled multi arg 252 | 253 | 254 | // always take the first value, regardless of the start string 255 | _extractValue( args[(*i)] ); 256 | 257 | /* 258 | // continue taking args until we hit the end or a start string 259 | while ( (unsigned int)(*i)+1 < args.size() && 260 | args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && 261 | args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) 262 | _extractValue( args[++(*i)] ); 263 | */ 264 | 265 | _alreadySet = true; 266 | 267 | return true; 268 | } 269 | 270 | template 271 | std::string UnlabeledMultiArg::shortID(const std::string& val) const 272 | { 273 | static_cast(val); // Ignore input, don't warn 274 | return std::string("<") + _typeDesc + "> ..."; 275 | } 276 | 277 | template 278 | std::string UnlabeledMultiArg::longID(const std::string& val) const 279 | { 280 | static_cast(val); // Ignore input, don't warn 281 | return std::string("<") + _typeDesc + "> (accepted multiple times)"; 282 | } 283 | 284 | template 285 | bool UnlabeledMultiArg::operator==(const Arg& a) const 286 | { 287 | if ( _name == a.getName() || _description == a.getDescription() ) 288 | return true; 289 | else 290 | return false; 291 | } 292 | 293 | template 294 | void UnlabeledMultiArg::addToList( std::list& argList ) const 295 | { 296 | argList.push_back( const_cast(static_cast(this)) ); 297 | } 298 | 299 | } 300 | 301 | #endif 302 | -------------------------------------------------------------------------------- /tclap/UnlabeledValueArg.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: UnlabeledValueArg.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | 24 | #ifndef TCLAP_UNLABELED_VALUE_ARGUMENT_H 25 | #define TCLAP_UNLABELED_VALUE_ARGUMENT_H 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | 34 | namespace TCLAP { 35 | 36 | /** 37 | * The basic unlabeled argument that parses a value. 38 | * This is a template class, which means the type T defines the type 39 | * that a given object will attempt to parse when an UnlabeledValueArg 40 | * is reached in the list of args that the CmdLine iterates over. 41 | */ 42 | template 43 | class UnlabeledValueArg : public ValueArg 44 | { 45 | 46 | // If compiler has two stage name lookup (as gcc >= 3.4 does) 47 | // this is requried to prevent undef. symbols 48 | using ValueArg::_ignoreable; 49 | using ValueArg::_hasBlanks; 50 | using ValueArg::_extractValue; 51 | using ValueArg::_typeDesc; 52 | using ValueArg::_name; 53 | using ValueArg::_description; 54 | using ValueArg::_alreadySet; 55 | using ValueArg::toString; 56 | 57 | public: 58 | 59 | /** 60 | * UnlabeledValueArg constructor. 61 | * \param name - A one word name for the argument. Note that this is used for 62 | * identification, not as a long flag. 63 | * \param desc - A description of what the argument is for or 64 | * does. 65 | * \param req - Whether the argument is required on the command 66 | * line. 67 | * \param value - The default value assigned to this argument if it 68 | * is not present on the command line. 69 | * \param typeDesc - A short, human readable description of the 70 | * type that this object expects. This is used in the generation 71 | * of the USAGE statement. The goal is to be helpful to the end user 72 | * of the program. 73 | * \param ignoreable - Allows you to specify that this argument can be 74 | * ignored if the '--' flag is set. This defaults to false (cannot 75 | * be ignored) and should generally stay that way unless you have 76 | * some special need for certain arguments to be ignored. 77 | * \param v - Optional Vistor. You should leave this blank unless 78 | * you have a very good reason. 79 | */ 80 | UnlabeledValueArg( const std::string& name, 81 | const std::string& desc, 82 | bool req, 83 | T value, 84 | const std::string& typeDesc, 85 | bool ignoreable = false, 86 | Visitor* v = NULL); 87 | 88 | /** 89 | * UnlabeledValueArg constructor. 90 | * \param name - A one word name for the argument. Note that this is used for 91 | * identification, not as a long flag. 92 | * \param desc - A description of what the argument is for or 93 | * does. 94 | * \param req - Whether the argument is required on the command 95 | * line. 96 | * \param value - The default value assigned to this argument if it 97 | * is not present on the command line. 98 | * \param typeDesc - A short, human readable description of the 99 | * type that this object expects. This is used in the generation 100 | * of the USAGE statement. The goal is to be helpful to the end user 101 | * of the program. 102 | * \param parser - A CmdLine parser object to add this Arg to 103 | * \param ignoreable - Allows you to specify that this argument can be 104 | * ignored if the '--' flag is set. This defaults to false (cannot 105 | * be ignored) and should generally stay that way unless you have 106 | * some special need for certain arguments to be ignored. 107 | * \param v - Optional Vistor. You should leave this blank unless 108 | * you have a very good reason. 109 | */ 110 | UnlabeledValueArg( const std::string& name, 111 | const std::string& desc, 112 | bool req, 113 | T value, 114 | const std::string& typeDesc, 115 | CmdLineInterface& parser, 116 | bool ignoreable = false, 117 | Visitor* v = NULL ); 118 | 119 | /** 120 | * UnlabeledValueArg constructor. 121 | * \param name - A one word name for the argument. Note that this is used for 122 | * identification, not as a long flag. 123 | * \param desc - A description of what the argument is for or 124 | * does. 125 | * \param req - Whether the argument is required on the command 126 | * line. 127 | * \param value - The default value assigned to this argument if it 128 | * is not present on the command line. 129 | * \param constraint - A pointer to a Constraint object used 130 | * to constrain this Arg. 131 | * \param ignoreable - Allows you to specify that this argument can be 132 | * ignored if the '--' flag is set. This defaults to false (cannot 133 | * be ignored) and should generally stay that way unless you have 134 | * some special need for certain arguments to be ignored. 135 | * \param v - Optional Vistor. You should leave this blank unless 136 | * you have a very good reason. 137 | */ 138 | UnlabeledValueArg( const std::string& name, 139 | const std::string& desc, 140 | bool req, 141 | T value, 142 | Constraint* constraint, 143 | bool ignoreable = false, 144 | Visitor* v = NULL ); 145 | 146 | 147 | /** 148 | * UnlabeledValueArg constructor. 149 | * \param name - A one word name for the argument. Note that this is used for 150 | * identification, not as a long flag. 151 | * \param desc - A description of what the argument is for or 152 | * does. 153 | * \param req - Whether the argument is required on the command 154 | * line. 155 | * \param value - The default value assigned to this argument if it 156 | * is not present on the command line. 157 | * \param constraint - A pointer to a Constraint object used 158 | * to constrain this Arg. 159 | * \param parser - A CmdLine parser object to add this Arg to 160 | * \param ignoreable - Allows you to specify that this argument can be 161 | * ignored if the '--' flag is set. This defaults to false (cannot 162 | * be ignored) and should generally stay that way unless you have 163 | * some special need for certain arguments to be ignored. 164 | * \param v - Optional Vistor. You should leave this blank unless 165 | * you have a very good reason. 166 | */ 167 | UnlabeledValueArg( const std::string& name, 168 | const std::string& desc, 169 | bool req, 170 | T value, 171 | Constraint* constraint, 172 | CmdLineInterface& parser, 173 | bool ignoreable = false, 174 | Visitor* v = NULL); 175 | 176 | /** 177 | * Handles the processing of the argument. 178 | * This re-implements the Arg version of this method to set the 179 | * _value of the argument appropriately. Handling specific to 180 | * unlabled arguments. 181 | * \param i - Pointer the the current argument in the list. 182 | * \param args - Mutable list of strings. 183 | */ 184 | virtual bool processArg(int* i, std::vector& args); 185 | 186 | /** 187 | * Overrides shortID for specific behavior. 188 | */ 189 | virtual std::string shortID(const std::string& val="val") const; 190 | 191 | /** 192 | * Overrides longID for specific behavior. 193 | */ 194 | virtual std::string longID(const std::string& val="val") const; 195 | 196 | /** 197 | * Overrides operator== for specific behavior. 198 | */ 199 | virtual bool operator==(const Arg& a ) const; 200 | 201 | /** 202 | * Instead of pushing to the front of list, push to the back. 203 | * \param argList - The list to add this to. 204 | */ 205 | virtual void addToList( std::list& argList ) const; 206 | 207 | }; 208 | 209 | /** 210 | * Constructor implemenation. 211 | */ 212 | template 213 | UnlabeledValueArg::UnlabeledValueArg(const std::string& name, 214 | const std::string& desc, 215 | bool req, 216 | T val, 217 | const std::string& typeDesc, 218 | bool ignoreable, 219 | Visitor* v) 220 | : ValueArg("", name, desc, req, val, typeDesc, v) 221 | { 222 | _ignoreable = ignoreable; 223 | 224 | OptionalUnlabeledTracker::check(req, toString()); 225 | 226 | } 227 | 228 | template 229 | UnlabeledValueArg::UnlabeledValueArg(const std::string& name, 230 | const std::string& desc, 231 | bool req, 232 | T val, 233 | const std::string& typeDesc, 234 | CmdLineInterface& parser, 235 | bool ignoreable, 236 | Visitor* v) 237 | : ValueArg("", name, desc, req, val, typeDesc, v) 238 | { 239 | _ignoreable = ignoreable; 240 | OptionalUnlabeledTracker::check(req, toString()); 241 | parser.add( this ); 242 | } 243 | 244 | /** 245 | * Constructor implemenation. 246 | */ 247 | template 248 | UnlabeledValueArg::UnlabeledValueArg(const std::string& name, 249 | const std::string& desc, 250 | bool req, 251 | T val, 252 | Constraint* constraint, 253 | bool ignoreable, 254 | Visitor* v) 255 | : ValueArg("", name, desc, req, val, constraint, v) 256 | { 257 | _ignoreable = ignoreable; 258 | OptionalUnlabeledTracker::check(req, toString()); 259 | } 260 | 261 | template 262 | UnlabeledValueArg::UnlabeledValueArg(const std::string& name, 263 | const std::string& desc, 264 | bool req, 265 | T val, 266 | Constraint* constraint, 267 | CmdLineInterface& parser, 268 | bool ignoreable, 269 | Visitor* v) 270 | : ValueArg("", name, desc, req, val, constraint, v) 271 | { 272 | _ignoreable = ignoreable; 273 | OptionalUnlabeledTracker::check(req, toString()); 274 | parser.add( this ); 275 | } 276 | 277 | /** 278 | * Implementation of processArg(). 279 | */ 280 | template 281 | bool UnlabeledValueArg::processArg(int *i, std::vector& args) 282 | { 283 | 284 | if ( _alreadySet ) 285 | return false; 286 | 287 | if ( _hasBlanks( args[*i] ) ) 288 | return false; 289 | 290 | // never ignore an unlabeled arg 291 | 292 | _extractValue( args[*i] ); 293 | _alreadySet = true; 294 | return true; 295 | } 296 | 297 | /** 298 | * Overriding shortID for specific output. 299 | */ 300 | template 301 | std::string UnlabeledValueArg::shortID(const std::string& val) const 302 | { 303 | static_cast(val); // Ignore input, don't warn 304 | return std::string("<") + _typeDesc + ">"; 305 | } 306 | 307 | /** 308 | * Overriding longID for specific output. 309 | */ 310 | template 311 | std::string UnlabeledValueArg::longID(const std::string& val) const 312 | { 313 | static_cast(val); // Ignore input, don't warn 314 | 315 | // Ideally we would like to be able to use RTTI to return the name 316 | // of the type required for this argument. However, g++ at least, 317 | // doesn't appear to return terribly useful "names" of the types. 318 | return std::string("<") + _typeDesc + ">"; 319 | } 320 | 321 | /** 322 | * Overriding operator== for specific behavior. 323 | */ 324 | template 325 | bool UnlabeledValueArg::operator==(const Arg& a ) const 326 | { 327 | if ( _name == a.getName() || _description == a.getDescription() ) 328 | return true; 329 | else 330 | return false; 331 | } 332 | 333 | template 334 | void UnlabeledValueArg::addToList( std::list& argList ) const 335 | { 336 | argList.push_back( const_cast(static_cast(this)) ); 337 | } 338 | 339 | } 340 | #endif 341 | -------------------------------------------------------------------------------- /tclap/ValueArg.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * file: ValueArg.h 4 | * 5 | * Copyright (c) 2003, Michael E. Smoot . 6 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 7 | * All rights reverved. 8 | * 9 | * See the file COPYING in the top directory of this distribution for 10 | * more information. 11 | * 12 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 18 | * DEALINGS IN THE SOFTWARE. 19 | * 20 | *****************************************************************************/ 21 | 22 | 23 | #ifndef TCLAP_VALUE_ARGUMENT_H 24 | #define TCLAP_VALUE_ARGUMENT_H 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | namespace TCLAP { 33 | 34 | /** 35 | * The basic labeled argument that parses a value. 36 | * This is a template class, which means the type T defines the type 37 | * that a given object will attempt to parse when the flag/name is matched 38 | * on the command line. While there is nothing stopping you from creating 39 | * an unflagged ValueArg, it is unwise and would cause significant problems. 40 | * Instead use an UnlabeledValueArg. 41 | */ 42 | template 43 | class ValueArg : public Arg 44 | { 45 | protected: 46 | 47 | /** 48 | * The value parsed from the command line. 49 | * Can be of any type, as long as the >> operator for the type 50 | * is defined. 51 | */ 52 | T _value; 53 | 54 | /** 55 | * Used to support the reset() method so that ValueArg can be 56 | * reset to their constructed value. 57 | */ 58 | T _default; 59 | 60 | /** 61 | * A human readable description of the type to be parsed. 62 | * This is a hack, plain and simple. Ideally we would use RTTI to 63 | * return the name of type T, but until there is some sort of 64 | * consistent support for human readable names, we are left to our 65 | * own devices. 66 | */ 67 | std::string _typeDesc; 68 | 69 | /** 70 | * A Constraint this Arg must conform to. 71 | */ 72 | Constraint* _constraint; 73 | 74 | /** 75 | * Extracts the value from the string. 76 | * Attempts to parse string as type T, if this fails an exception 77 | * is thrown. 78 | * \param val - value to be parsed. 79 | */ 80 | void _extractValue( const std::string& val ); 81 | 82 | public: 83 | 84 | /** 85 | * Labeled ValueArg constructor. 86 | * You could conceivably call this constructor with a blank flag, 87 | * but that would make you a bad person. It would also cause 88 | * an exception to be thrown. If you want an unlabeled argument, 89 | * use the other constructor. 90 | * \param flag - The one character flag that identifies this 91 | * argument on the command line. 92 | * \param name - A one word name for the argument. Can be 93 | * used as a long flag on the command line. 94 | * \param desc - A description of what the argument is for or 95 | * does. 96 | * \param req - Whether the argument is required on the command 97 | * line. 98 | * \param value - The default value assigned to this argument if it 99 | * is not present on the command line. 100 | * \param typeDesc - A short, human readable description of the 101 | * type that this object expects. This is used in the generation 102 | * of the USAGE statement. The goal is to be helpful to the end user 103 | * of the program. 104 | * \param v - An optional visitor. You probably should not 105 | * use this unless you have a very good reason. 106 | */ 107 | ValueArg( const std::string& flag, 108 | const std::string& name, 109 | const std::string& desc, 110 | bool req, 111 | T value, 112 | const std::string& typeDesc, 113 | Visitor* v = NULL); 114 | 115 | 116 | /** 117 | * Labeled ValueArg constructor. 118 | * You could conceivably call this constructor with a blank flag, 119 | * but that would make you a bad person. It would also cause 120 | * an exception to be thrown. If you want an unlabeled argument, 121 | * use the other constructor. 122 | * \param flag - The one character flag that identifies this 123 | * argument on the command line. 124 | * \param name - A one word name for the argument. Can be 125 | * used as a long flag on the command line. 126 | * \param desc - A description of what the argument is for or 127 | * does. 128 | * \param req - Whether the argument is required on the command 129 | * line. 130 | * \param value - The default value assigned to this argument if it 131 | * is not present on the command line. 132 | * \param typeDesc - A short, human readable description of the 133 | * type that this object expects. This is used in the generation 134 | * of the USAGE statement. The goal is to be helpful to the end user 135 | * of the program. 136 | * \param parser - A CmdLine parser object to add this Arg to 137 | * \param v - An optional visitor. You probably should not 138 | * use this unless you have a very good reason. 139 | */ 140 | ValueArg( const std::string& flag, 141 | const std::string& name, 142 | const std::string& desc, 143 | bool req, 144 | T value, 145 | const std::string& typeDesc, 146 | CmdLineInterface& parser, 147 | Visitor* v = NULL ); 148 | 149 | /** 150 | * Labeled ValueArg constructor. 151 | * You could conceivably call this constructor with a blank flag, 152 | * but that would make you a bad person. It would also cause 153 | * an exception to be thrown. If you want an unlabeled argument, 154 | * use the other constructor. 155 | * \param flag - The one character flag that identifies this 156 | * argument on the command line. 157 | * \param name - A one word name for the argument. Can be 158 | * used as a long flag on the command line. 159 | * \param desc - A description of what the argument is for or 160 | * does. 161 | * \param req - Whether the argument is required on the command 162 | * line. 163 | * \param value - The default value assigned to this argument if it 164 | * is not present on the command line. 165 | * \param constraint - A pointer to a Constraint object used 166 | * to constrain this Arg. 167 | * \param parser - A CmdLine parser object to add this Arg to. 168 | * \param v - An optional visitor. You probably should not 169 | * use this unless you have a very good reason. 170 | */ 171 | ValueArg( const std::string& flag, 172 | const std::string& name, 173 | const std::string& desc, 174 | bool req, 175 | T value, 176 | Constraint* constraint, 177 | CmdLineInterface& parser, 178 | Visitor* v = NULL ); 179 | 180 | /** 181 | * Labeled ValueArg constructor. 182 | * You could conceivably call this constructor with a blank flag, 183 | * but that would make you a bad person. It would also cause 184 | * an exception to be thrown. If you want an unlabeled argument, 185 | * use the other constructor. 186 | * \param flag - The one character flag that identifies this 187 | * argument on the command line. 188 | * \param name - A one word name for the argument. Can be 189 | * used as a long flag on the command line. 190 | * \param desc - A description of what the argument is for or 191 | * does. 192 | * \param req - Whether the argument is required on the command 193 | * line. 194 | * \param value - The default value assigned to this argument if it 195 | * is not present on the command line. 196 | * \param constraint - A pointer to a Constraint object used 197 | * to constrain this Arg. 198 | * \param v - An optional visitor. You probably should not 199 | * use this unless you have a very good reason. 200 | */ 201 | ValueArg( const std::string& flag, 202 | const std::string& name, 203 | const std::string& desc, 204 | bool req, 205 | T value, 206 | Constraint* constraint, 207 | Visitor* v = NULL ); 208 | 209 | /** 210 | * Handles the processing of the argument. 211 | * This re-implements the Arg version of this method to set the 212 | * _value of the argument appropriately. It knows the difference 213 | * between labeled and unlabeled. 214 | * \param i - Pointer the the current argument in the list. 215 | * \param args - Mutable list of strings. Passed 216 | * in from main(). 217 | */ 218 | virtual bool processArg(int* i, std::vector& args); 219 | 220 | /** 221 | * Returns the value of the argument. 222 | */ 223 | T& getValue() ; 224 | 225 | /** 226 | * Specialization of shortID. 227 | * \param val - value to be used. 228 | */ 229 | virtual std::string shortID(const std::string& val = "val") const; 230 | 231 | /** 232 | * Specialization of longID. 233 | * \param val - value to be used. 234 | */ 235 | virtual std::string longID(const std::string& val = "val") const; 236 | 237 | virtual void reset() ; 238 | 239 | private: 240 | /** 241 | * Prevent accidental copying 242 | */ 243 | ValueArg(const ValueArg& rhs); 244 | ValueArg& operator=(const ValueArg& rhs); 245 | }; 246 | 247 | 248 | /** 249 | * Constructor implementation. 250 | */ 251 | template 252 | ValueArg::ValueArg(const std::string& flag, 253 | const std::string& name, 254 | const std::string& desc, 255 | bool req, 256 | T val, 257 | const std::string& typeDesc, 258 | Visitor* v) 259 | : Arg(flag, name, desc, req, true, v), 260 | _value( val ), 261 | _default( val ), 262 | _typeDesc( typeDesc ), 263 | _constraint( NULL ) 264 | { } 265 | 266 | template 267 | ValueArg::ValueArg(const std::string& flag, 268 | const std::string& name, 269 | const std::string& desc, 270 | bool req, 271 | T val, 272 | const std::string& typeDesc, 273 | CmdLineInterface& parser, 274 | Visitor* v) 275 | : Arg(flag, name, desc, req, true, v), 276 | _value( val ), 277 | _default( val ), 278 | _typeDesc( typeDesc ), 279 | _constraint( NULL ) 280 | { 281 | parser.add( this ); 282 | } 283 | 284 | template 285 | ValueArg::ValueArg(const std::string& flag, 286 | const std::string& name, 287 | const std::string& desc, 288 | bool req, 289 | T val, 290 | Constraint* constraint, 291 | Visitor* v) 292 | : Arg(flag, name, desc, req, true, v), 293 | _value( val ), 294 | _default( val ), 295 | _typeDesc( constraint->shortID() ), 296 | _constraint( constraint ) 297 | { } 298 | 299 | template 300 | ValueArg::ValueArg(const std::string& flag, 301 | const std::string& name, 302 | const std::string& desc, 303 | bool req, 304 | T val, 305 | Constraint* constraint, 306 | CmdLineInterface& parser, 307 | Visitor* v) 308 | : Arg(flag, name, desc, req, true, v), 309 | _value( val ), 310 | _default( val ), 311 | _typeDesc( constraint->shortID() ), 312 | _constraint( constraint ) 313 | { 314 | parser.add( this ); 315 | } 316 | 317 | 318 | /** 319 | * Implementation of getValue(). 320 | */ 321 | template 322 | T& ValueArg::getValue() { return _value; } 323 | 324 | /** 325 | * Implementation of processArg(). 326 | */ 327 | template 328 | bool ValueArg::processArg(int *i, std::vector& args) 329 | { 330 | if ( _ignoreable && Arg::ignoreRest() ) 331 | return false; 332 | 333 | if ( _hasBlanks( args[*i] ) ) 334 | return false; 335 | 336 | std::string flag = args[*i]; 337 | 338 | std::string value = ""; 339 | trimFlag( flag, value ); 340 | 341 | if ( argMatches( flag ) ) 342 | { 343 | if ( _alreadySet ) 344 | { 345 | if ( _xorSet ) 346 | throw( CmdLineParseException( 347 | "Mutually exclusive argument already set!", 348 | toString()) ); 349 | else 350 | throw( CmdLineParseException("Argument already set!", 351 | toString()) ); 352 | } 353 | 354 | if ( Arg::delimiter() != ' ' && value == "" ) 355 | throw( ArgParseException( 356 | "Couldn't find delimiter for this argument!", 357 | toString() ) ); 358 | 359 | if ( value == "" ) 360 | { 361 | (*i)++; 362 | if ( static_cast(*i) < args.size() ) 363 | _extractValue( args[*i] ); 364 | else 365 | throw( ArgParseException("Missing a value for this argument!", 366 | toString() ) ); 367 | } 368 | else 369 | _extractValue( value ); 370 | 371 | _alreadySet = true; 372 | _checkWithVisitor(); 373 | return true; 374 | } 375 | else 376 | return false; 377 | } 378 | 379 | /** 380 | * Implementation of shortID. 381 | */ 382 | template 383 | std::string ValueArg::shortID(const std::string& val) const 384 | { 385 | static_cast(val); // Ignore input, don't warn 386 | return Arg::shortID( _typeDesc ); 387 | } 388 | 389 | /** 390 | * Implementation of longID. 391 | */ 392 | template 393 | std::string ValueArg::longID(const std::string& val) const 394 | { 395 | static_cast(val); // Ignore input, don't warn 396 | return Arg::longID( _typeDesc ); 397 | } 398 | 399 | template 400 | void ValueArg::_extractValue( const std::string& val ) 401 | { 402 | try { 403 | ExtractValue(_value, val, typename ArgTraits::ValueCategory()); 404 | } catch( ArgParseException &e) { 405 | throw ArgParseException(e.error(), toString()); 406 | } 407 | 408 | if ( _constraint != NULL ) 409 | if ( ! _constraint->check( _value ) ) 410 | throw( CmdLineParseException( "Value '" + val + 411 | + "' does not meet constraint: " 412 | + _constraint->description(), 413 | toString() ) ); 414 | } 415 | 416 | template 417 | void ValueArg::reset() 418 | { 419 | Arg::reset(); 420 | _value = _default; 421 | } 422 | 423 | } // namespace TCLAP 424 | 425 | #endif 426 | -------------------------------------------------------------------------------- /tclap/ValuesConstraint.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | /****************************************************************************** 4 | * 5 | * file: ValuesConstraint.h 6 | * 7 | * Copyright (c) 2005, Michael E. Smoot 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_VALUESCONSTRAINT_H 24 | #define TCLAP_VALUESCONSTRAINT_H 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #ifdef HAVE_CONFIG_H 31 | #include 32 | #else 33 | #define HAVE_SSTREAM 34 | #endif 35 | 36 | #if defined(HAVE_SSTREAM) 37 | #include 38 | #elif defined(HAVE_STRSTREAM) 39 | #include 40 | #else 41 | #error "Need a stringstream (sstream or strstream) to compile!" 42 | #endif 43 | 44 | namespace TCLAP { 45 | 46 | /** 47 | * A Constraint that constrains the Arg to only those values specified 48 | * in the constraint. 49 | */ 50 | template 51 | class ValuesConstraint : public Constraint 52 | { 53 | 54 | public: 55 | 56 | /** 57 | * Constructor. 58 | * \param allowed - vector of allowed values. 59 | */ 60 | ValuesConstraint(std::vector& allowed); 61 | 62 | /** 63 | * Virtual destructor. 64 | */ 65 | virtual ~ValuesConstraint() {} 66 | 67 | /** 68 | * Returns a description of the Constraint. 69 | */ 70 | virtual std::string description() const; 71 | 72 | /** 73 | * Returns the short ID for the Constraint. 74 | */ 75 | virtual std::string shortID() const; 76 | 77 | /** 78 | * The method used to verify that the value parsed from the command 79 | * line meets the constraint. 80 | * \param value - The value that will be checked. 81 | */ 82 | virtual bool check(const T& value) const; 83 | 84 | protected: 85 | 86 | /** 87 | * The list of valid values. 88 | */ 89 | std::vector _allowed; 90 | 91 | /** 92 | * The string used to describe the allowed values of this constraint. 93 | */ 94 | std::string _typeDesc; 95 | 96 | }; 97 | 98 | template 99 | ValuesConstraint::ValuesConstraint(std::vector& allowed) 100 | : _allowed(allowed), 101 | _typeDesc("") 102 | { 103 | for ( unsigned int i = 0; i < _allowed.size(); i++ ) 104 | { 105 | 106 | #if defined(HAVE_SSTREAM) 107 | std::ostringstream os; 108 | #elif defined(HAVE_STRSTREAM) 109 | std::ostrstream os; 110 | #else 111 | #error "Need a stringstream (sstream or strstream) to compile!" 112 | #endif 113 | 114 | os << _allowed[i]; 115 | 116 | std::string temp( os.str() ); 117 | 118 | if ( i > 0 ) 119 | _typeDesc += "|"; 120 | _typeDesc += temp; 121 | } 122 | } 123 | 124 | template 125 | bool ValuesConstraint::check( const T& val ) const 126 | { 127 | if ( std::find(_allowed.begin(),_allowed.end(),val) == _allowed.end() ) 128 | return false; 129 | else 130 | return true; 131 | } 132 | 133 | template 134 | std::string ValuesConstraint::shortID() const 135 | { 136 | return _typeDesc; 137 | } 138 | 139 | template 140 | std::string ValuesConstraint::description() const 141 | { 142 | return _typeDesc; 143 | } 144 | 145 | 146 | } //namespace TCLAP 147 | #endif 148 | 149 | -------------------------------------------------------------------------------- /tclap/VersionVisitor.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: VersionVisitor.h 6 | * 7 | * Copyright (c) 2003, Michael E. Smoot . 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | 24 | #ifndef TCLAP_VERSION_VISITOR_H 25 | #define TCLAP_VERSION_VISITOR_H 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | namespace TCLAP { 32 | 33 | /** 34 | * A Vistor that will call the version method of the given CmdLineOutput 35 | * for the specified CmdLine object and then exit. 36 | */ 37 | class VersionVisitor: public Visitor 38 | { 39 | private: 40 | /** 41 | * Prevent accidental copying 42 | */ 43 | VersionVisitor(const VersionVisitor& rhs); 44 | VersionVisitor& operator=(const VersionVisitor& rhs); 45 | 46 | protected: 47 | 48 | /** 49 | * The CmdLine of interest. 50 | */ 51 | CmdLineInterface* _cmd; 52 | 53 | /** 54 | * The output object. 55 | */ 56 | CmdLineOutput** _out; 57 | 58 | public: 59 | 60 | /** 61 | * Constructor. 62 | * \param cmd - The CmdLine the output is generated for. 63 | * \param out - The type of output. 64 | */ 65 | VersionVisitor( CmdLineInterface* cmd, CmdLineOutput** out ) 66 | : Visitor(), _cmd( cmd ), _out( out ) { } 67 | 68 | /** 69 | * Calls the version method of the output object using the 70 | * specified CmdLine. 71 | */ 72 | void visit() { 73 | (*_out)->version(*_cmd); 74 | throw ExitException(0); 75 | } 76 | 77 | }; 78 | 79 | } 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /tclap/Visitor.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: Visitor.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * All rights reverved. 8 | * 9 | * See the file COPYING in the top directory of this distribution for 10 | * more information. 11 | * 12 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 18 | * DEALINGS IN THE SOFTWARE. 19 | * 20 | *****************************************************************************/ 21 | 22 | 23 | #ifndef TCLAP_VISITOR_H 24 | #define TCLAP_VISITOR_H 25 | 26 | namespace TCLAP { 27 | 28 | /** 29 | * A base class that defines the interface for visitors. 30 | */ 31 | class Visitor 32 | { 33 | public: 34 | 35 | /** 36 | * Constructor. Does nothing. 37 | */ 38 | Visitor() { } 39 | 40 | /** 41 | * Destructor. Does nothing. 42 | */ 43 | virtual ~Visitor() { } 44 | 45 | /** 46 | * Does nothing. Should be overridden by child. 47 | */ 48 | virtual void visit() { } 49 | }; 50 | 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /tclap/XorHandler.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: XorHandler.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_XORHANDLER_H 24 | #define TCLAP_XORHANDLER_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace TCLAP { 33 | 34 | /** 35 | * This class handles lists of Arg's that are to be XOR'd on the command 36 | * line. This is used by CmdLine and you shouldn't ever use it. 37 | */ 38 | class XorHandler 39 | { 40 | protected: 41 | 42 | /** 43 | * The list of of lists of Arg's to be or'd together. 44 | */ 45 | std::vector< std::vector > _orList; 46 | 47 | public: 48 | 49 | /** 50 | * Constructor. Does nothing. 51 | */ 52 | XorHandler( ) : _orList(std::vector< std::vector >()) {} 53 | 54 | /** 55 | * Add a list of Arg*'s that will be orred together. 56 | * \param ors - list of Arg* that will be xor'd. 57 | */ 58 | void add( std::vector& ors ); 59 | 60 | /** 61 | * Checks whether the specified Arg is in one of the xor lists and 62 | * if it does match one, returns the size of the xor list that the 63 | * Arg matched. If the Arg matches, then it also sets the rest of 64 | * the Arg's in the list. You shouldn't use this. 65 | * \param a - The Arg to be checked. 66 | */ 67 | int check( const Arg* a ); 68 | 69 | /** 70 | * Returns the XOR specific short usage. 71 | */ 72 | std::string shortUsage(); 73 | 74 | /** 75 | * Prints the XOR specific long usage. 76 | * \param os - Stream to print to. 77 | */ 78 | void printLongUsage(std::ostream& os); 79 | 80 | /** 81 | * Simply checks whether the Arg is contained in one of the arg 82 | * lists. 83 | * \param a - The Arg to be checked. 84 | */ 85 | bool contains( const Arg* a ); 86 | 87 | std::vector< std::vector >& getXorList(); 88 | 89 | }; 90 | 91 | 92 | ////////////////////////////////////////////////////////////////////// 93 | //BEGIN XOR.cpp 94 | ////////////////////////////////////////////////////////////////////// 95 | inline void XorHandler::add( std::vector& ors ) 96 | { 97 | _orList.push_back( ors ); 98 | } 99 | 100 | inline int XorHandler::check( const Arg* a ) 101 | { 102 | // iterate over each XOR list 103 | for ( int i = 0; static_cast(i) < _orList.size(); i++ ) 104 | { 105 | // if the XOR list contains the arg.. 106 | ArgVectorIterator ait = std::find( _orList[i].begin(), 107 | _orList[i].end(), a ); 108 | if ( ait != _orList[i].end() ) 109 | { 110 | // first check to see if a mutually exclusive switch 111 | // has not already been set 112 | for ( ArgVectorIterator it = _orList[i].begin(); 113 | it != _orList[i].end(); 114 | it++ ) 115 | if ( a != (*it) && (*it)->isSet() ) 116 | throw(CmdLineParseException( 117 | "Mutually exclusive argument already set!", 118 | (*it)->toString())); 119 | 120 | // go through and set each arg that is not a 121 | for ( ArgVectorIterator it = _orList[i].begin(); 122 | it != _orList[i].end(); 123 | it++ ) 124 | if ( a != (*it) ) 125 | (*it)->xorSet(); 126 | 127 | // return the number of required args that have now been set 128 | if ( (*ait)->allowMore() ) 129 | return 0; 130 | else 131 | return static_cast(_orList[i].size()); 132 | } 133 | } 134 | 135 | if ( a->isRequired() ) 136 | return 1; 137 | else 138 | return 0; 139 | } 140 | 141 | inline bool XorHandler::contains( const Arg* a ) 142 | { 143 | for ( int i = 0; static_cast(i) < _orList.size(); i++ ) 144 | for ( ArgVectorIterator it = _orList[i].begin(); 145 | it != _orList[i].end(); 146 | it++ ) 147 | if ( a == (*it) ) 148 | return true; 149 | 150 | return false; 151 | } 152 | 153 | inline std::vector< std::vector >& XorHandler::getXorList() 154 | { 155 | return _orList; 156 | } 157 | 158 | 159 | 160 | ////////////////////////////////////////////////////////////////////// 161 | //END XOR.cpp 162 | ////////////////////////////////////////////////////////////////////// 163 | 164 | } //namespace TCLAP 165 | 166 | #endif 167 | -------------------------------------------------------------------------------- /tclap/ZshCompletionOutput.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: ZshCompletionOutput.h 6 | * 7 | * Copyright (c) 2006, Oliver Kiddle 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_ZSHCOMPLETIONOUTPUT_H 24 | #define TCLAP_ZSHCOMPLETIONOUTPUT_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | namespace TCLAP { 38 | 39 | /** 40 | * A class that generates a Zsh completion function as output from the usage() 41 | * method for the given CmdLine and its Args. 42 | */ 43 | class ZshCompletionOutput : public CmdLineOutput 44 | { 45 | 46 | public: 47 | 48 | ZshCompletionOutput(); 49 | 50 | /** 51 | * Prints the usage to stdout. Can be overridden to 52 | * produce alternative behavior. 53 | * \param c - The CmdLine object the output is generated for. 54 | */ 55 | virtual void usage(CmdLineInterface& c); 56 | 57 | /** 58 | * Prints the version to stdout. Can be overridden 59 | * to produce alternative behavior. 60 | * \param c - The CmdLine object the output is generated for. 61 | */ 62 | virtual void version(CmdLineInterface& c); 63 | 64 | /** 65 | * Prints (to stderr) an error message, short usage 66 | * Can be overridden to produce alternative behavior. 67 | * \param c - The CmdLine object the output is generated for. 68 | * \param e - The ArgException that caused the failure. 69 | */ 70 | virtual void failure(CmdLineInterface& c, 71 | ArgException& e ); 72 | 73 | protected: 74 | 75 | void basename( std::string& s ); 76 | void quoteSpecialChars( std::string& s ); 77 | 78 | std::string getMutexList( CmdLineInterface& _cmd, Arg* a ); 79 | void printOption( Arg* it, std::string mutex ); 80 | void printArg( Arg* it ); 81 | 82 | std::map common; 83 | char theDelimiter; 84 | }; 85 | 86 | ZshCompletionOutput::ZshCompletionOutput() 87 | : common(std::map()), 88 | theDelimiter('=') 89 | { 90 | common["host"] = "_hosts"; 91 | common["hostname"] = "_hosts"; 92 | common["file"] = "_files"; 93 | common["filename"] = "_files"; 94 | common["user"] = "_users"; 95 | common["username"] = "_users"; 96 | common["directory"] = "_directories"; 97 | common["path"] = "_directories"; 98 | common["url"] = "_urls"; 99 | } 100 | 101 | inline void ZshCompletionOutput::version(CmdLineInterface& _cmd) 102 | { 103 | std::cout << _cmd.getVersion() << std::endl; 104 | } 105 | 106 | inline void ZshCompletionOutput::usage(CmdLineInterface& _cmd ) 107 | { 108 | std::list argList = _cmd.getArgList(); 109 | std::string progName = _cmd.getProgramName(); 110 | std::string xversion = _cmd.getVersion(); 111 | theDelimiter = _cmd.getDelimiter(); 112 | basename(progName); 113 | 114 | std::cout << "#compdef " << progName << std::endl << std::endl << 115 | "# " << progName << " version " << _cmd.getVersion() << std::endl << std::endl << 116 | "_arguments -s -S"; 117 | 118 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 119 | { 120 | if ( (*it)->shortID().at(0) == '<' ) 121 | printArg((*it)); 122 | else if ( (*it)->getFlag() != "-" ) 123 | printOption((*it), getMutexList(_cmd, *it)); 124 | } 125 | 126 | std::cout << std::endl; 127 | } 128 | 129 | inline void ZshCompletionOutput::failure( CmdLineInterface& _cmd, 130 | ArgException& e ) 131 | { 132 | static_cast(_cmd); // unused 133 | std::cout << e.what() << std::endl; 134 | } 135 | 136 | inline void ZshCompletionOutput::quoteSpecialChars( std::string& s ) 137 | { 138 | size_t idx = s.find_last_of(':'); 139 | while ( idx != std::string::npos ) 140 | { 141 | s.insert(idx, 1, '\\'); 142 | idx = s.find_last_of(':', idx); 143 | } 144 | idx = s.find_last_of('\''); 145 | while ( idx != std::string::npos ) 146 | { 147 | s.insert(idx, "'\\'"); 148 | if (idx == 0) 149 | idx = std::string::npos; 150 | else 151 | idx = s.find_last_of('\'', --idx); 152 | } 153 | } 154 | 155 | inline void ZshCompletionOutput::basename( std::string& s ) 156 | { 157 | size_t p = s.find_last_of('/'); 158 | if ( p != std::string::npos ) 159 | { 160 | s.erase(0, p + 1); 161 | } 162 | } 163 | 164 | inline void ZshCompletionOutput::printArg(Arg* a) 165 | { 166 | static int count = 1; 167 | 168 | std::cout << " \\" << std::endl << " '"; 169 | if ( a->acceptsMultipleValues() ) 170 | std::cout << '*'; 171 | else 172 | std::cout << count++; 173 | std::cout << ':'; 174 | if ( !a->isRequired() ) 175 | std::cout << ':'; 176 | 177 | std::cout << a->getName() << ':'; 178 | std::map::iterator compArg = common.find(a->getName()); 179 | if ( compArg != common.end() ) 180 | { 181 | std::cout << compArg->second; 182 | } 183 | else 184 | { 185 | std::cout << "_guard \"^-*\" " << a->getName(); 186 | } 187 | std::cout << '\''; 188 | } 189 | 190 | inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex) 191 | { 192 | std::string flag = a->flagStartChar() + a->getFlag(); 193 | std::string name = a->nameStartString() + a->getName(); 194 | std::string desc = a->getDescription(); 195 | 196 | // remove full stop and capitalisation from description as 197 | // this is the convention for zsh function 198 | if (!desc.compare(0, 12, "(required) ")) 199 | { 200 | desc.erase(0, 12); 201 | } 202 | if (!desc.compare(0, 15, "(OR required) ")) 203 | { 204 | desc.erase(0, 15); 205 | } 206 | size_t len = desc.length(); 207 | if (len && desc.at(--len) == '.') 208 | { 209 | desc.erase(len); 210 | } 211 | if (len) 212 | { 213 | desc.replace(0, 1, 1, tolower(desc.at(0))); 214 | } 215 | 216 | std::cout << " \\" << std::endl << " '" << mutex; 217 | 218 | if ( a->getFlag().empty() ) 219 | { 220 | std::cout << name; 221 | } 222 | else 223 | { 224 | std::cout << "'{" << flag << ',' << name << "}'"; 225 | } 226 | if ( theDelimiter == '=' && a->isValueRequired() ) 227 | std::cout << "=-"; 228 | quoteSpecialChars(desc); 229 | std::cout << '[' << desc << ']'; 230 | 231 | if ( a->isValueRequired() ) 232 | { 233 | std::string arg = a->shortID(); 234 | arg.erase(0, arg.find_last_of(theDelimiter) + 1); 235 | if ( arg.at(arg.length()-1) == ']' ) 236 | arg.erase(arg.length()-1); 237 | if ( arg.at(arg.length()-1) == ']' ) 238 | { 239 | arg.erase(arg.length()-1); 240 | } 241 | if ( arg.at(0) == '<' ) 242 | { 243 | arg.erase(arg.length()-1); 244 | arg.erase(0, 1); 245 | } 246 | size_t p = arg.find('|'); 247 | if ( p != std::string::npos ) 248 | { 249 | do 250 | { 251 | arg.replace(p, 1, 1, ' '); 252 | } 253 | while ( (p = arg.find_first_of('|', p)) != std::string::npos ); 254 | quoteSpecialChars(arg); 255 | std::cout << ": :(" << arg << ')'; 256 | } 257 | else 258 | { 259 | std::cout << ':' << arg; 260 | std::map::iterator compArg = common.find(arg); 261 | if ( compArg != common.end() ) 262 | { 263 | std::cout << ':' << compArg->second; 264 | } 265 | } 266 | } 267 | 268 | std::cout << '\''; 269 | } 270 | 271 | inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Arg* a) 272 | { 273 | XorHandler xorHandler = _cmd.getXorHandler(); 274 | std::vector< std::vector > xorList = xorHandler.getXorList(); 275 | 276 | if (a->getName() == "help" || a->getName() == "version") 277 | { 278 | return "(-)"; 279 | } 280 | 281 | std::ostringstream list; 282 | if ( a->acceptsMultipleValues() ) 283 | { 284 | list << '*'; 285 | } 286 | 287 | for ( int i = 0; static_cast(i) < xorList.size(); i++ ) 288 | { 289 | for ( ArgVectorIterator it = xorList[i].begin(); 290 | it != xorList[i].end(); 291 | it++) 292 | if ( a == (*it) ) 293 | { 294 | list << '('; 295 | for ( ArgVectorIterator iu = xorList[i].begin(); 296 | iu != xorList[i].end(); 297 | iu++ ) 298 | { 299 | bool notCur = (*iu) != a; 300 | bool hasFlag = !(*iu)->getFlag().empty(); 301 | if ( iu != xorList[i].begin() && (notCur || hasFlag) ) 302 | list << ' '; 303 | if (hasFlag) 304 | list << (*iu)->flagStartChar() << (*iu)->getFlag() << ' '; 305 | if ( notCur || hasFlag ) 306 | list << (*iu)->nameStartString() << (*iu)->getName(); 307 | } 308 | list << ')'; 309 | return list.str(); 310 | } 311 | } 312 | 313 | // wasn't found in xor list 314 | if (!a->getFlag().empty()) { 315 | list << "(" << a->flagStartChar() << a->getFlag() << ' ' << 316 | a->nameStartString() << a->getName() << ')'; 317 | } 318 | 319 | return list.str(); 320 | } 321 | 322 | } //namespace TCLAP 323 | #endif 324 | --------------------------------------------------------------------------------