From 5baeb631d5fcf8da72ffef0158fe17309e3957ac Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Wed, 9 Nov 2016 03:32:47 +0100 Subject: [PATCH] First version --- RebootInto.sln | 28 + RebootInto/RebootInto.vcxproj | 147 ++++ RebootInto/RebootInto.vcxproj.filters | 6 + RebootInto/main.cpp | 322 ++++++++ deps/include/nowide/args.hpp | 167 +++++ deps/include/nowide/cenv.hpp | 126 ++++ deps/include/nowide/config.hpp | 37 + deps/include/nowide/convert.hpp | 154 ++++ deps/include/nowide/cstdio.hpp | 101 +++ deps/include/nowide/cstdlib.hpp | 16 + deps/include/nowide/encoding_errors.hpp | 58 ++ deps/include/nowide/encoding_utf.hpp | 84 +++ deps/include/nowide/filebuf.hpp | 408 +++++++++++ deps/include/nowide/fstream.hpp | 248 +++++++ deps/include/nowide/iostream.hpp | 99 +++ deps/include/nowide/scoped_ptr.hpp | 93 +++ deps/include/nowide/stackstring.hpp | 154 ++++ deps/include/nowide/system.hpp | 46 ++ deps/include/nowide/utf.hpp | 469 ++++++++++++ deps/include/nowide/windows.hpp | 39 + deps/include/tclap/Arg.h | 692 ++++++++++++++++++ deps/include/tclap/ArgException.h | 200 +++++ deps/include/tclap/ArgTraits.h | 87 +++ deps/include/tclap/CmdLine.h | 633 ++++++++++++++++ deps/include/tclap/CmdLineInterface.h | 150 ++++ deps/include/tclap/CmdLineOutput.h | 74 ++ deps/include/tclap/Constraint.h | 68 ++ deps/include/tclap/DocBookOutput.h | 299 ++++++++ deps/include/tclap/HelpVisitor.h | 76 ++ deps/include/tclap/IgnoreRestVisitor.h | 52 ++ deps/include/tclap/MultiArg.h | 433 +++++++++++ deps/include/tclap/MultiSwitchArg.h | 216 ++++++ deps/include/tclap/OptionalUnlabeledTracker.h | 62 ++ deps/include/tclap/StandardTraits.h | 208 ++++++ deps/include/tclap/StdOutput.h | 298 ++++++++ deps/include/tclap/SwitchArg.h | 266 +++++++ deps/include/tclap/UnlabeledMultiArg.h | 301 ++++++++ deps/include/tclap/UnlabeledValueArg.h | 340 +++++++++ deps/include/tclap/ValueArg.h | 425 +++++++++++ deps/include/tclap/ValuesConstraint.h | 148 ++++ deps/include/tclap/VersionVisitor.h | 81 ++ deps/include/tclap/Visitor.h | 53 ++ deps/include/tclap/XorHandler.h | 166 +++++ deps/include/tclap/ZshCompletionOutput.h | 323 ++++++++ 44 files changed, 8453 insertions(+) create mode 100644 RebootInto.sln create mode 100644 RebootInto/RebootInto.vcxproj create mode 100644 RebootInto/RebootInto.vcxproj.filters create mode 100644 RebootInto/main.cpp create mode 100644 deps/include/nowide/args.hpp create mode 100644 deps/include/nowide/cenv.hpp create mode 100644 deps/include/nowide/config.hpp create mode 100644 deps/include/nowide/convert.hpp create mode 100644 deps/include/nowide/cstdio.hpp create mode 100644 deps/include/nowide/cstdlib.hpp create mode 100644 deps/include/nowide/encoding_errors.hpp create mode 100644 deps/include/nowide/encoding_utf.hpp create mode 100644 deps/include/nowide/filebuf.hpp create mode 100644 deps/include/nowide/fstream.hpp create mode 100644 deps/include/nowide/iostream.hpp create mode 100644 deps/include/nowide/scoped_ptr.hpp create mode 100644 deps/include/nowide/stackstring.hpp create mode 100644 deps/include/nowide/system.hpp create mode 100644 deps/include/nowide/utf.hpp create mode 100644 deps/include/nowide/windows.hpp create mode 100644 deps/include/tclap/Arg.h create mode 100644 deps/include/tclap/ArgException.h create mode 100644 deps/include/tclap/ArgTraits.h create mode 100644 deps/include/tclap/CmdLine.h create mode 100644 deps/include/tclap/CmdLineInterface.h create mode 100644 deps/include/tclap/CmdLineOutput.h create mode 100644 deps/include/tclap/Constraint.h create mode 100644 deps/include/tclap/DocBookOutput.h create mode 100644 deps/include/tclap/HelpVisitor.h create mode 100644 deps/include/tclap/IgnoreRestVisitor.h create mode 100644 deps/include/tclap/MultiArg.h create mode 100644 deps/include/tclap/MultiSwitchArg.h create mode 100644 deps/include/tclap/OptionalUnlabeledTracker.h create mode 100644 deps/include/tclap/StandardTraits.h create mode 100644 deps/include/tclap/StdOutput.h create mode 100644 deps/include/tclap/SwitchArg.h create mode 100644 deps/include/tclap/UnlabeledMultiArg.h create mode 100644 deps/include/tclap/UnlabeledValueArg.h create mode 100644 deps/include/tclap/ValueArg.h create mode 100644 deps/include/tclap/ValuesConstraint.h create mode 100644 deps/include/tclap/VersionVisitor.h create mode 100644 deps/include/tclap/Visitor.h create mode 100644 deps/include/tclap/XorHandler.h create mode 100644 deps/include/tclap/ZshCompletionOutput.h diff --git a/RebootInto.sln b/RebootInto.sln new file mode 100644 index 0000000..69c4b63 --- /dev/null +++ b/RebootInto.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RebootInto", "RebootInto\RebootInto.vcxproj", "{99BB47F2-FC67-43E8-BDDB-CFF4C426D365}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {99BB47F2-FC67-43E8-BDDB-CFF4C426D365}.Debug|x64.ActiveCfg = Debug|x64 + {99BB47F2-FC67-43E8-BDDB-CFF4C426D365}.Debug|x64.Build.0 = Debug|x64 + {99BB47F2-FC67-43E8-BDDB-CFF4C426D365}.Debug|x86.ActiveCfg = Debug|Win32 + {99BB47F2-FC67-43E8-BDDB-CFF4C426D365}.Debug|x86.Build.0 = Debug|Win32 + {99BB47F2-FC67-43E8-BDDB-CFF4C426D365}.Release|x64.ActiveCfg = Release|x64 + {99BB47F2-FC67-43E8-BDDB-CFF4C426D365}.Release|x64.Build.0 = Release|x64 + {99BB47F2-FC67-43E8-BDDB-CFF4C426D365}.Release|x86.ActiveCfg = Release|Win32 + {99BB47F2-FC67-43E8-BDDB-CFF4C426D365}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/RebootInto/RebootInto.vcxproj b/RebootInto/RebootInto.vcxproj new file mode 100644 index 0000000..5b97a33 --- /dev/null +++ b/RebootInto/RebootInto.vcxproj @@ -0,0 +1,147 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {99BB47F2-FC67-43E8-BDDB-CFF4C426D365} + RebootInto + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)/deps/include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)/deps/lib;$(LibraryPath) + + + $(SolutionDir)/deps/include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)/deps/lib;$(LibraryPath) + + + $(SolutionDir)/deps/lib;$(LibraryPath) + $(SolutionDir)/deps/include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + + + $(SolutionDir)/deps/lib;$(LibraryPath) + $(SolutionDir)/deps/include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + + + + Level3 + Disabled + true + + + Console + RequireAdministrator + + + + + Level3 + Disabled + true + MultiThreadedDebug + + + RequireAdministrator + Console + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + RequireAdministrator + + + + + Level3 + Full + true + false + true + MultiThreaded + Size + + + true + true + RequireAdministrator + Console + + + + + + + + + \ No newline at end of file diff --git a/RebootInto/RebootInto.vcxproj.filters b/RebootInto/RebootInto.vcxproj.filters new file mode 100644 index 0000000..4327830 --- /dev/null +++ b/RebootInto/RebootInto.vcxproj.filters @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/RebootInto/main.cpp b/RebootInto/main.cpp new file mode 100644 index 0000000..e47978e --- /dev/null +++ b/RebootInto/main.cpp @@ -0,0 +1,322 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#define NOMINMAX +#include +#include +//#define TCLAP_NAMESTARTSTRING "/" +//#define TCLAP_FLAGSTARTSTRING "/" +#include + +using namespace nowide; + +#define VERSION "1.0" +#define EFI_GLOBAL_VARIABLE L"{8BE4DF61-93CA-11D2-AA0D-00E098032B8C}" +const std::size_t EFI_LOAD_OPTION_DESCRIPTION_OFFSET = sizeof(std::uint32_t) + sizeof(std::uint16_t); +const std::uint16_t INVALID_OPTION_ID = std::numeric_limits::max(); + +bool Verbose = false; +std::vector BootOrder; +std::map DescriptionToID; +std::map IDToDescription; + +DWORD SetPrivilege(HANDLE hToken, LPCWSTR lpszPrivilege, bool bEnablePrivilege) +{ + LUID luid; + if (!LookupPrivilegeValueW(NULL, lpszPrivilege, &luid)) { + std::cerr << "LookupPrivilegeValue failed: " << GetLastError() << std::endl; + return GetLastError(); + } + + TOKEN_PRIVILEGES tp; + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + if (bEnablePrivilege) { + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + } else { + tp.Privileges[0].Attributes = 0; + } + + if (!AdjustTokenPrivileges( + hToken, + false, + &tp, + sizeof(TOKEN_PRIVILEGES), + nullptr, + nullptr + )) { + std::cerr << "AdjustTokenPrivileges failed: " << GetLastError() << std::endl; + return GetLastError(); + } + + if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) + { + std::cerr << "AdjustTokenPrivileges failed: The token does not have the specified privilege" << std::endl; + return GetLastError(); + } + + return ERROR_SUCCESS; +} + +DWORD SetPrivileges() +{ + // Get access token + HANDLE hInstance = GetCurrentProcess(); + HANDLE hToken; + if (OpenProcessToken(hInstance, TOKEN_ADJUST_PRIVILEGES, &hToken) == 0) { + std::cerr << "OpenProcessToken failed: " << GetLastError() << std::endl; + return GetLastError(); + } + + DWORD result; + // Enable environment edit privileges + result = SetPrivilege(hToken, widen(SE_SYSTEM_ENVIRONMENT_NAME).c_str(), true); + if (result != ERROR_SUCCESS) { + return result; + } + // Enable shutdown privileges + result = SetPrivilege(hToken, widen(SE_SHUTDOWN_NAME).c_str(), true); + if (result != ERROR_SUCCESS) { + return result; + } + + return ERROR_SUCCESS; +} + +DWORD LoadBootOrder() +{ + std::array buffer; + std::size_t size = GetFirmwareEnvironmentVariableW(L"BootOrder", EFI_GLOBAL_VARIABLE, buffer.data(), sizeof(std::uint16_t) * buffer.size()); + if (size == 0) { + std::cout << "LoadBootOrder failed: " << GetLastError() << std::endl; + return GetLastError(); + } + + int numEntries = size / sizeof(std::uint16_t); + if (Verbose) { + std::cout << "Received " << numEntries << " UEFI entries." << std::endl; + } + + BootOrder.resize(numEntries); + std::copy_n(buffer.begin(), numEntries, BootOrder.begin()); + + return ERROR_SUCCESS; +} + +DWORD LoadBootDescriptions() +{ + char* buffer = new char[1024]; + for (int i = 0; i < BootOrder.size(); i++) { + std::uint16_t id = BootOrder.at(i); + char entry[9] = "Boot####"; + std::snprintf(entry, 9, "Boot%04X", id); + + std::size_t size = GetFirmwareEnvironmentVariableW(widen(entry).c_str(), EFI_GLOBAL_VARIABLE, buffer, sizeof(char) * 1024); + if (size == 0) { + std::cerr << "LoadBootDescriptions failed on " << entry << ": " << GetLastError() << std::endl; + return GetLastError(); + } + + std::string description(narrow(reinterpret_cast(buffer + EFI_LOAD_OPTION_DESCRIPTION_OFFSET))); + DescriptionToID[description] = id; + IDToDescription[id] = description; + } + delete[] buffer; + + return ERROR_SUCCESS; +} + +void PrintBootOrder() +{ + for (auto& id : BootOrder) { + std::cout << id << ": \"" << IDToDescription.at(id) << "\"" << std::endl; + } +} + +std::uint16_t GetCurrentBootOption() +{ + std::uint16_t current; + std::size_t size = GetFirmwareEnvironmentVariableW(L"BootCurrent", EFI_GLOBAL_VARIABLE, ¤t, sizeof(std::uint16_t)); + if (size == 0) { + std::cout << "GetCurrentBootOption failed: " << GetLastError() << std::endl; + return INVALID_OPTION_ID; + } + return current; +} + +DWORD SetBootNext(std::uint16_t entry) +{ + bool result = SetFirmwareEnvironmentVariableW(L"BootNext", EFI_GLOBAL_VARIABLE, &entry, sizeof(std::uint16_t)); + if (!result) { + std::cerr << "SetBootNext failed: " << GetLastError() << std::endl; + return GetLastError(); + } + + return ERROR_SUCCESS; +} + +DWORD SetBootDefault(std::uint16_t entry, std::size_t offset = 0) +{ + auto currentDefault = BootOrder.begin(); + std::advance(currentDefault, offset); + auto newDefault = std::find(BootOrder.begin(), BootOrder.end(), entry); + if (newDefault > currentDefault) { + // Shift entry to top + std::uint16_t tmp = *newDefault; + std::copy_backward(currentDefault, newDefault, std::next(newDefault)); + *currentDefault = tmp; + + // Apply boot order + bool result = SetFirmwareEnvironmentVariableW(L"BootOrder", EFI_GLOBAL_VARIABLE, BootOrder.data(), sizeof(std::uint16_t) * BootOrder.size()); + if (!result) { + std::cerr << "Failed to apply boot order: " << GetLastError() << std::endl; + return GetLastError(); + } + + std::cout << "Boot order changed successfully." << std::endl; + } else if (newDefault < currentDefault) { + std::cout << "Boot entry is already above provided offset! Nothing has been changed." << std::endl; + } else { + std::cout << "Boot entry is already the default! Nothing has been changed." << std::endl; + } + + return ERROR_SUCCESS; +} + +int wmain(int argc, wchar_t* argv[]) +{ + // Check for UEFI + FIRMWARE_TYPE firmwareType; + if (GetFirmwareType(&firmwareType) == 0) { + std::cerr << "GetFirmwareType failed: " << GetLastError() << std::endl; + return 1; + } + if (firmwareType != FirmwareTypeUefi) { + std::cerr << "Error: System is not UEFI!" << std::endl; + return 1; + } + + // Create a UTF-8 argument vector for TCLAP + std::vector args(argc); + for (int i = 0; i < argc; i++) { + args[i] = narrow(argv[i]); + } + + // Arguments + auto cmd = std::make_shared("Tool to simplify dual-boot scenarios by changing the UEFI boot order to the desired entry and then reboot.", ' ', VERSION); + TCLAP::SwitchArg arg_list("l", "list", "List current UEFI boot order and exit."); + TCLAP::SwitchArg arg_current("c", "current", "Move the currently booted UEFI entry to the top of the boot order and exit. Useful if you want your manual UEFI choices to stick, by automatically running this argument at startup."); + TCLAP::ValueArg arg_offset("o", "offset", "Numerical offset from the top of the boot order that acts as a barrier to how high entries will be moved. Default is 0, which means boot entries will be moved to the very top. Useful if you want UEFI to try another media before proceeding with your chosen boot entry.", false, 0, "offset"); + TCLAP::SwitchArg arg_once("n", "once", "Change boot order for the next boot only"); + TCLAP::SwitchArg arg_noreboot("b", "noreboot", "Do not reboot."); + TCLAP::SwitchArg arg_verbose("v", "verbose", "Verbose output."); + TCLAP::UnlabeledValueArg arg_entry("entry", "The UEFI entry to reboot into.", false, "", "UEFI entry"); + + // Parse command line + try { + cmd->add(arg_list); + cmd->add(arg_current); + cmd->add(arg_offset); + cmd->add(arg_once); + cmd->add(arg_noreboot); + cmd->add(arg_verbose); + cmd->add(arg_entry); + cmd->parse(args); + } catch (TCLAP::ArgException& e) { + std::cerr << "Error: " << e.error() << " for arg " << e.argId() << std::endl; + return 1; + } + Verbose = arg_verbose.getValue(); + // Positional argument requirement + if (arg_entry.getValue().empty() && !arg_list.getValue() && !arg_current.getValue()) { + auto output = cmd->getOutput(); + output->usage(*cmd); + return 1; + } + + // Initialize + if (SetPrivileges() != ERROR_SUCCESS) { return 1; } + if (LoadBootOrder() != ERROR_SUCCESS) { return 1; } + if (LoadBootDescriptions() != ERROR_SUCCESS) { return 1; } + + // Print boot order + if (arg_list.getValue() || Verbose) { // --list --verbose + PrintBootOrder(); + if (!Verbose) { + return 0; + } + } + + // Get option ID + std::uint16_t entry = INVALID_OPTION_ID; + if (arg_current.getValue()) { // --current + entry = GetCurrentBootOption(); + if (entry == INVALID_OPTION_ID) { + return 1; + } + if (std::find(BootOrder.begin(), BootOrder.end(), entry) == BootOrder.end()) { + std::cerr << "Error: Currently booted UEFI entry has been deleted since last boot!" << std::endl; + return 1; + } + if (Verbose) { + std::cout << "Currently booted UEFI entry is \"" << entry << ": " << IDToDescription.at(entry) << "\"" << std::endl; + } + } else { // + // Find by ID + try { + std::size_t numNums; + std::uint16_t id = std::stoi(arg_entry.getValue(), &numNums); + if (numNums == arg_entry.getValue().size()) { + auto it = std::find(BootOrder.begin(), BootOrder.end(), id); + if (it != BootOrder.end()) { + entry = id; + if (Verbose) { + std::cout << "UEFI entry matched by ID." << std::endl; + } + } + } + } catch (std::invalid_argument& e) { + } catch (std::out_of_range& e) { } + + // Find by description + if (entry == INVALID_OPTION_ID) { + auto it = DescriptionToID.find(arg_entry.getValue()); + if (it == DescriptionToID.end()) { + std::cerr << "Error: No UEFI entry found with ID or description \"" << arg_entry.getValue() << "\"." << std::endl; + std::cerr << "Use --list to list all available entries." << std::endl; + return 1; + } + + if (Verbose) { + std::cout << "UEFI entry matched by description." << std::endl; + } + entry = it->second; + } + } + + // Write boot commands to UEFI + if (arg_once.getValue()) { // --once + // Set BootNext + if (SetBootNext(entry) != ERROR_SUCCESS) { return 1; } + } else { + // Move option to top of boot order + if (SetBootDefault(entry, arg_offset.getValue()) != ERROR_SUCCESS) { return 1; } + } + + // Reboot + if (!arg_noreboot.getValue() && !arg_current.getValue()) { // --noreboot --current + if (InitiateSystemShutdown(nullptr, nullptr, 0, false, true) == 0) { + std::cerr << "Failed to initiate reboot: " << GetLastError() << std::endl; + return 1; + } else { + std::cout << "Rebooting..." << std::endl; + } + } + + return 0; +} \ No newline at end of file diff --git a/deps/include/nowide/args.hpp b/deps/include/nowide/args.hpp new file mode 100644 index 0000000..d1e9b44 --- /dev/null +++ b/deps/include/nowide/args.hpp @@ -0,0 +1,167 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef NOWIDE_ARGS_HPP_INCLUDED +#define NOWIDE_ARGS_HPP_INCLUDED + +#include +#include +#include +#ifdef NOWIDE_WINDOWS +#include +#endif + + +namespace nowide { + #if !defined(NOWIDE_WINDOWS) && !defined(NOWIDE_DOXYGEN) + class args { + public: + args(int &,char **&) {} + args(int &,char **&,char **&){} + ~args() {} + }; + + #else + + /// + /// \brief args is a class that fixes standard main() function arguments and changes them to UTF-8 under + /// Microsoft Windows. + /// + /// The class uses \c GetCommandLineW(), \c CommandLineToArgvW() and \c GetEnvironmentStringsW() + /// in order to obtain the information. It does not relates to actual values of argc,argv and env + /// under Windows. + /// + /// It restores the original values in its destructor + /// + /// \note the class owns the memory of the newly allocated strings + /// + class args { + public: + + /// + /// Fix command line agruments + /// + args(int &argc,char **&argv) : + old_argc_(argc), + old_argv_(argv), + old_env_(0), + old_argc_ptr_(&argc), + old_argv_ptr_(&argv), + old_env_ptr_(0) + { + fix_args(argc,argv); + } + /// + /// Fix command line agruments and environment + /// + args(int &argc,char **&argv,char **&en) : + old_argc_(argc), + old_argv_(argv), + old_env_(en), + old_argc_ptr_(&argc), + old_argv_ptr_(&argv), + old_env_ptr_(&en) + { + fix_args(argc,argv); + fix_env(en); + } + /// + /// Restore original argc,argv,env values, if changed + /// + ~args() + { + if(old_argc_ptr_) + *old_argc_ptr_ = old_argc_; + if(old_argv_ptr_) + *old_argv_ptr_ = old_argv_; + if(old_env_ptr_) + *old_env_ptr_ = old_env_; + } + private: + void fix_args(int &argc,char **&argv) + { + int wargc; + wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(),&wargc); + if(!wargv) { + argc = 0; + static char *dummy = 0; + argv = &dummy; + return; + } + try{ + args_.resize(wargc+1,0); + arg_values_.resize(wargc); + for(int i=0;i args_; + std::vector arg_values_; + stackstring env_; + std::vector envp_; + + int old_argc_; + char **old_argv_; + char **old_env_; + + int *old_argc_ptr_; + char ***old_argv_ptr_; + char ***old_env_ptr_; + }; + + #endif + +} // nowide + +#endif + +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/deps/include/nowide/cenv.hpp b/deps/include/nowide/cenv.hpp new file mode 100644 index 0000000..f7c8f84 --- /dev/null +++ b/deps/include/nowide/cenv.hpp @@ -0,0 +1,126 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef NOWIDE_CENV_H_INCLUDED +#define NOWIDE_CENV_H_INCLUDED + +#include +#include +#include +#include +#include +#include + +#ifdef NOWIDE_WINDOWS +#include +#endif + + +namespace nowide { + #if !defined(NOWIDE_WINDOWS) && !defined(NOWIDE_DOXYGEN) + using ::getenv; + using ::setenv; + using ::unsetenv; + using ::putenv; + #else + /// + /// \brief UTF-8 aware getenv. Returns 0 if the variable is not set. + /// + /// This function is not thread safe or reenterable as defined by the standard library + /// + inline char *getenv(char const *key) + { + static stackstring value; + + wshort_stackstring name; + if(!name.convert(key)) + return 0; + + static const size_t buf_size = 64; + wchar_t buf[buf_size]; + std::vector tmp; + wchar_t *ptr = buf; + size_t n = GetEnvironmentVariableW(name.c_str(),buf,buf_size); + if(n == 0 && GetLastError() == 203) // ERROR_ENVVAR_NOT_FOUND + return 0; + if(n >= buf_size) { + tmp.resize(n+1,L'\0'); + n = GetEnvironmentVariableW(name.c_str(),&tmp[0],static_cast(tmp.size() - 1)); + // The size may have changed + if(n >= tmp.size() - 1) + return 0; + ptr = &tmp[0]; + } + if(!value.convert(ptr)) + return 0; + return value.c_str(); + } + /// + /// \brief UTF-8 aware setenv, \a key - the variable name, \a value is a new UTF-8 value, + /// + /// if override is not 0, that the old value is always overridded, otherwise, + /// if the variable exists it remains unchanged + /// + inline int setenv(char const *key,char const *value,int override) + { + wshort_stackstring name; + if(!name.convert(key)) + return -1; + if(!override) { + wchar_t unused[2]; + if(!(GetEnvironmentVariableW(name.c_str(),unused,2)==0 && GetLastError() == 203)) // ERROR_ENVVAR_NOT_FOUND + return 0; + } + wstackstring wval; + if(!wval.convert(value)) + return -1; + if(SetEnvironmentVariableW(name.c_str(),wval.c_str())) + return 0; + return -1; + } + /// + /// \brief Remove enviroment variable \a key + /// + inline int unsetenv(char const *key) + { + wshort_stackstring name; + if(!name.convert(key)) + return -1; + if(SetEnvironmentVariableW(name.c_str(),0)) + return 0; + return -1; + } + /// + /// \brief UTF-8 aware putenv implementation, expects string in format KEY=VALUE + /// + inline int putenv(char *string) + { + char const *key = string; + char const *key_end = string; + while(*key_end!='=' && key_end!='\0') + key_end++; + if(*key_end == '\0') + return -1; + wshort_stackstring wkey; + if(!wkey.convert(key,key_end)) + return -1; + + wstackstring wvalue; + if(!wvalue.convert(key_end+1)) + return -1; + + if(SetEnvironmentVariableW(wkey.c_str(),wvalue.c_str())) + return 0; + return -1; + } + #endif +} // nowide + + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/deps/include/nowide/config.hpp b/deps/include/nowide/config.hpp new file mode 100644 index 0000000..89c1f51 --- /dev/null +++ b/deps/include/nowide/config.hpp @@ -0,0 +1,37 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef NOWIDE_CONFIG_H_INCLUDED +#define NOWIDE_CONFIG_H_INCLUDED + + +#if (defined(__WIN32) || defined(_WIN32) || defined(WIN32)) && !defined(__CYGWIN__) +#define NOWIDE_WINDOWS +#endif + +#ifdef _MSC_VER +#define NOWIDE_MSVC +#endif + +#ifdef NOWIDE_WINDOWS +# if defined(DLL_EXPORT) || defined(NOWIDE_EXPORT) +# ifdef NOWIDE_SOURCE +# define NOWIDE_DECL __declspec(dllexport) +# else +# define NOWIDE_DECL __declspec(dllimport) +# endif //NOWIDE_SOURCE +# endif // DYN_LINK +#endif + +#ifndef NOWIDE_DECL +# define NOWIDE_DECL +#endif + + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/deps/include/nowide/convert.hpp b/deps/include/nowide/convert.hpp new file mode 100644 index 0000000..9c234f7 --- /dev/null +++ b/deps/include/nowide/convert.hpp @@ -0,0 +1,154 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef NOWIDE_CONVERT_H_INCLUDED +#define NOWIDE_CONVERT_H_INCLUDED + +#include +#include + + +namespace nowide { + /// + /// \brief Template function that converts a buffer of UTF sequence in range [source_begin,source_end) + /// to the output \a buffer of size \a buffer_size. + /// + /// In case of success a NUL terminated string returned (buffer), otherwise 0 is returned. + /// + /// If there is not enough room in the buffer or the source sequence contains invalid UTF + /// 0 is returned, and the contend of the buffer is undefined. + /// + template + CharOut *basic_convert(CharOut *buffer,size_t buffer_size,CharIn const *source_begin,CharIn const *source_end) + { + CharOut *rv = buffer; + if(buffer_size == 0) + return 0; + buffer_size --; + while(source_begin!=source_end) { + using namespace nowide::utf; + code_point c = utf_traits::template decode(source_begin,source_end); + if(c==illegal || c==incomplete) { + rv = 0; + break; + } + size_t width = utf_traits::width(c); + if(buffer_size < width) { + rv=0; + break; + } + buffer = utf_traits::template encode(c,buffer); + buffer_size -= width; + } + *buffer++ = 0; + return rv; + } + + /// \cond INTERNAL + namespace details { + // + // wcslen defined only in C99... So we will not use it + // + template + Char const *basic_strend(Char const *s) + { + while(*s) + s++; + return s; + } + } + /// \endcond + + /// + /// Convert NUL terminated UTF source string to NUL terminated \a output string of size at + /// most output_size (including NUL) + /// + /// In case of surcess output is returned, if the input sequence is illegal, + /// or there is not enough room NULL is returned + /// + inline char *narrow(char *output,size_t output_size,wchar_t const *source) + { + return basic_convert(output,output_size,source,details::basic_strend(source)); + } + /// + /// Convert UTF text in range [begin,end) to NUL terminated \a output string of size at + /// most output_size (including NUL) + /// + /// In case of surcess output is returned, if the input sequence is illegal, + /// or there is not enough room NULL is returned + /// + inline char *narrow(char *output,size_t output_size,wchar_t const *begin,wchar_t const *end) + { + return basic_convert(output,output_size,begin,end); + } + /// + /// Convert NUL terminated UTF source string to NUL terminated \a output string of size at + /// most output_size (including NUL) + /// + /// In case of surcess output is returned, if the input sequence is illegal, + /// or there is not enough room NULL is returned + /// + inline wchar_t *widen(wchar_t *output,size_t output_size,char const *source) + { + return basic_convert(output,output_size,source,details::basic_strend(source)); + } + /// + /// Convert UTF text in range [begin,end) to NUL terminated \a output string of size at + /// most output_size (including NUL) + /// + /// In case of surcess output is returned, if the input sequence is illegal, + /// or there is not enough room NULL is returned + /// + inline wchar_t *widen(wchar_t *output,size_t output_size,char const *begin,char const *end) + { + return basic_convert(output,output_size,begin,end); + } + + + /// + /// Convert between Wide - UTF-16/32 string and UTF-8 string. + /// + /// nowide::conv::conversion_error is thrown in a case of a error + /// + inline std::string narrow(wchar_t const *s) + { + return nowide::conv::utf_to_utf(s); + } + /// + /// Convert between UTF-8 and UTF-16 string, implemented only on Windows platform + /// + /// nowide::conv::conversion_error is thrown in a case of a error + /// + inline std::wstring widen(char const *s) + { + return nowide::conv::utf_to_utf(s); + } + /// + /// Convert between Wide - UTF-16/32 string and UTF-8 string + /// + /// nowide::conv::conversion_error is thrown in a case of a error + /// + inline std::string narrow(std::wstring const &s) + { + return nowide::conv::utf_to_utf(s); + } + /// + /// Convert between UTF-8 and UTF-16 string, implemented only on Windows platform + /// + /// nowide::conv::conversion_error is thrown in a case of a error + /// + inline std::wstring widen(std::string const &s) + { + return nowide::conv::utf_to_utf(s); + } + +} // nowide + + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/deps/include/nowide/cstdio.hpp b/deps/include/nowide/cstdio.hpp new file mode 100644 index 0000000..b34ccf8 --- /dev/null +++ b/deps/include/nowide/cstdio.hpp @@ -0,0 +1,101 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef NOWIDE_CSTDIO_H_INCLUDED +#define NOWIDE_CSTDIO_H_INCLUDED + +#include +#include +#include +#include +#include +#include + +#ifdef NOWIDE_MSVC +# pragma warning(push) +# pragma warning(disable : 4996) +#endif + + + +namespace nowide { +#if !defined(NOWIDE_WINDOWS) && !defined(NOWIDE_DOXYGEN) + using std::fopen; + using std::freopen; + using std::remove; + using std::rename; +#else + +/// +/// \brief Same as freopen but file_name and mode are UTF-8 strings +/// +/// In invalid UTF-8 given, NULL is returned and errno is set to EINVAL +/// +inline FILE *freopen(char const *file_name,char const *mode,FILE *stream) +{ + wstackstring wname; + wshort_stackstring wmode; + if(!wname.convert(file_name) || !wmode.convert(mode)) { + errno = EINVAL; + return 0; + } + return _wfreopen(wname.c_str(),wmode.c_str(),stream); +} +/// +/// \brief Same as fopen but file_name and mode are UTF-8 strings +/// +/// In invalid UTF-8 given, NULL is returned and errno is set to EINVAL +/// +inline FILE *fopen(char const *file_name,char const *mode) +{ + wstackstring wname; + wshort_stackstring wmode; + if(!wname.convert(file_name) || !wmode.convert(mode)) { + errno = EINVAL; + return 0; + } + return _wfopen(wname.c_str(),wmode.c_str()); +} +/// +/// \brief Same as rename but old_name and new_name are UTF-8 strings +/// +/// In invalid UTF-8 given, -1 is returned and errno is set to EINVAL +/// +inline int rename(char const *old_name,char const *new_name) +{ + wstackstring wold,wnew; + if(!wold.convert(old_name) || !wnew.convert(new_name)) { + errno = EINVAL; + return -1; + } + return _wrename(wold.c_str(),wnew.c_str()); +} +/// +/// \brief Same as rename but name is UTF-8 string +/// +/// In invalid UTF-8 given, -1 is returned and errno is set to EINVAL +/// +inline int remove(char const *name) +{ + wstackstring wname; + if(!wname.convert(name)) { + errno = EINVAL; + return -1; + } + return _wremove(wname.c_str()); +} +#endif +} // nowide + + +#ifdef NOWIDE_MSVC +#pragma warning(pop) +#endif + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/deps/include/nowide/cstdlib.hpp b/deps/include/nowide/cstdlib.hpp new file mode 100644 index 0000000..0a7cf69 --- /dev/null +++ b/deps/include/nowide/cstdlib.hpp @@ -0,0 +1,16 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef NOWIDE_CSTDLIB_HPP_INCLUDED +#define NOWIDE_CSTDLIB_HPP_INCLUDED + +#include +#include + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/deps/include/nowide/encoding_errors.hpp b/deps/include/nowide/encoding_errors.hpp new file mode 100644 index 0000000..a7a4058 --- /dev/null +++ b/deps/include/nowide/encoding_errors.hpp @@ -0,0 +1,58 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef NOWIDE_ENCODING_ERRORS_HPP_INCLUDED +#define NOWIDE_ENCODING_ERRORS_HPP_INCLUDED + +#include +#ifdef NOWIDE_MSVC +# pragma warning(push) +# pragma warning(disable : 4275 4251 4231 4660) +#endif +#include + + + +namespace nowide { + namespace conv { + /// + /// \addtogroup codepage + /// + /// @{ + + /// + /// \brief The excepton that is thrown in case of conversion error + /// + class conversion_error : public std::runtime_error { + public: + conversion_error() : std::runtime_error("Conversion failed") {} + }; + + /// + /// enum that defines conversion policy + /// + typedef enum { + skip = 0, ///< Skip illegal/unconvertable characters + stop = 1, ///< Stop conversion and throw conversion_error + default_method = skip ///< Default method - skip + } method_type; + + + /// @} + + } // conv + +} // nowide + +#ifdef NOWIDE_MSVC +#pragma warning(pop) +#endif + +#endif + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/deps/include/nowide/encoding_utf.hpp b/deps/include/nowide/encoding_utf.hpp new file mode 100644 index 0000000..018b648 --- /dev/null +++ b/deps/include/nowide/encoding_utf.hpp @@ -0,0 +1,84 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef NOWIDE_ENCODING_UTF_HPP_INCLUDED +#define NOWIDE_ENCODING_UTF_HPP_INCLUDED + +#include +#include +#include +#include +#ifdef NOWIDE_MSVC +# pragma warning(push) +# pragma warning(disable : 4275 4251 4231 4660) +#endif + + +namespace nowide{ + namespace conv { + /// + /// Convert a Unicode text in range [begin,end) to other Unicode encoding + /// + template + std::basic_string + utf_to_utf(CharIn const *begin,CharIn const *end,method_type how = default_method) + { + std::basic_string result; + result.reserve(end-begin); + typedef std::back_insert_iterator > inserter_type; + inserter_type inserter(result); + utf::code_point c; + while(begin!=end) { + c=utf::utf_traits::template decode(begin,end); + if(c==utf::illegal || c==utf::incomplete) { + if(how==stop) + throw conversion_error(); + } + else { + utf::utf_traits::template encode(c,inserter); + } + } + return result; + } + + /// + /// Convert a Unicode NUL terminated string \a str other Unicode encoding + /// + template + std::basic_string + utf_to_utf(CharIn const *str,method_type how = default_method) + { + CharIn const *end = str; + while(*end) + end++; + return utf_to_utf(str,end,how); + } + + + /// + /// Convert a Unicode string \a str other Unicode encoding + /// + template + std::basic_string + utf_to_utf(std::basic_string const &str,method_type how = default_method) + { + return utf_to_utf(str.c_str(),str.c_str()+str.size(),how); + } + + + +} // conv +} // nowide + +#ifdef NOWIDE_MSVC +#pragma warning(pop) +#endif + +#endif + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/deps/include/nowide/filebuf.hpp b/deps/include/nowide/filebuf.hpp new file mode 100644 index 0000000..c6ad987 --- /dev/null +++ b/deps/include/nowide/filebuf.hpp @@ -0,0 +1,408 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef NOWIDE_FILEBUF_HPP +#define NOWIDE_FILEBUF_HPP + +#include +#include +#include +#include +#include +#include + +#ifdef NOWIDE_MSVC +# pragma warning(push) +# pragma warning(disable : 4996 4244) +#endif + + + +namespace nowide { +#if !defined(NOWIDE_WINDOWS) && !defined(NOWIDE_FSTREAM_TESTS) && !defined(NOWIDE_DOXYGEN) + using std::basic_filebuf; + using std::filebuf; +#else // Windows + + /// + /// \brief This forward declaration defined the basic_filebuf type. + /// + /// it is implemented and specialized for CharType = char, it behaves + /// implements std::filebuf over standard C I/O + /// + template > + class basic_filebuf; + + /// + /// \brief This is implementation of std::filebuf + /// + /// it is implemented and specialized for CharType = char, it behaves + /// implements std::filebuf over standard C I/O + /// + template<> + class basic_filebuf : public std::basic_streambuf { + public: + /// + /// Creates new filebuf + /// + basic_filebuf() : + buffer_size_(4), + buffer_(0), + file_(0), + own_(true), + mode_(std::ios::in | std::ios::out) + { + setg(0,0,0); + setp(0,0); + } + + virtual ~basic_filebuf() + { + if(file_) { + ::fclose(file_); + file_ = 0; + } + if(own_ && buffer_) + delete [] buffer_; + } + + /// + /// Same as std::filebuf::open but s is UTF-8 string + /// + basic_filebuf *open(std::string const &s,std::ios_base::openmode mode) + { + return open(s.c_str(),mode); + } + /// + /// Same as std::filebuf::open but s is UTF-8 string + /// + basic_filebuf *open(char const *s,std::ios_base::openmode mode) + { + if(file_) { + sync(); + ::fclose(file_); + file_ = 0; + } + wchar_t const *smode = get_mode(mode); + if(!smode) + return 0; + wstackstring name; + if(!name.convert(s)) + return 0; + #ifdef NOWIDE_FSTREAM_TESTS + FILE *f = ::fopen(s,nowide::convert(smode).c_str()); + #else + FILE *f = ::_wfopen(name.c_str(),smode); + #endif + if(!f) + return 0; + file_ = f; + return this; + } + /// + /// Same as std::filebuf::close() + /// + basic_filebuf *close() + { + bool res = sync() == 0; + if(file_) { + if(::fclose(file_)!=0) + res = false; + file_ = 0; + } + return res ? this : 0; + } + /// + /// Same as std::filebuf::is_open() + /// + bool is_open() const + { + return file_ != 0; + } + + private: + void make_buffer() + { + if(buffer_) + return; + if(buffer_size_ > 0) { + buffer_ = new char [buffer_size_]; + own_ = true; + } + } + protected: + + virtual std::streambuf *setbuf(char *s,std::streamsize n) + { + if(!buffer_ && n>=0) { + buffer_ = s; + buffer_size_ = n; + own_ = false; + } + return this; + } + +#ifdef NOWIDE_DEBUG_FILEBUF + + void print_buf(char *b,char *p,char *e) + { + std::cerr << "-- Is Null: " << (b==0) << std::endl;; + if(b==0) + return; + if(e != 0) + std::cerr << "-- Total: " << e - b <<" offset from start " << p - b << std::endl; + else + std::cerr << "-- Total: " << p - b << std::endl; + + std::cerr << "-- ["; + for(char *ptr = b;ptrprint_state(); + } + ~print_guard() + { + std::cerr << "Out: " << f << std::endl; + self->print_state(); + } + basic_filebuf *self; + char const *f; + }; +#else +#endif + + int overflow(int c) + { +#ifdef NOWIDE_DEBUG_FILEBUF + print_guard g(this,__FUNCTION__); +#endif + if(!file_) + return EOF; + + if(fixg() < 0) + return EOF; + + size_t n = pptr() - pbase(); + if(n > 0) { + if(::fwrite(pbase(),1,n,file_) < n) + return -1; + fflush(file_); + } + + if(buffer_size_ > 0) { + make_buffer(); + setp(buffer_,buffer_+buffer_size_); + if(c!=EOF) + sputc(c); + } + else if(c!=EOF) { + if(::fputc(c,file_)==EOF) + return EOF; + fflush(file_); + } + return 0; + } + + + int sync() + { + return overflow(EOF); + } + + int underflow() + { +#ifdef NOWIDE_DEBUG_FILEBUF + print_guard g(this,__FUNCTION__); +#endif + if(!file_) + return EOF; + if(fixp() < 0) + return EOF; + if(buffer_size_ == 0) { + int c = ::fgetc(file_); + if(c==EOF) { + return EOF; + } + last_char_ = c; + setg(&last_char_,&last_char_,&last_char_ + 1); + return c; + } + make_buffer(); + size_t n = ::fread(buffer_,1,buffer_size_,file_); + setg(buffer_,buffer_,buffer_+n); + if(n == 0) + return EOF; + return std::char_traits::to_int_type(*gptr()); + } + + int pbackfail(int) + { + return pubseekoff(-1,std::ios::cur); + } + + std::streampos seekoff(std::streamoff off, + std::ios_base::seekdir seekdir, + std::ios_base::openmode /*m*/) + { +#ifdef NOWIDE_DEBUG_FILEBUF + print_guard g(this,__FUNCTION__); +#endif + if(!file_) + return EOF; + if(fixp() < 0 || fixg() < 0) + return EOF; + if(seekdir == std::ios_base::cur) { + if( ::fseek(file_,off,SEEK_CUR) < 0) + return EOF; + } + else if(seekdir == std::ios_base::beg) { + if( ::fseek(file_,off,SEEK_SET) < 0) + return EOF; + } + else if(seekdir == std::ios_base::end) { + if( ::fseek(file_,off,SEEK_END) < 0) + return EOF; + } + else + return -1; + return ftell(file_); + } + std::streampos seekpos(std::streampos off,std::ios_base::openmode m) + { + return seekoff(std::streamoff(off),std::ios_base::beg,m); + } + private: + int fixg() + { + if(gptr()!=egptr()) { + std::streamsize off = gptr() - egptr(); + setg(0,0,0); + if(fseek(file_,off,SEEK_CUR) != 0) + return -1; + } + setg(0,0,0); + return 0; + } + + int fixp() + { + if(pptr()!=0) { + int r = sync(); + setp(0,0); + return r; + } + return 0; + } + + void reset(FILE *f = 0) + { + sync(); + if(file_) { + fclose(file_); + file_ = 0; + } + file_ = f; + } + + + static wchar_t const *get_mode(std::ios_base::openmode mode) + { + // + // done according to n2914 table 106 27.9.1.4 + // + + // note can't use switch case as overload operator can't be used + // in constant expression + if(mode == (std::ios_base::out)) + return L"w"; + if(mode == (std::ios_base::out | std::ios_base::app)) + return L"a"; + if(mode == (std::ios_base::app)) + return L"a"; + if(mode == (std::ios_base::out | std::ios_base::trunc)) + return L"w"; + if(mode == (std::ios_base::in)) + return L"r"; + if(mode == (std::ios_base::in | std::ios_base::out)) + return L"r+"; + if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::trunc)) + return L"w+"; + if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::app)) + return L"a+"; + if(mode == (std::ios_base::in | std::ios_base::app)) + return L"a+"; + if(mode == (std::ios_base::binary | std::ios_base::out)) + return L"wb"; + if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::app)) + return L"ab"; + if(mode == (std::ios_base::binary | std::ios_base::app)) + return L"ab"; + if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::trunc)) + return L"wb"; + if(mode == (std::ios_base::binary | std::ios_base::in)) + return L"rb"; + if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out)) + return L"r+b"; + if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::trunc)) + return L"w+b"; + if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::app)) + return L"a+b"; + if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::app)) + return L"a+b"; + return 0; + } + + size_t buffer_size_; + char *buffer_; + FILE *file_; + bool own_; + char last_char_; + std::ios::openmode mode_; + }; + + /// + /// \brief Convinience typedef + /// + typedef basic_filebuf filebuf; + + #endif // windows + +} // nowide + + +#ifdef NOWIDE_MSVC +# pragma warning(pop) +#endif + + +#endif + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/deps/include/nowide/fstream.hpp b/deps/include/nowide/fstream.hpp new file mode 100644 index 0000000..dda00d1 --- /dev/null +++ b/deps/include/nowide/fstream.hpp @@ -0,0 +1,248 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef NOWIDE_FSTREAM_INCLUDED_HPP +#define NOWIDE_FSTREAM_INCLUDED_HPP + +#include +#include +#include +#include +#include +#include +#include + + +/// +/// \brief This namespace includes implementation of the standard library functios +/// such that they accept UTF-8 strings on Windows. On other platforms it is just an alias +/// of std namespace (i.e. not on Windows) +/// +namespace nowide { +#if !defined(NOWIDE_WINDOWS) && !defined(NOWIDE_FSTREAM_TESTS) && !defined(NOWIDE_DOXYGEN) + + using std::basic_ifstream; + using std::basic_ofstream; + using std::basic_fstream; + using std::ifstream; + using std::ofstream; + using std::fstream; + +#else + /// + /// \brief Same as std::basic_ifstream but accepts UTF-8 strings under Windows + /// + template > + class basic_ifstream : public std::basic_istream + { + public: + typedef basic_filebuf internal_buffer_type; + typedef std::basic_istream internal_stream_type; + + basic_ifstream() : + internal_stream_type(0) + { + buf_.reset(new internal_buffer_type()); + std::ios::rdbuf(buf_.get()); + } + + explicit basic_ifstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::in) : + internal_stream_type(0) + { + buf_.reset(new internal_buffer_type()); + std::ios::rdbuf(buf_.get()); + open(file_name,mode); + } + + void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::in) + { + if(!buf_->open(file_name,mode | std::ios_base::in)) { + this->setstate(std::ios_base::failbit); + } + else { + this->clear(); + } + } + bool is_open() + { + return buf_->is_open(); + } + bool is_open() const + { + return buf_->is_open(); + } + void close() + { + if(!buf_->close()) + this->setstate(std::ios_base::failbit); + else + this->clear(); + } + + internal_buffer_type *rdbuf() const + { + return buf_.get(); + } + ~basic_ifstream() + { + buf_->close(); + } + + private: + nowide::scoped_ptr buf_; + }; + + /// + /// \brief Same as std::basic_ofstream but accepts UTF-8 strings under Windows + /// + + template > + class basic_ofstream : public std::basic_ostream + { + public: + typedef basic_filebuf internal_buffer_type; + typedef std::basic_ostream internal_stream_type; + + basic_ofstream() : + internal_stream_type(0) + { + buf_.reset(new internal_buffer_type()); + std::ios::rdbuf(buf_.get()); + } + explicit basic_ofstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out) : + internal_stream_type(0) + { + buf_.reset(new internal_buffer_type()); + std::ios::rdbuf(buf_.get()); + open(file_name,mode); + } + void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out) + { + if(!buf_->open(file_name,mode | std::ios_base::out)) { + this->setstate(std::ios_base::failbit); + } + else { + this->clear(); + } + } + bool is_open() + { + return buf_->is_open(); + } + bool is_open() const + { + return buf_->is_open(); + } + void close() + { + if(!buf_->close()) + this->setstate(std::ios_base::failbit); + else + this->clear(); + } + + internal_buffer_type *rdbuf() const + { + return buf_.get(); + } + ~basic_ofstream() + { + buf_->close(); + } + + private: + nowide::scoped_ptr buf_; + }; + + /// + /// \brief Same as std::basic_fstream but accepts UTF-8 strings under Windows + /// + + template > + class basic_fstream : public std::basic_iostream + { + public: + typedef basic_filebuf internal_buffer_type; + typedef std::basic_iostream internal_stream_type; + + basic_fstream() : + internal_stream_type(0) + { + buf_.reset(new internal_buffer_type()); + std::ios::rdbuf(buf_.get()); + } + explicit basic_fstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::in) : + internal_stream_type(0) + { + buf_.reset(new internal_buffer_type()); + std::ios::rdbuf(buf_.get()); + open(file_name,mode); + } + void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::out) + { + if(!buf_->open(file_name,mode)) { + this->setstate(std::ios_base::failbit); + } + else { + this->clear(); + } + } + bool is_open() + { + return buf_->is_open(); + } + bool is_open() const + { + return buf_->is_open(); + } + void close() + { + if(!buf_->close()) + this->setstate(std::ios_base::failbit); + else + this->clear(); + } + + internal_buffer_type *rdbuf() const + { + return buf_.get(); + } + ~basic_fstream() + { + buf_->close(); + } + + private: + nowide::scoped_ptr buf_; + }; + + + /// + /// \brief Same as std::filebuf but accepts UTF-8 strings under Windows + /// + typedef basic_filebuf filebuf; + /// + /// Same as std::ifstream but accepts UTF-8 strings under Windows + /// + typedef basic_ifstream ifstream; + /// + /// Same as std::ofstream but accepts UTF-8 strings under Windows + /// + typedef basic_ofstream ofstream; + /// + /// Same as std::fstream but accepts UTF-8 strings under Windows + /// + typedef basic_fstream fstream; + +#endif +} // nowide + + + + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/deps/include/nowide/iostream.hpp b/deps/include/nowide/iostream.hpp new file mode 100644 index 0000000..b08c477 --- /dev/null +++ b/deps/include/nowide/iostream.hpp @@ -0,0 +1,99 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef NOWIDE_IOSTREAM_HPP_INCLUDED +#define NOWIDE_IOSTREAM_HPP_INCLUDED + +#include +#include +#include +#include +#include + +#ifdef NOWIDE_MSVC +# pragma warning(push) +# pragma warning(disable : 4251) +#endif + + + +namespace nowide { + #if !defined(NOWIDE_WINDOWS) && !defined(NOWIDE_DOXYGEN) + using std::cout; + using std::cerr; + using std::cin; + using std::clog; + #else + + /// \cond INTERNAL + namespace details { + class console_output_buffer; + class console_input_buffer; + + class NOWIDE_DECL winconsole_ostream : public std::ostream { + winconsole_ostream(winconsole_ostream const &); + void operator=(winconsole_ostream const &); + public: + winconsole_ostream(int fd); + ~winconsole_ostream(); + private: + nowide::scoped_ptr d; + }; + + class NOWIDE_DECL winconsole_istream : public std::istream { + winconsole_istream(winconsole_istream const &); + void operator=(winconsole_istream const &); + public: + + winconsole_istream(); + ~winconsole_istream(); + private: + struct data; + nowide::scoped_ptr d; + }; + } // details + + /// \endcond + + /// + /// \brief Same as std::cin, but uses UTF-8 + /// + /// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio + /// + extern NOWIDE_DECL details::winconsole_istream cin; + /// + /// \brief Same as std::cout, but uses UTF-8 + /// + /// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio + /// + extern NOWIDE_DECL details::winconsole_ostream cout; + /// + /// \brief Same as std::cerr, but uses UTF-8 + /// + /// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio + /// + extern NOWIDE_DECL details::winconsole_ostream cerr; + /// + /// \brief Same as std::clog, but uses UTF-8 + /// + /// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio + /// + extern NOWIDE_DECL details::winconsole_ostream clog; + + #endif + +} // nowide + + +#ifdef NOWIDE_MSVC +# pragma warning(pop) +#endif + + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/deps/include/nowide/scoped_ptr.hpp b/deps/include/nowide/scoped_ptr.hpp new file mode 100644 index 0000000..92410e2 --- /dev/null +++ b/deps/include/nowide/scoped_ptr.hpp @@ -0,0 +1,93 @@ +#ifndef NOWIDE_SCOPED_PTR_HPP +#define NOWIDE_SCOPED_PTR_HPP + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov, +// Copyright (C) 2012 Artyom Beilis +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm +// + +#include + +namespace nowide +{ + +// scoped_ptr mimics a built-in pointer except that it guarantees deletion +// of the object pointed to, either on destruction of the scoped_ptr or via +// an explicit reset(). scoped_ptr is a simple solution for simple needs; +// use shared_ptr or std::auto_ptr if your needs are more complex. + +template class scoped_ptr // noncopyable +{ +private: + + T * px; + + scoped_ptr(scoped_ptr const &); + scoped_ptr & operator=(scoped_ptr const &); + + typedef scoped_ptr this_type; + + void operator==( scoped_ptr const& ) const; + void operator!=( scoped_ptr const& ) const; + +public: + + typedef T element_type; + + explicit scoped_ptr( T * p = 0 ): px( p ) // never throws + { + } + + ~scoped_ptr() // never throws + { + delete px; + } + + void reset(T * p = 0) // never throws + { + assert( p == 0 || p != px ); // catch self-reset errors + this_type(p).swap(*this); + } + + T & operator*() const // never throws + { + assert( px != 0 ); + return *px; + } + + T * operator->() const // never throws + { + assert( px != 0 ); + return px; + } + + T * get() const // never throws + { + return px; + } + + operator bool() const + { + return px!=0; + } + + void swap(scoped_ptr & b) // never throws + { + T * tmp = b.px; + b.px = px; + px = tmp; + } +}; + + +} // namespace nowide + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/deps/include/nowide/stackstring.hpp b/deps/include/nowide/stackstring.hpp new file mode 100644 index 0000000..c93f983 --- /dev/null +++ b/deps/include/nowide/stackstring.hpp @@ -0,0 +1,154 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef NOWIDE_DETAILS_WIDESTR_H_INCLUDED +#define NOWIDE_DETAILS_WIDESTR_H_INCLUDED +#include +#include +#include + + +namespace nowide { + +/// +/// \brief A class that allows to create a temporary wide or narrow UTF strings from +/// wide or narrow UTF source. +/// +/// It uses on stack buffer of the string is short enough +/// and allocated a buffer on the heap if the size of the buffer is too small +/// +template +class basic_stackstring { +public: + + static const size_t buffer_size = BufferSize; + typedef CharOut output_char; + typedef CharIn input_char; + + basic_stackstring(basic_stackstring const &other) : + mem_buffer_(0) + { + clear(); + if(other.mem_buffer_) { + size_t len = 0; + while(other.mem_buffer_[len]) + len ++; + mem_buffer_ = new output_char[len + 1]; + memcpy(mem_buffer_,other.mem_buffer_,sizeof(output_char) * (len+1)); + } + else { + memcpy(buffer_,other.buffer_,buffer_size * sizeof(output_char)); + } + } + + void swap(basic_stackstring &other) + { + std::swap(mem_buffer_,other.mem_buffer_); + for(size_t i=0;i wstackstring; +/// +/// Convinience typedef +/// +typedef basic_stackstring stackstring; +/// +/// Convinience typedef +/// +typedef basic_stackstring wshort_stackstring; +/// +/// Convinience typedef +/// +typedef basic_stackstring short_stackstring; + + +} // nowide + + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/deps/include/nowide/system.hpp b/deps/include/nowide/system.hpp new file mode 100644 index 0000000..8083bfc --- /dev/null +++ b/deps/include/nowide/system.hpp @@ -0,0 +1,46 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef NOWIDE_CSTDLIB_HPP +#define NOWIDE_CSTDLIB_HPP + +#include +#include +#include + +namespace nowide { + +#if !defined(NOWIDE_WINDOWS) && !defined(NOWIDE_DOXYGEN) + +using ::system; + +#else // Windows + +/// +/// Same as std::system but cmd is UTF-8. +/// +/// If the input is not valid UTF-8, -1 returned and errno set to EINVAL +/// +inline int system(char const *cmd) +{ + if(!cmd) + return _wsystem(0); + wstackstring wcmd; + if(!wcmd.convert(cmd)) { + errno = EINVAL; + return -1; + } + return _wsystem(wcmd.c_str()); +} + +#endif +} // nowide + + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/deps/include/nowide/utf.hpp b/deps/include/nowide/utf.hpp new file mode 100644 index 0000000..55dc2cc --- /dev/null +++ b/deps/include/nowide/utf.hpp @@ -0,0 +1,469 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef NOWIDE_UTF_HPP_INCLUDED +#define NOWIDE_UTF_HPP_INCLUDED + +#include + +#ifndef NOWIDE_MSVC +namespace nowide { +namespace utf { + typedef unsigned uint32_t; + typedef unsigned short uint16_t; + typedef unsigned char uint8_t; +} +} +#else +#include +#endif + +namespace nowide { +/// +/// \brief Namespace that holds basic operations on UTF encoded sequences +/// +/// All functions defined in this namespace do not require linking with Boost.Locale library +/// +namespace utf { + /// \cond INTERNAL + #ifdef __GNUC__ + # define NOWIDE_LIKELY(x) __builtin_expect((x),1) + # define NOWIDE_UNLIKELY(x) __builtin_expect((x),0) + #else + # define NOWIDE_LIKELY(x) (x) + # define NOWIDE_UNLIKELY(x) (x) + #endif + /// \endcond + + /// + /// \brief The integral type type that can hold a Unicode code point + /// + typedef uint32_t code_point; + + /// + /// \brief Special constant that defines illegal code point + /// + static const code_point illegal = 0xFFFFFFFFu; + + /// + /// \brief Special constant that defines incomplete code point + /// + static const code_point incomplete = 0xFFFFFFFEu; + + /// + /// \brief the function checks if \a v is a valid code point + /// + inline bool is_valid_codepoint(code_point v) + { + if(v>0x10FFFF) + return false; + if(0xD800 <=v && v<= 0xDFFF) // surragates + return false; + return true; + } + + #ifdef NOWIDE_DOXYGEN + /// + /// \brief UTF Traits class - functions to convert UTF sequences to and from Unicode code points + /// + template + struct utf_traits { + /// + /// The type of the character + /// + typedef CharType char_type; + /// + /// Read one code point from the range [p,e) and return it. + /// + /// - If the sequence that was read is incomplete sequence returns \ref incomplete, + /// - If illegal sequence detected returns \ref illegal + /// + /// Requirements + /// + /// - Iterator is valid input iterator + /// + /// Postconditions + /// + /// - p points to the last consumed character + /// + template + static code_point decode(Iterator &p,Iterator e); + + /// + /// Maximal width of valid sequence in the code units: + /// + /// - UTF-8 - 4 + /// - UTF-16 - 2 + /// - UTF-32 - 1 + /// + static const int max_width; + /// + /// The width of specific code point in the code units. + /// + /// Requirement: value is a valid Unicode code point + /// Returns value in range [1..max_width] + /// + static int width(code_point value); + + /// + /// Get the size of the trail part of variable length encoded sequence. + /// + /// Returns -1 if C is not valid lead character + /// + static int trail_length(char_type c); + /// + /// Returns true if c is trail code unit, always false for UTF-32 + /// + static bool is_trail(char_type c); + /// + /// Returns true if c is lead code unit, always true of UTF-32 + /// + static bool is_lead(char_type c); + + /// + /// Convert valid Unicode code point \a value to the UTF sequence. + /// + /// Requirements: + /// + /// - \a value is valid code point + /// - \a out is an output iterator should be able to accept at least width(value) units + /// + /// Returns the iterator past the last written code unit. + /// + template + static Iterator encode(code_point value,Iterator out); + /// + /// Decodes valid UTF sequence that is pointed by p into code point. + /// + /// If the sequence is invalid or points to end the behavior is undefined + /// + template + static code_point decode_valid(Iterator &p); + }; + + #else + + template + struct utf_traits; + + template + struct utf_traits { + + typedef CharType char_type; + + static int trail_length(char_type ci) + { + unsigned char c = ci; + if(c < 128) + return 0; + if(NOWIDE_UNLIKELY(c < 194)) + return -1; + if(c < 224) + return 1; + if(c < 240) + return 2; + if(NOWIDE_LIKELY(c <=244)) + return 3; + return -1; + } + + static const int max_width = 4; + + static int width(code_point value) + { + if(value <=0x7F) { + return 1; + } + else if(value <=0x7FF) { + return 2; + } + else if(NOWIDE_LIKELY(value <=0xFFFF)) { + return 3; + } + else { + return 4; + } + } + + static bool is_trail(char_type ci) + { + unsigned char c=ci; + return (c & 0xC0)==0x80; + } + + static bool is_lead(char_type ci) + { + return !is_trail(ci); + } + + template + static code_point decode(Iterator &p,Iterator e) + { + if(NOWIDE_UNLIKELY(p==e)) + return incomplete; + + unsigned char lead = *p++; + + // First byte is fully validated here + int trail_size = trail_length(lead); + + if(NOWIDE_UNLIKELY(trail_size < 0)) + return illegal; + + // + // Ok as only ASCII may be of size = 0 + // also optimize for ASCII text + // + if(trail_size == 0) + return lead; + + code_point c = lead & ((1<<(6-trail_size))-1); + + // Read the rest + unsigned char tmp; + switch(trail_size) { + case 3: + if(NOWIDE_UNLIKELY(p==e)) + return incomplete; + tmp = *p++; + if (!is_trail(tmp)) + return illegal; + c = (c << 6) | ( tmp & 0x3F); + case 2: + if(NOWIDE_UNLIKELY(p==e)) + return incomplete; + tmp = *p++; + if (!is_trail(tmp)) + return illegal; + c = (c << 6) | ( tmp & 0x3F); + case 1: + if(NOWIDE_UNLIKELY(p==e)) + return incomplete; + tmp = *p++; + if (!is_trail(tmp)) + return illegal; + c = (c << 6) | ( tmp & 0x3F); + } + + // Check code point validity: no surrogates and + // valid range + if(NOWIDE_UNLIKELY(!is_valid_codepoint(c))) + return illegal; + + // make sure it is the most compact representation + if(NOWIDE_UNLIKELY(width(c)!=trail_size + 1)) + return illegal; + + return c; + + } + + template + static code_point decode_valid(Iterator &p) + { + unsigned char lead = *p++; + if(lead < 192) + return lead; + + int trail_size; + + if(lead < 224) + trail_size = 1; + else if(NOWIDE_LIKELY(lead < 240)) // non-BMP rare + trail_size = 2; + else + trail_size = 3; + + code_point c = lead & ((1<<(6-trail_size))-1); + + switch(trail_size) { + case 3: + c = (c << 6) | ( static_cast(*p++) & 0x3F); + case 2: + c = (c << 6) | ( static_cast(*p++) & 0x3F); + case 1: + c = (c << 6) | ( static_cast(*p++) & 0x3F); + } + + return c; + } + + + + template + static Iterator encode(code_point value,Iterator out) + { + if(value <= 0x7F) { + *out++ = static_cast(value); + } + else if(value <= 0x7FF) { + *out++ = static_cast((value >> 6) | 0xC0); + *out++ = static_cast((value & 0x3F) | 0x80); + } + else if(NOWIDE_LIKELY(value <= 0xFFFF)) { + *out++ = static_cast((value >> 12) | 0xE0); + *out++ = static_cast(((value >> 6) & 0x3F) | 0x80); + *out++ = static_cast((value & 0x3F) | 0x80); + } + else { + *out++ = static_cast((value >> 18) | 0xF0); + *out++ = static_cast(((value >> 12) & 0x3F) | 0x80); + *out++ = static_cast(((value >> 6) & 0x3F) | 0x80); + *out++ = static_cast((value & 0x3F) | 0x80); + } + return out; + } + }; // utf8 + + template + struct utf_traits { + typedef CharType char_type; + + // See RFC 2781 + static bool is_first_surrogate(uint16_t x) + { + return 0xD800 <=x && x<= 0xDBFF; + } + static bool is_second_surrogate(uint16_t x) + { + return 0xDC00 <=x && x<= 0xDFFF; + } + static code_point combine_surrogate(uint16_t w1,uint16_t w2) + { + return ((code_point(w1 & 0x3FF) << 10) | (w2 & 0x3FF)) + 0x10000; + } + static int trail_length(char_type c) + { + if(is_first_surrogate(c)) + return 1; + if(is_second_surrogate(c)) + return -1; + return 0; + } + /// + /// Returns true if c is trail code unit, always false for UTF-32 + /// + static bool is_trail(char_type c) + { + return is_second_surrogate(c); + } + /// + /// Returns true if c is lead code unit, always true of UTF-32 + /// + static bool is_lead(char_type c) + { + return !is_second_surrogate(c); + } + + template + static code_point decode(It ¤t,It last) + { + if(NOWIDE_UNLIKELY(current == last)) + return incomplete; + uint16_t w1=*current++; + if(NOWIDE_LIKELY(w1 < 0xD800 || 0xDFFF < w1)) { + return w1; + } + if(w1 > 0xDBFF) + return illegal; + if(current==last) + return incomplete; + uint16_t w2=*current++; + if(w2 < 0xDC00 || 0xDFFF < w2) + return illegal; + return combine_surrogate(w1,w2); + } + template + static code_point decode_valid(It ¤t) + { + uint16_t w1=*current++; + if(NOWIDE_LIKELY(w1 < 0xD800 || 0xDFFF < w1)) { + return w1; + } + uint16_t w2=*current++; + return combine_surrogate(w1,w2); + } + + static const int max_width = 2; + static int width(code_point u) + { + return u>=0x10000 ? 2 : 1; + } + template + static It encode(code_point u,It out) + { + if(NOWIDE_LIKELY(u<=0xFFFF)) { + *out++ = static_cast(u); + } + else { + u -= 0x10000; + *out++ = static_cast(0xD800 | (u>>10)); + *out++ = static_cast(0xDC00 | (u & 0x3FF)); + } + return out; + } + }; // utf16; + + + template + struct utf_traits { + typedef CharType char_type; + static int trail_length(char_type c) + { + if(is_valid_codepoint(c)) + return 0; + return -1; + } + static bool is_trail(char_type /*c*/) + { + return false; + } + static bool is_lead(char_type /*c*/) + { + return true; + } + + template + static code_point decode_valid(It ¤t) + { + return *current++; + } + + template + static code_point decode(It ¤t,It last) + { + if(NOWIDE_UNLIKELY(current == last)) + return nowide::utf::incomplete; + code_point c=*current++; + if(NOWIDE_UNLIKELY(!is_valid_codepoint(c))) + return nowide::utf::illegal; + return c; + } + static const int max_width = 1; + static int width(code_point /*u*/) + { + return 1; + } + template + static It encode(code_point u,It out) + { + *out++ = static_cast(u); + return out; + } + + }; // utf32 + + #endif + +} // utf +} // nowide + + +#endif + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/deps/include/nowide/windows.hpp b/deps/include/nowide/windows.hpp new file mode 100644 index 0000000..b9abff4 --- /dev/null +++ b/deps/include/nowide/windows.hpp @@ -0,0 +1,39 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef NOWIDE_WINDOWS_HPP_INCLUDED +#define NOWIDE_WINDOWS_HPP_INCLUDED + +#include + +#ifdef NOWIDE_USE_WINDOWS_H +#include +#else + +// +// These are function prototypes... Allow to to include windows.h +// +extern "C" { + +__declspec(dllimport) wchar_t* __stdcall GetEnvironmentStringsW(void); +__declspec(dllimport) int __stdcall FreeEnvironmentStringsW(wchar_t *); +__declspec(dllimport) wchar_t* __stdcall GetCommandLineW(void); +__declspec(dllimport) wchar_t** __stdcall CommandLineToArgvW(wchar_t const *,int *); +__declspec(dllimport) unsigned long __stdcall GetLastError(); +__declspec(dllimport) void* __stdcall LocalFree(void *); +__declspec(dllimport) int __stdcall SetEnvironmentVariableW(wchar_t const *,wchar_t const *); +__declspec(dllimport) unsigned long __stdcall GetEnvironmentVariableW(wchar_t const *,wchar_t *,unsigned long); + +} + +#endif + + + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/deps/include/tclap/Arg.h b/deps/include/tclap/Arg.h new file mode 100644 index 0000000..b28eef1 --- /dev/null +++ b/deps/include/tclap/Arg.h @@ -0,0 +1,692 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: Arg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_ARGUMENT_H +#define TCLAP_ARGUMENT_H + +#ifdef HAVE_CONFIG_H +#include +#else +#define HAVE_SSTREAM +#endif + +#include +#include +#include +#include +#include +#include + +#if defined(HAVE_SSTREAM) +#include +typedef std::istringstream istringstream; +#elif defined(HAVE_STRSTREAM) +#include +typedef std::istrstream istringstream; +#else +#error "Need a stringstream (sstream or strstream) to compile!" +#endif + +#include +#include +#include +#include +#include + +namespace TCLAP { + +/** + * A virtual base class that defines the essential data for all arguments. + * This class, or one of its existing children, must be subclassed to do + * anything. + */ +class Arg +{ + private: + /** + * Prevent accidental copying. + */ + Arg(const Arg& rhs); + + /** + * Prevent accidental copying. + */ + Arg& operator=(const Arg& rhs); + + /** + * Indicates whether the rest of the arguments should be ignored. + */ + static bool& ignoreRestRef() { static bool ign = false; return ign; } + + /** + * The delimiter that separates an argument flag/name from the + * value. + */ + static char& delimiterRef() { static char delim = ' '; return delim; } + + protected: + + /** + * The single char flag used to identify the argument. + * This value (preceded by a dash {-}), can be used to identify + * an argument on the command line. The _flag can be blank, + * in fact this is how unlabeled args work. Unlabeled args must + * override appropriate functions to get correct handling. Note + * that the _flag does NOT include the dash as part of the flag. + */ + std::string _flag; + + /** + * A single work namd indentifying the argument. + * This value (preceded by two dashed {--}) can also be used + * to identify an argument on the command line. Note that the + * _name does NOT include the two dashes as part of the _name. The + * _name cannot be blank. + */ + std::string _name; + + /** + * Description of the argument. + */ + std::string _description; + + /** + * Indicating whether the argument is required. + */ + bool _required; + + /** + * Label to be used in usage description. Normally set to + * "required", but can be changed when necessary. + */ + std::string _requireLabel; + + /** + * Indicates whether a value is required for the argument. + * Note that the value may be required but the argument/value + * combination may not be, as specified by _required. + */ + bool _valueRequired; + + /** + * Indicates whether the argument has been set. + * Indicates that a value on the command line has matched the + * name/flag of this argument and the values have been set accordingly. + */ + bool _alreadySet; + + /** + * A pointer to a vistitor object. + * The visitor allows special handling to occur as soon as the + * argument is matched. This defaults to NULL and should not + * be used unless absolutely necessary. + */ + Visitor* _visitor; + + /** + * Whether this argument can be ignored, if desired. + */ + bool _ignoreable; + + /** + * Indicates that the arg was set as part of an XOR and not on the + * command line. + */ + bool _xorSet; + + bool _acceptsMultipleValues; + + /** + * Performs the special handling described by the Vistitor. + */ + void _checkWithVisitor() const; + + /** + * Primary constructor. YOU (yes you) should NEVER construct an Arg + * directly, this is a base class that is extended by various children + * that are meant to be used. Use SwitchArg, ValueArg, MultiArg, + * UnlabeledValueArg, or UnlabeledMultiArg instead. + * + * \param flag - The flag identifying the argument. + * \param name - The name identifying the argument. + * \param desc - The description of the argument, used in the usage. + * \param req - Whether the argument is required. + * \param valreq - Whether the a value is required for the argument. + * \param v - The visitor checked by the argument. Defaults to NULL. + */ + Arg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + bool valreq, + Visitor* v = NULL ); + + public: + /** + * Destructor. + */ + virtual ~Arg(); + + /** + * Adds this to the specified list of Args. + * \param argList - The list to add this to. + */ + virtual void addToList( std::list& argList ) const; + + /** + * Begin ignoring arguments since the "--" argument was specified. + */ + static void beginIgnoring() { ignoreRestRef() = true; } + + /** + * Whether to ignore the rest. + */ + static bool ignoreRest() { return ignoreRestRef(); } + + /** + * The delimiter that separates an argument flag/name from the + * value. + */ + static char delimiter() { return delimiterRef(); } + + /** + * The char used as a place holder when SwitchArgs are combined. + * Currently set to the bell char (ASCII 7). + */ + static char blankChar() { return (char)7; } + + /** + * The char that indicates the beginning of a flag. Defaults to '-', but + * clients can define TCLAP_FLAGSTARTCHAR to override. + */ +#ifndef TCLAP_FLAGSTARTCHAR +#define TCLAP_FLAGSTARTCHAR '-' +#endif + static char flagStartChar() { return TCLAP_FLAGSTARTCHAR; } + + /** + * The sting that indicates the beginning of a flag. Defaults to "-", but + * clients can define TCLAP_FLAGSTARTSTRING to override. Should be the same + * as TCLAP_FLAGSTARTCHAR. + */ +#ifndef TCLAP_FLAGSTARTSTRING +#define TCLAP_FLAGSTARTSTRING "-" +#endif + static const std::string flagStartString() { return TCLAP_FLAGSTARTSTRING; } + + /** + * The sting that indicates the beginning of a name. Defaults to "--", but + * clients can define TCLAP_NAMESTARTSTRING to override. + */ +#ifndef TCLAP_NAMESTARTSTRING +#define TCLAP_NAMESTARTSTRING "--" +#endif + static const std::string nameStartString() { return TCLAP_NAMESTARTSTRING; } + + /** + * The name used to identify the ignore rest argument. + */ + static const std::string ignoreNameString() { return "ignore_rest"; } + + /** + * Sets the delimiter for all arguments. + * \param c - The character that delimits flags/names from values. + */ + static void setDelimiter( char c ) { delimiterRef() = c; } + + /** + * Pure virtual method meant to handle the parsing and value assignment + * of the string on the command line. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. What is + * passed in from main. + */ + virtual bool processArg(int *i, std::vector& args) = 0; + + /** + * Operator ==. + * Equality operator. Must be virtual to handle unlabeled args. + * \param a - The Arg to be compared to this. + */ + virtual bool operator==(const Arg& a) const; + + /** + * Returns the argument flag. + */ + const std::string& getFlag() const; + + /** + * Returns the argument name. + */ + const std::string& getName() const; + + /** + * Returns the argument description. + */ + std::string getDescription() const; + + /** + * Indicates whether the argument is required. + */ + virtual bool isRequired() const; + + /** + * Sets _required to true. This is used by the XorHandler. + * You really have no reason to ever use it. + */ + void forceRequired(); + + /** + * Sets the _alreadySet value to true. This is used by the XorHandler. + * You really have no reason to ever use it. + */ + void xorSet(); + + /** + * Indicates whether a value must be specified for argument. + */ + bool isValueRequired() const; + + /** + * Indicates whether the argument has already been set. Only true + * if the arg has been matched on the command line. + */ + bool isSet() const; + + /** + * Indicates whether the argument can be ignored, if desired. + */ + bool isIgnoreable() const; + + /** + * A method that tests whether a string matches this argument. + * This is generally called by the processArg() method. This + * method could be re-implemented by a child to change how + * arguments are specified on the command line. + * \param s - The string to be compared to the flag/name to determine + * whether the arg matches. + */ + virtual bool argMatches( const std::string& s ) const; + + /** + * Returns a simple string representation of the argument. + * Primarily for debugging. + */ + virtual std::string toString() const; + + /** + * Returns a short ID for the usage. + * \param valueId - The value used in the id. + */ + virtual std::string shortID( const std::string& valueId = "val" ) const; + + /** + * Returns a long ID for the usage. + * \param valueId - The value used in the id. + */ + virtual std::string longID( const std::string& valueId = "val" ) const; + + /** + * Trims a value off of the flag. + * \param flag - The string from which the flag and value will be + * trimmed. Contains the flag once the value has been trimmed. + * \param value - Where the value trimmed from the string will + * be stored. + */ + virtual void trimFlag( std::string& flag, std::string& value ) const; + + /** + * Checks whether a given string has blank chars, indicating that + * it is a combined SwitchArg. If so, return true, otherwise return + * false. + * \param s - string to be checked. + */ + bool _hasBlanks( const std::string& s ) const; + + /** + * Sets the requireLabel. Used by XorHandler. You shouldn't ever + * use this. + * \param s - Set the requireLabel to this value. + */ + void setRequireLabel( const std::string& s ); + + /** + * Used for MultiArgs and XorHandler to determine whether args + * can still be set. + */ + virtual bool allowMore(); + + /** + * Use by output classes to determine whether an Arg accepts + * multiple values. + */ + virtual bool acceptsMultipleValues(); + + /** + * Clears the Arg object and allows it to be reused by new + * command lines. + */ + virtual void reset(); +}; + +/** + * Typedef of an Arg list iterator. + */ +typedef std::list::iterator ArgListIterator; + +/** + * Typedef of an Arg vector iterator. + */ +typedef std::vector::iterator ArgVectorIterator; + +/** + * Typedef of a Visitor list iterator. + */ +typedef std::list::iterator VisitorListIterator; + +/* + * Extract a value of type T from it's string representation contained + * in strVal. The ValueLike parameter used to select the correct + * specialization of ExtractValue depending on the value traits of T. + * ValueLike traits use operator>> to assign the value from strVal. + */ +template void +ExtractValue(T &destVal, const std::string& strVal, ValueLike vl) +{ + static_cast(vl); // Avoid warning about unused vl + std::istringstream is(strVal); + + int valuesRead = 0; + while ( is.good() ) { + if ( is.peek() != EOF ) +#ifdef TCLAP_SETBASE_ZERO + is >> std::setbase(0) >> destVal; +#else + is >> destVal; +#endif + else + break; + + valuesRead++; + } + + if ( is.fail() ) + throw( ArgParseException("Couldn't read argument value " + "from string '" + strVal + "'")); + + + if ( valuesRead > 1 ) + throw( ArgParseException("More than one valid value parsed from " + "string '" + strVal + "'")); + +} + +/* + * Extract a value of type T from it's string representation contained + * in strVal. The ValueLike parameter used to select the correct + * specialization of ExtractValue depending on the value traits of T. + * StringLike uses assignment (operator=) to assign from strVal. + */ +template void +ExtractValue(T &destVal, const std::string& strVal, StringLike sl) +{ + static_cast(sl); // Avoid warning about unused sl + SetString(destVal, strVal); +} + +////////////////////////////////////////////////////////////////////// +//BEGIN Arg.cpp +////////////////////////////////////////////////////////////////////// + +inline Arg::Arg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + bool valreq, + Visitor* v) : + _flag(flag), + _name(name), + _description(desc), + _required(req), + _requireLabel("required"), + _valueRequired(valreq), + _alreadySet(false), + _visitor( v ), + _ignoreable(true), + _xorSet(false), + _acceptsMultipleValues(false) +{ + if ( _flag.length() > 1 ) + throw(SpecificationException( + "Argument flag can only be one character long", toString() ) ); + + if ( _name != ignoreNameString() && + ( _flag == Arg::flagStartString() || + _flag == Arg::nameStartString() || + _flag == " " ) ) + throw(SpecificationException("Argument flag cannot be either '" + + Arg::flagStartString() + "' or '" + + Arg::nameStartString() + "' or a space.", + toString() ) ); + + if ( ( _name.substr( 0, Arg::flagStartString().length() ) == Arg::flagStartString() ) || + ( _name.substr( 0, Arg::nameStartString().length() ) == Arg::nameStartString() ) || + ( _name.find( " ", 0 ) != std::string::npos ) ) + throw(SpecificationException("Argument name begin with either '" + + Arg::flagStartString() + "' or '" + + Arg::nameStartString() + "' or space.", + toString() ) ); + +} + +inline Arg::~Arg() { } + +inline std::string Arg::shortID( const std::string& valueId ) const +{ + std::string id = ""; + + if ( _flag != "" ) + id = Arg::flagStartString() + _flag; + else + id = Arg::nameStartString() + _name; + + if ( _valueRequired ) + id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + + if ( !_required ) + id = "[" + id + "]"; + + return id; +} + +inline std::string Arg::longID( const std::string& valueId ) const +{ + std::string id = ""; + + if ( _flag != "" ) + { + id += Arg::flagStartString() + _flag; + + if ( _valueRequired ) + id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + + id += ", "; + } + + id += Arg::nameStartString() + _name; + + if ( _valueRequired ) + id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + + return id; + +} + +inline bool Arg::operator==(const Arg& a) const +{ + if ( ( _flag != "" && _flag == a._flag ) || _name == a._name) + return true; + else + return false; +} + +inline std::string Arg::getDescription() const +{ + std::string desc = ""; + if ( _required ) + desc = "(" + _requireLabel + ") "; + +// if ( _valueRequired ) +// desc += "(value required) "; + + desc += _description; + return desc; +} + +inline const std::string& Arg::getFlag() const { return _flag; } + +inline const std::string& Arg::getName() const { return _name; } + +inline bool Arg::isRequired() const { return _required; } + +inline bool Arg::isValueRequired() const { return _valueRequired; } + +inline bool Arg::isSet() const +{ + if ( _alreadySet && !_xorSet ) + return true; + else + return false; +} + +inline bool Arg::isIgnoreable() const { return _ignoreable; } + +inline void Arg::setRequireLabel( const std::string& s) +{ + _requireLabel = s; +} + +inline bool Arg::argMatches( const std::string& argFlag ) const +{ + if ( ( argFlag == Arg::flagStartString() + _flag && _flag != "" ) || + argFlag == Arg::nameStartString() + _name ) + return true; + else + return false; +} + +inline std::string Arg::toString() const +{ + std::string s = ""; + + if ( _flag != "" ) + s += Arg::flagStartString() + _flag + " "; + + s += "(" + Arg::nameStartString() + _name + ")"; + + return s; +} + +inline void Arg::_checkWithVisitor() const +{ + if ( _visitor != NULL ) + _visitor->visit(); +} + +/** + * Implementation of trimFlag. + */ +inline void Arg::trimFlag(std::string& flag, std::string& value) const +{ + int stop = 0; + for ( int i = 0; static_cast(i) < flag.length(); i++ ) + if ( flag[i] == Arg::delimiter() ) + { + stop = i; + break; + } + + if ( stop > 1 ) + { + value = flag.substr(stop+1); + flag = flag.substr(0,stop); + } + +} + +/** + * Implementation of _hasBlanks. + */ +inline bool Arg::_hasBlanks( const std::string& s ) const +{ + for ( int i = 1; static_cast(i) < s.length(); i++ ) + if ( s[i] == Arg::blankChar() ) + return true; + + return false; +} + +inline void Arg::forceRequired() +{ + _required = true; +} + +inline void Arg::xorSet() +{ + _alreadySet = true; + _xorSet = true; +} + +/** + * Overridden by Args that need to added to the end of the list. + */ +inline void Arg::addToList( std::list& argList ) const +{ + argList.push_front( const_cast(this) ); +} + +inline bool Arg::allowMore() +{ + return false; +} + +inline bool Arg::acceptsMultipleValues() +{ + return _acceptsMultipleValues; +} + +inline void Arg::reset() +{ + _xorSet = false; + _alreadySet = false; +} + +////////////////////////////////////////////////////////////////////// +//END Arg.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif + diff --git a/deps/include/tclap/ArgException.h b/deps/include/tclap/ArgException.h new file mode 100644 index 0000000..3411aa9 --- /dev/null +++ b/deps/include/tclap/ArgException.h @@ -0,0 +1,200 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: ArgException.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_ARG_EXCEPTION_H +#define TCLAP_ARG_EXCEPTION_H + +#include +#include + +namespace TCLAP { + +/** + * A simple class that defines and argument exception. Should be caught + * whenever a CmdLine is created and parsed. + */ +class ArgException : public std::exception +{ + public: + + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source. + * \param td - Text describing the type of ArgException it is. + * of the exception. + */ + ArgException( const std::string& text = "undefined exception", + const std::string& id = "undefined", + const std::string& td = "Generic ArgException") + : std::exception(), + _errorText(text), + _argId( id ), + _typeDescription(td) + { } + + /** + * Destructor. + */ + virtual ~ArgException() throw() { } + + /** + * Returns the error text. + */ + std::string error() const { return ( _errorText ); } + + /** + * Returns the argument id. + */ + std::string argId() const + { + if ( _argId == "undefined" ) + return " "; + else + return ( "Argument: " + _argId ); + } + + /** + * Returns the arg id and error text. + */ + const char* what() const throw() + { + static std::string ex; + ex = _argId + " -- " + _errorText; + return ex.c_str(); + } + + /** + * Returns the type of the exception. Used to explain and distinguish + * between different child exceptions. + */ + std::string typeDescription() const + { + return _typeDescription; + } + + + private: + + /** + * The text of the exception message. + */ + std::string _errorText; + + /** + * The argument related to this exception. + */ + std::string _argId; + + /** + * Describes the type of the exception. Used to distinguish + * between different child exceptions. + */ + std::string _typeDescription; + +}; + +/** + * Thrown from within the child Arg classes when it fails to properly + * parse the argument it has been passed. + */ +class ArgParseException : public ArgException +{ + public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + ArgParseException( const std::string& text = "undefined exception", + const std::string& id = "undefined" ) + : ArgException( text, + id, + std::string( "Exception found while parsing " ) + + std::string( "the value the Arg has been passed." )) + { } +}; + +/** + * Thrown from CmdLine when the arguments on the command line are not + * properly specified, e.g. too many arguments, required argument missing, etc. + */ +class CmdLineParseException : public ArgException +{ + public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + CmdLineParseException( const std::string& text = "undefined exception", + const std::string& id = "undefined" ) + : ArgException( text, + id, + std::string( "Exception found when the values ") + + std::string( "on the command line do not meet ") + + std::string( "the requirements of the defined ") + + std::string( "Args." )) + { } +}; + +/** + * Thrown from Arg and CmdLine when an Arg is improperly specified, e.g. + * same flag as another Arg, same name, etc. + */ +class SpecificationException : public ArgException +{ + public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + SpecificationException( const std::string& text = "undefined exception", + const std::string& id = "undefined" ) + : ArgException( text, + id, + std::string("Exception found when an Arg object ")+ + std::string("is improperly defined by the ") + + std::string("developer." )) + { } + +}; + +class ExitException { +public: + ExitException(int estat) : _estat(estat) {} + + int getExitStatus() const { return _estat; } + +private: + int _estat; +}; + +} // namespace TCLAP + +#endif + diff --git a/deps/include/tclap/ArgTraits.h b/deps/include/tclap/ArgTraits.h new file mode 100644 index 0000000..0b2c18f --- /dev/null +++ b/deps/include/tclap/ArgTraits.h @@ -0,0 +1,87 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: ArgTraits.h + * + * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +// This is an internal tclap file, you should probably not have to +// include this directly + +#ifndef TCLAP_ARGTRAITS_H +#define TCLAP_ARGTRAITS_H + +namespace TCLAP { + +// We use two empty structs to get compile type specialization +// function to work + +/** + * A value like argument value type is a value that can be set using + * operator>>. This is the default value type. + */ +struct ValueLike { + typedef ValueLike ValueCategory; + virtual ~ValueLike() {} +}; + +/** + * A string like argument value type is a value that can be set using + * operator=(string). Usefull if the value type contains spaces which + * will be broken up into individual tokens by operator>>. + */ +struct StringLike { + virtual ~StringLike() {} +}; + +/** + * A class can inherit from this object to make it have string like + * traits. This is a compile time thing and does not add any overhead + * to the inherenting class. + */ +struct StringLikeTrait { + typedef StringLike ValueCategory; + virtual ~StringLikeTrait() {} +}; + +/** + * A class can inherit from this object to make it have value like + * traits. This is a compile time thing and does not add any overhead + * to the inherenting class. + */ +struct ValueLikeTrait { + typedef ValueLike ValueCategory; + virtual ~ValueLikeTrait() {} +}; + +/** + * Arg traits are used to get compile type specialization when parsing + * argument values. Using an ArgTraits you can specify the way that + * values gets assigned to any particular type during parsing. The two + * supported types are StringLike and ValueLike. + */ +template +struct ArgTraits { + typedef typename T::ValueCategory ValueCategory; + virtual ~ArgTraits() {} + //typedef ValueLike ValueCategory; +}; + +#endif + +} // namespace diff --git a/deps/include/tclap/CmdLine.h b/deps/include/tclap/CmdLine.h new file mode 100644 index 0000000..0fec8d8 --- /dev/null +++ b/deps/include/tclap/CmdLine.h @@ -0,0 +1,633 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: CmdLine.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_CMDLINE_H +#define TCLAP_CMDLINE_H + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include // Needed for exit(), which isn't defined in some envs. + +namespace TCLAP { + +template void DelPtr(T ptr) +{ + delete ptr; +} + +template void ClearContainer(C &c) +{ + typedef typename C::value_type value_type; + std::for_each(c.begin(), c.end(), DelPtr); + c.clear(); +} + + +/** + * The base class that manages the command line definition and passes + * along the parsing to the appropriate Arg classes. + */ +class CmdLine : public CmdLineInterface +{ + protected: + + /** + * The list of arguments that will be tested against the + * command line. + */ + std::list _argList; + + /** + * The name of the program. Set to argv[0]. + */ + std::string _progName; + + /** + * A message used to describe the program. Used in the usage output. + */ + std::string _message; + + /** + * The version to be displayed with the --version switch. + */ + std::string _version; + + /** + * The number of arguments that are required to be present on + * the command line. This is set dynamically, based on the + * Args added to the CmdLine object. + */ + int _numRequired; + + /** + * The character that is used to separate the argument flag/name + * from the value. Defaults to ' ' (space). + */ + char _delimiter; + + /** + * The handler that manages xoring lists of args. + */ + XorHandler _xorHandler; + + /** + * A list of Args to be explicitly deleted when the destructor + * is called. At the moment, this only includes the three default + * Args. + */ + std::list _argDeleteOnExitList; + + /** + * A list of Visitors to be explicitly deleted when the destructor + * is called. At the moment, these are the Vistors created for the + * default Args. + */ + std::list _visitorDeleteOnExitList; + + /** + * Object that handles all output for the CmdLine. + */ + CmdLineOutput* _output; + + /** + * Should CmdLine handle parsing exceptions internally? + */ + bool _handleExceptions; + + /** + * Throws an exception listing the missing args. + */ + void missingArgsException(); + + /** + * Checks whether a name/flag string matches entirely matches + * the Arg::blankChar. Used when multiple switches are combined + * into a single argument. + * \param s - The message to be used in the usage. + */ + bool _emptyCombined(const std::string& s); + + /** + * Perform a delete ptr; operation on ptr when this object is deleted. + */ + void deleteOnExit(Arg* ptr); + + /** + * Perform a delete ptr; operation on ptr when this object is deleted. + */ + void deleteOnExit(Visitor* ptr); + +private: + + /** + * Prevent accidental copying. + */ + CmdLine(const CmdLine& rhs); + CmdLine& operator=(const CmdLine& rhs); + + /** + * Encapsulates the code common to the constructors + * (which is all of it). + */ + void _constructor(); + + + /** + * Is set to true when a user sets the output object. We use this so + * that we don't delete objects that are created outside of this lib. + */ + bool _userSetOutput; + + /** + * Whether or not to automatically create help and version switches. + */ + bool _helpAndVersion; + + public: + + /** + * Command line constructor. Defines how the arguments will be + * parsed. + * \param message - The message to be used in the usage + * output. + * \param delimiter - The character that is used to separate + * the argument flag/name from the value. Defaults to ' ' (space). + * \param version - The version number to be used in the + * --version switch. + * \param helpAndVersion - Whether or not to create the Help and + * Version switches. Defaults to true. + */ + CmdLine(const std::string& message, + const char delimiter = ' ', + const std::string& version = "none", + bool helpAndVersion = true); + + /** + * Deletes any resources allocated by a CmdLine object. + */ + virtual ~CmdLine(); + + /** + * Adds an argument to the list of arguments to be parsed. + * \param a - Argument to be added. + */ + void add( Arg& a ); + + /** + * An alternative add. Functionally identical. + * \param a - Argument to be added. + */ + void add( Arg* a ); + + /** + * Add two Args that will be xor'd. If this method is used, add does + * not need to be called. + * \param a - Argument to be added and xor'd. + * \param b - Argument to be added and xor'd. + */ + void xorAdd( Arg& a, Arg& b ); + + /** + * Add a list of Args that will be xor'd. If this method is used, + * add does not need to be called. + * \param xors - List of Args to be added and xor'd. + */ + void xorAdd( std::vector& xors ); + + /** + * Parses the command line. + * \param argc - Number of arguments. + * \param argv - Array of arguments. + */ + void parse(int argc, const char * const * argv); + + /** + * Parses the command line. + * \param args - A vector of strings representing the args. + * args[0] is still the program name. + */ + void parse(std::vector& args); + + /** + * + */ + CmdLineOutput* getOutput(); + + /** + * + */ + void setOutput(CmdLineOutput* co); + + /** + * + */ + std::string& getVersion(); + + /** + * + */ + std::string& getProgramName(); + + /** + * + */ + std::list& getArgList(); + + /** + * + */ + XorHandler& getXorHandler(); + + /** + * + */ + char getDelimiter(); + + /** + * + */ + std::string& getMessage(); + + /** + * + */ + bool hasHelpAndVersion(); + + /** + * Disables or enables CmdLine's internal parsing exception handling. + * + * @param state Should CmdLine handle parsing exceptions internally? + */ + void setExceptionHandling(const bool state); + + /** + * Returns the current state of the internal exception handling. + * + * @retval true Parsing exceptions are handled internally. + * @retval false Parsing exceptions are propagated to the caller. + */ + bool getExceptionHandling() const; + + /** + * Allows the CmdLine object to be reused. + */ + void reset(); + +}; + + +/////////////////////////////////////////////////////////////////////////////// +//Begin CmdLine.cpp +/////////////////////////////////////////////////////////////////////////////// + +inline CmdLine::CmdLine(const std::string& m, + char delim, + const std::string& v, + bool help ) + : + _argList(std::list()), + _progName("not_set_yet"), + _message(m), + _version(v), + _numRequired(0), + _delimiter(delim), + _xorHandler(XorHandler()), + _argDeleteOnExitList(std::list()), + _visitorDeleteOnExitList(std::list()), + _output(0), + _handleExceptions(true), + _userSetOutput(false), + _helpAndVersion(help) +{ + _constructor(); +} + +inline CmdLine::~CmdLine() +{ + ClearContainer(_argDeleteOnExitList); + ClearContainer(_visitorDeleteOnExitList); + + if ( !_userSetOutput ) { + delete _output; + _output = 0; + } +} + +inline void CmdLine::_constructor() +{ + _output = new StdOutput; + + Arg::setDelimiter( _delimiter ); + + Visitor* v; + + if ( _helpAndVersion ) + { + v = new HelpVisitor( this, &_output ); + SwitchArg* help = new SwitchArg("h","help", + "Displays usage information and exits.", + false, v); + add( help ); + deleteOnExit(help); + deleteOnExit(v); + + v = new VersionVisitor( this, &_output ); + SwitchArg* vers = new SwitchArg("","version", + "Displays version information and exits.", + false, v); + add( vers ); + deleteOnExit(vers); + deleteOnExit(v); + } + + v = new IgnoreRestVisitor(); + SwitchArg* ignore = new SwitchArg(Arg::flagStartString(), + Arg::ignoreNameString(), + "Ignores the rest of the labeled arguments following this flag.", + false, v); + add( ignore ); + deleteOnExit(ignore); + deleteOnExit(v); +} + +inline void CmdLine::xorAdd( std::vector& ors ) +{ + _xorHandler.add( ors ); + + for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++) + { + (*it)->forceRequired(); + (*it)->setRequireLabel( "OR required" ); + add( *it ); + } +} + +inline void CmdLine::xorAdd( Arg& a, Arg& b ) +{ + std::vector ors; + ors.push_back( &a ); + ors.push_back( &b ); + xorAdd( ors ); +} + +inline void CmdLine::add( Arg& a ) +{ + add( &a ); +} + +inline void CmdLine::add( Arg* a ) +{ + for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ ) + if ( *a == *(*it) ) + throw( SpecificationException( + "Argument with same flag/name already exists!", + a->longID() ) ); + + a->addToList( _argList ); + + if ( a->isRequired() ) + _numRequired++; +} + + +inline void CmdLine::parse(int argc, const char * const * argv) +{ + // this step is necessary so that we have easy access to + // mutable strings. + std::vector args; + for (int i = 0; i < argc; i++) + args.push_back(argv[i]); + + parse(args); +} + +inline void CmdLine::parse(std::vector& args) +{ + bool shouldExit = false; + int estat = 0; + + try { + _progName = args.front(); + args.erase(args.begin()); + + int requiredCount = 0; + + for (int i = 0; static_cast(i) < args.size(); i++) + { + bool matched = false; + for (ArgListIterator it = _argList.begin(); + it != _argList.end(); it++) { + if ( (*it)->processArg( &i, args ) ) + { + requiredCount += _xorHandler.check( *it ); + matched = true; + break; + } + } + + // checks to see if the argument is an empty combined + // switch and if so, then we've actually matched it + if ( !matched && _emptyCombined( args[i] ) ) + matched = true; + + if ( !matched && !Arg::ignoreRest() ) + throw(CmdLineParseException("Couldn't find match " + "for argument", + args[i])); + } + + if ( requiredCount < _numRequired ) + missingArgsException(); + + if ( requiredCount > _numRequired ) + throw(CmdLineParseException("Too many arguments!")); + + } catch ( ArgException& e ) { + // If we're not handling the exceptions, rethrow. + if ( !_handleExceptions) { + throw; + } + + try { + _output->failure(*this,e); + } catch ( ExitException &ee ) { + estat = ee.getExitStatus(); + shouldExit = true; + } + } catch (ExitException &ee) { + // If we're not handling the exceptions, rethrow. + if ( !_handleExceptions) { + throw; + } + + estat = ee.getExitStatus(); + shouldExit = true; + } + + if (shouldExit) + exit(estat); +} + +inline bool CmdLine::_emptyCombined(const std::string& s) +{ + if ( s.length() > 0 && s[0] != Arg::flagStartChar() ) + return false; + + for ( int i = 1; static_cast(i) < s.length(); i++ ) + if ( s[i] != Arg::blankChar() ) + return false; + + return true; +} + +inline void CmdLine::missingArgsException() +{ + int count = 0; + + std::string missingArgList; + for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++) + { + if ( (*it)->isRequired() && !(*it)->isSet() ) + { + missingArgList += (*it)->getName(); + missingArgList += ", "; + count++; + } + } + missingArgList = missingArgList.substr(0,missingArgList.length()-2); + + std::string msg; + if ( count > 1 ) + msg = "Required arguments missing: "; + else + msg = "Required argument missing: "; + + msg += missingArgList; + + throw(CmdLineParseException(msg)); +} + +inline void CmdLine::deleteOnExit(Arg* ptr) +{ + _argDeleteOnExitList.push_back(ptr); +} + +inline void CmdLine::deleteOnExit(Visitor* ptr) +{ + _visitorDeleteOnExitList.push_back(ptr); +} + +inline CmdLineOutput* CmdLine::getOutput() +{ + return _output; +} + +inline void CmdLine::setOutput(CmdLineOutput* co) +{ + if ( !_userSetOutput ) + delete _output; + _userSetOutput = true; + _output = co; +} + +inline std::string& CmdLine::getVersion() +{ + return _version; +} + +inline std::string& CmdLine::getProgramName() +{ + return _progName; +} + +inline std::list& CmdLine::getArgList() +{ + return _argList; +} + +inline XorHandler& CmdLine::getXorHandler() +{ + return _xorHandler; +} + +inline char CmdLine::getDelimiter() +{ + return _delimiter; +} + +inline std::string& CmdLine::getMessage() +{ + return _message; +} + +inline bool CmdLine::hasHelpAndVersion() +{ + return _helpAndVersion; +} + +inline void CmdLine::setExceptionHandling(const bool state) +{ + _handleExceptions = state; +} + +inline bool CmdLine::getExceptionHandling() const +{ + return _handleExceptions; +} + +inline void CmdLine::reset() +{ + for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ ) + (*it)->reset(); + + _progName.clear(); +} + +/////////////////////////////////////////////////////////////////////////////// +//End CmdLine.cpp +/////////////////////////////////////////////////////////////////////////////// + + + +} //namespace TCLAP +#endif diff --git a/deps/include/tclap/CmdLineInterface.h b/deps/include/tclap/CmdLineInterface.h new file mode 100644 index 0000000..1b25e9b --- /dev/null +++ b/deps/include/tclap/CmdLineInterface.h @@ -0,0 +1,150 @@ + +/****************************************************************************** + * + * file: CmdLineInterface.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_COMMANDLINE_INTERFACE_H +#define TCLAP_COMMANDLINE_INTERFACE_H + +#include +#include +#include +#include +#include + + +namespace TCLAP { + +class Arg; +class CmdLineOutput; +class XorHandler; + +/** + * The base class that manages the command line definition and passes + * along the parsing to the appropriate Arg classes. + */ +class CmdLineInterface +{ + public: + + /** + * Destructor + */ + virtual ~CmdLineInterface() {} + + /** + * Adds an argument to the list of arguments to be parsed. + * \param a - Argument to be added. + */ + virtual void add( Arg& a )=0; + + /** + * An alternative add. Functionally identical. + * \param a - Argument to be added. + */ + virtual void add( Arg* a )=0; + + /** + * Add two Args that will be xor'd. + * If this method is used, add does + * not need to be called. + * \param a - Argument to be added and xor'd. + * \param b - Argument to be added and xor'd. + */ + virtual void xorAdd( Arg& a, Arg& b )=0; + + /** + * Add a list of Args that will be xor'd. If this method is used, + * add does not need to be called. + * \param xors - List of Args to be added and xor'd. + */ + virtual void xorAdd( std::vector& xors )=0; + + /** + * Parses the command line. + * \param argc - Number of arguments. + * \param argv - Array of arguments. + */ + virtual void parse(int argc, const char * const * argv)=0; + + /** + * Parses the command line. + * \param args - A vector of strings representing the args. + * args[0] is still the program name. + */ + void parse(std::vector& args); + + /** + * Returns the CmdLineOutput object. + */ + virtual CmdLineOutput* getOutput()=0; + + /** + * \param co - CmdLineOutput object that we want to use instead. + */ + virtual void setOutput(CmdLineOutput* co)=0; + + /** + * Returns the version string. + */ + virtual std::string& getVersion()=0; + + /** + * Returns the program name string. + */ + virtual std::string& getProgramName()=0; + + /** + * Returns the argList. + */ + virtual std::list& getArgList()=0; + + /** + * Returns the XorHandler. + */ + virtual XorHandler& getXorHandler()=0; + + /** + * Returns the delimiter string. + */ + virtual char getDelimiter()=0; + + /** + * Returns the message string. + */ + virtual std::string& getMessage()=0; + + /** + * Indicates whether or not the help and version switches were created + * automatically. + */ + virtual bool hasHelpAndVersion()=0; + + /** + * Resets the instance as if it had just been constructed so that the + * instance can be reused. + */ + virtual void reset()=0; +}; + +} //namespace + + +#endif diff --git a/deps/include/tclap/CmdLineOutput.h b/deps/include/tclap/CmdLineOutput.h new file mode 100644 index 0000000..71ee5a3 --- /dev/null +++ b/deps/include/tclap/CmdLineOutput.h @@ -0,0 +1,74 @@ + + +/****************************************************************************** + * + * file: CmdLineOutput.h + * + * Copyright (c) 2004, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_CMDLINEOUTPUT_H +#define TCLAP_CMDLINEOUTPUT_H + +#include +#include +#include +#include +#include +#include + +namespace TCLAP { + +class CmdLineInterface; +class ArgException; + +/** + * The interface that any output object must implement. + */ +class CmdLineOutput +{ + + public: + + /** + * Virtual destructor. + */ + virtual ~CmdLineOutput() {} + + /** + * Generates some sort of output for the USAGE. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c)=0; + + /** + * Generates some sort of output for the version. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c)=0; + + /** + * Generates some sort of output for a failure. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure( CmdLineInterface& c, + ArgException& e )=0; + +}; + +} //namespace TCLAP +#endif diff --git a/deps/include/tclap/Constraint.h b/deps/include/tclap/Constraint.h new file mode 100644 index 0000000..a92acf9 --- /dev/null +++ b/deps/include/tclap/Constraint.h @@ -0,0 +1,68 @@ + +/****************************************************************************** + * + * file: Constraint.h + * + * Copyright (c) 2005, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_CONSTRAINT_H +#define TCLAP_CONSTRAINT_H + +#include +#include +#include +#include +#include +#include + +namespace TCLAP { + +/** + * The interface that defines the interaction between the Arg and Constraint. + */ +template +class Constraint +{ + + public: + /** + * Returns a description of the Constraint. + */ + virtual std::string description() const =0; + + /** + * Returns the short ID for the Constraint. + */ + virtual std::string shortID() const =0; + + /** + * The method used to verify that the value parsed from the command + * line meets the constraint. + * \param value - The value that will be checked. + */ + virtual bool check(const T& value) const =0; + + /** + * Destructor. + * Silences warnings about Constraint being a base class with virtual + * functions but without a virtual destructor. + */ + virtual ~Constraint() { ; } +}; + +} //namespace TCLAP +#endif diff --git a/deps/include/tclap/DocBookOutput.h b/deps/include/tclap/DocBookOutput.h new file mode 100644 index 0000000..a42ca27 --- /dev/null +++ b/deps/include/tclap/DocBookOutput.h @@ -0,0 +1,299 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: DocBookOutput.h + * + * Copyright (c) 2004, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_DOCBOOKOUTPUT_H +#define TCLAP_DOCBOOKOUTPUT_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace TCLAP { + +/** + * A class that generates DocBook output for usage() method for the + * given CmdLine and its Args. + */ +class DocBookOutput : public CmdLineOutput +{ + + public: + + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface& c, + ArgException& e ); + + protected: + + /** + * Substitutes the char r for string x in string s. + * \param s - The string to operate on. + * \param r - The char to replace. + * \param x - What to replace r with. + */ + void substituteSpecialChars( std::string& s, char r, std::string& x ); + void removeChar( std::string& s, char r); + void basename( std::string& s ); + + void printShortArg(Arg* it); + void printLongArg(Arg* it); + + char theDelimiter; +}; + + +inline void DocBookOutput::version(CmdLineInterface& _cmd) +{ + std::cout << _cmd.getVersion() << std::endl; +} + +inline void DocBookOutput::usage(CmdLineInterface& _cmd ) +{ + std::list argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + std::string xversion = _cmd.getVersion(); + theDelimiter = _cmd.getDelimiter(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector > xorList = xorHandler.getXorList(); + basename(progName); + + std::cout << "" << std::endl; + std::cout << "" << std::endl << std::endl; + + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "" << progName << "" << std::endl; + std::cout << "1" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "" << progName << "" << std::endl; + std::cout << "" << _cmd.getMessage() << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << progName << "" << std::endl; + + // xor + for ( int i = 0; (unsigned int)i < xorList.size(); i++ ) + { + std::cout << "" << std::endl; + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); it++ ) + printShortArg((*it)); + + std::cout << "" << std::endl; + } + + // rest of args + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if ( !xorHandler.contains( (*it) ) ) + printShortArg((*it)); + + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "Description" << std::endl; + std::cout << "" << std::endl; + std::cout << _cmd.getMessage() << std::endl; + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "Options" << std::endl; + + std::cout << "" << std::endl; + + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + printLongArg((*it)); + + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "Version" << std::endl; + std::cout << "" << std::endl; + std::cout << xversion << std::endl; + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + +} + +inline void DocBookOutput::failure( CmdLineInterface& _cmd, + ArgException& e ) +{ + static_cast(_cmd); // unused + std::cout << e.what() << std::endl; + throw ExitException(1); +} + +inline void DocBookOutput::substituteSpecialChars( std::string& s, + char r, + std::string& x ) +{ + size_t p; + while ( (p = s.find_first_of(r)) != std::string::npos ) + { + s.erase(p,1); + s.insert(p,x); + } +} + +inline void DocBookOutput::removeChar( std::string& s, char r) +{ + size_t p; + while ( (p = s.find_first_of(r)) != std::string::npos ) + { + s.erase(p,1); + } +} + +inline void DocBookOutput::basename( std::string& s ) +{ + size_t p = s.find_last_of('/'); + if ( p != std::string::npos ) + { + s.erase(0, p + 1); + } +} + +inline void DocBookOutput::printShortArg(Arg* a) +{ + std::string lt = "<"; + std::string gt = ">"; + + std::string id = a->shortID(); + substituteSpecialChars(id,'<',lt); + substituteSpecialChars(id,'>',gt); + removeChar(id,'['); + removeChar(id,']'); + + std::string choice = "opt"; + if ( a->isRequired() ) + choice = "plain"; + + std::cout << "acceptsMultipleValues() ) + std::cout << " rep='repeat'"; + + + std::cout << '>'; + if ( !a->getFlag().empty() ) + std::cout << a->flagStartChar() << a->getFlag(); + else + std::cout << a->nameStartString() << a->getName(); + if ( a->isValueRequired() ) + { + std::string arg = a->shortID(); + removeChar(arg,'['); + removeChar(arg,']'); + removeChar(arg,'<'); + removeChar(arg,'>'); + arg.erase(0, arg.find_last_of(theDelimiter) + 1); + std::cout << theDelimiter; + std::cout << "" << arg << ""; + } + std::cout << "" << std::endl; + +} + +inline void DocBookOutput::printLongArg(Arg* a) +{ + std::string lt = "<"; + std::string gt = ">"; + + std::string desc = a->getDescription(); + substituteSpecialChars(desc,'<',lt); + substituteSpecialChars(desc,'>',gt); + + std::cout << "" << std::endl; + + if ( !a->getFlag().empty() ) + { + std::cout << "" << std::endl; + std::cout << "" << std::endl; + std::cout << "" << std::endl; + } + + std::cout << "" << std::endl; + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "" << std::endl; + std::cout << desc << std::endl; + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; +} + +} //namespace TCLAP +#endif diff --git a/deps/include/tclap/HelpVisitor.h b/deps/include/tclap/HelpVisitor.h new file mode 100644 index 0000000..cc3bd07 --- /dev/null +++ b/deps/include/tclap/HelpVisitor.h @@ -0,0 +1,76 @@ + +/****************************************************************************** + * + * file: HelpVisitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_HELP_VISITOR_H +#define TCLAP_HELP_VISITOR_H + +#include +#include +#include + +namespace TCLAP { + +/** + * A Visitor object that calls the usage method of the given CmdLineOutput + * object for the specified CmdLine object. + */ +class HelpVisitor: public Visitor +{ + private: + /** + * Prevent accidental copying. + */ + HelpVisitor(const HelpVisitor& rhs); + HelpVisitor& operator=(const HelpVisitor& rhs); + + protected: + + /** + * The CmdLine the output will be generated for. + */ + CmdLineInterface* _cmd; + + /** + * The output object. + */ + CmdLineOutput** _out; + + public: + + /** + * Constructor. + * \param cmd - The CmdLine the output will be generated for. + * \param out - The type of output. + */ + HelpVisitor(CmdLineInterface* cmd, CmdLineOutput** out) + : Visitor(), _cmd( cmd ), _out( out ) { } + + /** + * Calls the usage method of the CmdLineOutput for the + * specified CmdLine. + */ + void visit() { (*_out)->usage(*_cmd); throw ExitException(0); } + +}; + +} + +#endif diff --git a/deps/include/tclap/IgnoreRestVisitor.h b/deps/include/tclap/IgnoreRestVisitor.h new file mode 100644 index 0000000..e328649 --- /dev/null +++ b/deps/include/tclap/IgnoreRestVisitor.h @@ -0,0 +1,52 @@ + +/****************************************************************************** + * + * file: IgnoreRestVisitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_IGNORE_REST_VISITOR_H +#define TCLAP_IGNORE_REST_VISITOR_H + +#include +#include + +namespace TCLAP { + +/** + * A Vistor that tells the CmdLine to begin ignoring arguments after + * this one is parsed. + */ +class IgnoreRestVisitor: public Visitor +{ + public: + + /** + * Constructor. + */ + IgnoreRestVisitor() : Visitor() {} + + /** + * Sets Arg::_ignoreRest. + */ + void visit() { Arg::beginIgnoring(); } +}; + +} + +#endif diff --git a/deps/include/tclap/MultiArg.h b/deps/include/tclap/MultiArg.h new file mode 100644 index 0000000..34bb2d7 --- /dev/null +++ b/deps/include/tclap/MultiArg.h @@ -0,0 +1,433 @@ +/****************************************************************************** + * + * file: MultiArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_MULTIPLE_ARGUMENT_H +#define TCLAP_MULTIPLE_ARGUMENT_H + +#include +#include + +#include +#include + +namespace TCLAP { +/** + * An argument that allows multiple values of type T to be specified. Very + * similar to a ValueArg, except a vector of values will be returned + * instead of just one. + */ +template +class MultiArg : public Arg +{ +public: + typedef std::vector container_type; + typedef typename container_type::iterator iterator; + typedef typename container_type::const_iterator const_iterator; + +protected: + + /** + * The list of values parsed from the CmdLine. + */ + std::vector _values; + + /** + * The description of type T to be used in the usage. + */ + std::string _typeDesc; + + /** + * A list of constraint on this Arg. + */ + Constraint* _constraint; + + /** + * Extracts the value from the string. + * Attempts to parse string as type T, if this fails an exception + * is thrown. + * \param val - The string to be read. + */ + void _extractValue( const std::string& val ); + + /** + * Used by XorHandler to decide whether to keep parsing for this arg. + */ + bool _allowMore; + +public: + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + Visitor* v = NULL); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint* constraint, + Visitor* v = NULL ); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint* constraint, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed from main(). + */ + virtual bool processArg(int* i, std::vector& args); + + /** + * Returns a vector of type T containing the values parsed from + * the command line. + */ + const std::vector& getValue(); + + /** + * Returns an iterator over the values parsed from the command + * line. + */ + const_iterator begin() const { return _values.begin(); } + + /** + * Returns the end of the values parsed from the command + * line. + */ + const_iterator end() const { return _values.end(); } + + /** + * Returns the a short id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string& val="val") const; + + /** + * Returns the a long id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string longID(const std::string& val="val") const; + + /** + * Once we've matched the first value, then the arg is no longer + * required. + */ + virtual bool isRequired() const; + + virtual bool allowMore(); + + virtual void reset(); + +private: + /** + * Prevent accidental copying + */ + MultiArg(const MultiArg& rhs); + MultiArg& operator=(const MultiArg& rhs); + +}; + +template +MultiArg::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + Visitor* v) : + Arg( flag, name, desc, req, true, v ), + _values(std::vector()), + _typeDesc( typeDesc ), + _constraint( NULL ), + _allowMore(false) +{ + _acceptsMultipleValues = true; +} + +template +MultiArg::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _values(std::vector()), + _typeDesc( typeDesc ), + _constraint( NULL ), + _allowMore(false) +{ + parser.add( this ); + _acceptsMultipleValues = true; +} + +/** + * + */ +template +MultiArg::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint* constraint, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _values(std::vector()), + _typeDesc( constraint->shortID() ), + _constraint( constraint ), + _allowMore(false) +{ + _acceptsMultipleValues = true; +} + +template +MultiArg::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint* constraint, + CmdLineInterface& parser, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _values(std::vector()), + _typeDesc( constraint->shortID() ), + _constraint( constraint ), + _allowMore(false) +{ + parser.add( this ); + _acceptsMultipleValues = true; +} + +template +const std::vector& MultiArg::getValue() { return _values; } + +template +bool MultiArg::processArg(int *i, std::vector& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( _hasBlanks( args[*i] ) ) + return false; + + std::string flag = args[*i]; + std::string value = ""; + + trimFlag( flag, value ); + + if ( argMatches( flag ) ) + { + if ( Arg::delimiter() != ' ' && value == "" ) + throw( ArgParseException( + "Couldn't find delimiter for this argument!", + toString() ) ); + + // always take the first one, regardless of start string + if ( value == "" ) + { + (*i)++; + if ( static_cast(*i) < args.size() ) + _extractValue( args[*i] ); + else + throw( ArgParseException("Missing a value for this argument!", + toString() ) ); + } + else + _extractValue( value ); + + /* + // continuing taking the args until we hit one with a start string + while ( (unsigned int)(*i)+1 < args.size() && + args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && + args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) + _extractValue( args[++(*i)] ); + */ + + _alreadySet = true; + _checkWithVisitor(); + + return true; + } + else + return false; +} + +/** + * + */ +template +std::string MultiArg::shortID(const std::string& val) const +{ + static_cast(val); // Ignore input, don't warn + return Arg::shortID(_typeDesc) + " ... "; +} + +/** + * + */ +template +std::string MultiArg::longID(const std::string& val) const +{ + static_cast(val); // Ignore input, don't warn + return Arg::longID(_typeDesc) + " (accepted multiple times)"; +} + +/** + * Once we've matched the first value, then the arg is no longer + * required. + */ +template +bool MultiArg::isRequired() const +{ + if ( _required ) + { + if ( _values.size() > 1 ) + return false; + else + return true; + } + else + return false; + +} + +template +void MultiArg::_extractValue( const std::string& val ) +{ + try { + T tmp; + ExtractValue(tmp, val, typename ArgTraits::ValueCategory()); + _values.push_back(tmp); + } catch( ArgParseException &e) { + throw ArgParseException(e.error(), toString()); + } + + if ( _constraint != NULL ) + if ( ! _constraint->check( _values.back() ) ) + throw( CmdLineParseException( "Value '" + val + + "' does not meet constraint: " + + _constraint->description(), + toString() ) ); +} + +template +bool MultiArg::allowMore() +{ + bool am = _allowMore; + _allowMore = true; + return am; +} + +template +void MultiArg::reset() +{ + Arg::reset(); + _values.clear(); +} + +} // namespace TCLAP + +#endif diff --git a/deps/include/tclap/MultiSwitchArg.h b/deps/include/tclap/MultiSwitchArg.h new file mode 100644 index 0000000..8820b64 --- /dev/null +++ b/deps/include/tclap/MultiSwitchArg.h @@ -0,0 +1,216 @@ + +/****************************************************************************** +* +* file: MultiSwitchArg.h +* +* Copyright (c) 2003, Michael E. Smoot . +* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. +* Copyright (c) 2005, Michael E. Smoot, Daniel Aarno, Erik Zeek. +* All rights reverved. +* +* See the file COPYING in the top directory of this distribution for +* more information. +* +* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +* +*****************************************************************************/ + + +#ifndef TCLAP_MULTI_SWITCH_ARG_H +#define TCLAP_MULTI_SWITCH_ARG_H + +#include +#include + +#include + +namespace TCLAP { + +/** +* A multiple switch argument. If the switch is set on the command line, then +* the getValue method will return the number of times the switch appears. +*/ +class MultiSwitchArg : public SwitchArg +{ + protected: + + /** + * The value of the switch. + */ + int _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + int _default; + + public: + + /** + * MultiSwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param init - Optional. The initial/default value of this Arg. + * Defaults to 0. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + int init = 0, + Visitor* v = NULL); + + + /** + * MultiSwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param parser - A CmdLine parser object to add this Arg to + * \param init - Optional. The initial/default value of this Arg. + * Defaults to 0. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + int init = 0, + Visitor* v = NULL); + + + /** + * Handles the processing of the argument. + * This re-implements the SwitchArg version of this method to set the + * _value of the argument appropriately. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int* i, std::vector& args); + + /** + * Returns int, the number of times the switch has been set. + */ + int getValue(); + + /** + * Returns the shortID for this Arg. + */ + std::string shortID(const std::string& val) const; + + /** + * Returns the longID for this Arg. + */ + std::string longID(const std::string& val) const; + + void reset(); + +}; + +////////////////////////////////////////////////////////////////////// +//BEGIN MultiSwitchArg.cpp +////////////////////////////////////////////////////////////////////// +inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + int init, + Visitor* v ) +: SwitchArg(flag, name, desc, false, v), +_value( init ), +_default( init ) +{ } + +inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + int init, + Visitor* v ) +: SwitchArg(flag, name, desc, false, v), +_value( init ), +_default( init ) +{ + parser.add( this ); +} + +inline int MultiSwitchArg::getValue() { return _value; } + +inline bool MultiSwitchArg::processArg(int *i, std::vector& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( argMatches( args[*i] )) + { + // so the isSet() method will work + _alreadySet = true; + + // Matched argument: increment value. + ++_value; + + _checkWithVisitor(); + + return true; + } + else if ( combinedSwitchesMatch( args[*i] ) ) + { + // so the isSet() method will work + _alreadySet = true; + + // Matched argument: increment value. + ++_value; + + // Check for more in argument and increment value. + while ( combinedSwitchesMatch( args[*i] ) ) + ++_value; + + _checkWithVisitor(); + + return false; + } + else + return false; +} + +inline std::string +MultiSwitchArg::shortID(const std::string& val) const +{ + return Arg::shortID(val) + " ... "; +} + +inline std::string +MultiSwitchArg::longID(const std::string& val) const +{ + return Arg::longID(val) + " (accepted multiple times)"; +} + +inline void +MultiSwitchArg::reset() +{ + MultiSwitchArg::_value = MultiSwitchArg::_default; +} + +////////////////////////////////////////////////////////////////////// +//END MultiSwitchArg.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif diff --git a/deps/include/tclap/OptionalUnlabeledTracker.h b/deps/include/tclap/OptionalUnlabeledTracker.h new file mode 100644 index 0000000..8174c5f --- /dev/null +++ b/deps/include/tclap/OptionalUnlabeledTracker.h @@ -0,0 +1,62 @@ + + +/****************************************************************************** + * + * file: OptionalUnlabeledTracker.h + * + * Copyright (c) 2005, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_OPTIONAL_UNLABELED_TRACKER_H +#define TCLAP_OPTIONAL_UNLABELED_TRACKER_H + +#include + +namespace TCLAP { + +class OptionalUnlabeledTracker +{ + + public: + + static void check( bool req, const std::string& argName ); + + static void gotOptional() { alreadyOptionalRef() = true; } + + static bool& alreadyOptional() { return alreadyOptionalRef(); } + + private: + + static bool& alreadyOptionalRef() { static bool ct = false; return ct; } +}; + + +inline void OptionalUnlabeledTracker::check( bool req, const std::string& argName ) +{ + if ( OptionalUnlabeledTracker::alreadyOptional() ) + throw( SpecificationException( + "You can't specify ANY Unlabeled Arg following an optional Unlabeled Arg", + argName ) ); + + if ( !req ) + OptionalUnlabeledTracker::gotOptional(); +} + + +} // namespace TCLAP + +#endif diff --git a/deps/include/tclap/StandardTraits.h b/deps/include/tclap/StandardTraits.h new file mode 100644 index 0000000..46d7f6f --- /dev/null +++ b/deps/include/tclap/StandardTraits.h @@ -0,0 +1,208 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: StandardTraits.h + * + * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +// This is an internal tclap file, you should probably not have to +// include this directly + +#ifndef TCLAP_STANDARD_TRAITS_H +#define TCLAP_STANDARD_TRAITS_H + +#ifdef HAVE_CONFIG_H +#include // To check for long long +#endif + +// If Microsoft has already typedef'd wchar_t as an unsigned +// short, then compiles will break because it's as if we're +// creating ArgTraits twice for unsigned short. Thus... +#ifdef _MSC_VER +#ifndef _NATIVE_WCHAR_T_DEFINED +#define TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS +#endif +#endif + +namespace TCLAP { + +// ====================================================================== +// Integer types +// ====================================================================== + +/** + * longs have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +/** + * ints have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +/** + * shorts have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +/** + * chars have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +#ifdef HAVE_LONG_LONG +/** + * long longs have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; +#endif + +// ====================================================================== +// Unsigned integer types +// ====================================================================== + +/** + * unsigned longs have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +/** + * unsigned ints have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +/** + * unsigned shorts have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +/** + * unsigned chars have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +// Microsoft implements size_t awkwardly. +#if defined(_MSC_VER) && defined(_M_X64) +/** + * size_ts have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; +#endif + + +#ifdef HAVE_LONG_LONG +/** + * unsigned long longs have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; +#endif + +// ====================================================================== +// Float types +// ====================================================================== + +/** + * floats have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +/** + * doubles have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +// ====================================================================== +// Other types +// ====================================================================== + +/** + * bools have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + + +/** + * wchar_ts have value-like semantics. + */ +#ifndef TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; +#endif + +/** + * Strings have string like argument traits. + */ +template<> +struct ArgTraits { + typedef StringLike ValueCategory; +}; + +template +void SetString(T &dst, const std::string &src) +{ + dst = src; +} + +} // namespace + +#endif + diff --git a/deps/include/tclap/StdOutput.h b/deps/include/tclap/StdOutput.h new file mode 100644 index 0000000..35f7b99 --- /dev/null +++ b/deps/include/tclap/StdOutput.h @@ -0,0 +1,298 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: StdOutput.h + * + * Copyright (c) 2004, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_STDCMDLINEOUTPUT_H +#define TCLAP_STDCMDLINEOUTPUT_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace TCLAP { + +/** + * A class that isolates any output from the CmdLine object so that it + * may be easily modified. + */ +class StdOutput : public CmdLineOutput +{ + + public: + + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface& c, + ArgException& e ); + + protected: + + /** + * Writes a brief usage message with short args. + * \param c - The CmdLine object the output is generated for. + * \param os - The stream to write the message to. + */ + void _shortUsage( CmdLineInterface& c, std::ostream& os ) const; + + /** + * Writes a longer usage message with long and short args, + * provides descriptions and prints message. + * \param c - The CmdLine object the output is generated for. + * \param os - The stream to write the message to. + */ + void _longUsage( CmdLineInterface& c, std::ostream& os ) const; + + /** + * This function inserts line breaks and indents long strings + * according the params input. It will only break lines at spaces, + * commas and pipes. + * \param os - The stream to be printed to. + * \param s - The string to be printed. + * \param maxWidth - The maxWidth allowed for the output line. + * \param indentSpaces - The number of spaces to indent the first line. + * \param secondLineOffset - The number of spaces to indent the second + * and all subsequent lines in addition to indentSpaces. + */ + void spacePrint( std::ostream& os, + const std::string& s, + int maxWidth, + int indentSpaces, + int secondLineOffset ) const; + +}; + + +inline void StdOutput::version(CmdLineInterface& _cmd) +{ + std::string progName = _cmd.getProgramName(); + std::string xversion = _cmd.getVersion(); + + std::cout << std::endl << progName << " version: " + << xversion << std::endl << std::endl; +} + +inline void StdOutput::usage(CmdLineInterface& _cmd ) +{ + std::cout << std::endl << "USAGE: " << std::endl << std::endl; + + _shortUsage( _cmd, std::cout ); + + std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl; + + _longUsage( _cmd, std::cout ); + + std::cout << std::endl; + +} + +inline void StdOutput::failure( CmdLineInterface& _cmd, + ArgException& e ) +{ + std::string progName = _cmd.getProgramName(); + + std::cerr << "PARSE ERROR: " << e.argId() << std::endl + << " " << e.error() << std::endl << std::endl; + + if ( _cmd.hasHelpAndVersion() ) + { + std::cerr << "Brief USAGE: " << std::endl; + + _shortUsage( _cmd, std::cerr ); + + std::cerr << std::endl << "For complete USAGE and HELP type: " + << std::endl << " " << progName << " --help" + << std::endl << std::endl; + } + else + usage(_cmd); + + throw ExitException(1); +} + +inline void +StdOutput::_shortUsage( CmdLineInterface& _cmd, + std::ostream& os ) const +{ + std::list argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector > xorList = xorHandler.getXorList(); + + std::string s = progName + " "; + + // first the xor + for ( int i = 0; static_cast(i) < xorList.size(); i++ ) + { + s += " {"; + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); it++ ) + s += (*it)->shortID() + "|"; + + s[s.length()-1] = '}'; + } + + // then the rest + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if ( !xorHandler.contains( (*it) ) ) + s += " " + (*it)->shortID(); + + // if the program name is too long, then adjust the second line offset + int secondLineOffset = static_cast(progName.length()) + 2; + if ( secondLineOffset > 75/2 ) + secondLineOffset = static_cast(75/2); + + spacePrint( os, s, 75, 3, secondLineOffset ); +} + +inline void +StdOutput::_longUsage( CmdLineInterface& _cmd, + std::ostream& os ) const +{ + std::list argList = _cmd.getArgList(); + std::string message = _cmd.getMessage(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector > xorList = xorHandler.getXorList(); + + // first the xor + for ( int i = 0; static_cast(i) < xorList.size(); i++ ) + { + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); + it++ ) + { + spacePrint( os, (*it)->longID(), 75, 3, 3 ); + spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); + + if ( it+1 != xorList[i].end() ) + spacePrint(os, "-- OR --", 75, 9, 0); + } + os << std::endl << std::endl; + } + + // then the rest + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if ( !xorHandler.contains( (*it) ) ) + { + spacePrint( os, (*it)->longID(), 75, 3, 3 ); + spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); + os << std::endl; + } + + os << std::endl; + + spacePrint( os, message, 75, 3, 0 ); +} + +inline void StdOutput::spacePrint( std::ostream& os, + const std::string& s, + int maxWidth, + int indentSpaces, + int secondLineOffset ) const +{ + int len = static_cast(s.length()); + + if ( (len + indentSpaces > maxWidth) && maxWidth > 0 ) + { + int allowedLen = maxWidth - indentSpaces; + int start = 0; + while ( start < len ) + { + // find the substring length + // int stringLen = std::min( len - start, allowedLen ); + // doing it this way to support a VisualC++ 2005 bug + using namespace std; + int stringLen = min( len - start, allowedLen ); + + // trim the length so it doesn't end in middle of a word + if ( stringLen == allowedLen ) + while ( stringLen >= 0 && + s[stringLen+start] != ' ' && + s[stringLen+start] != ',' && + s[stringLen+start] != '|' ) + stringLen--; + + // ok, the word is longer than the line, so just split + // wherever the line ends + if ( stringLen <= 0 ) + stringLen = allowedLen; + + // check for newlines + for ( int i = 0; i < stringLen; i++ ) + if ( s[start+i] == '\n' ) + stringLen = i+1; + + // print the indent + for ( int i = 0; i < indentSpaces; i++ ) + os << " "; + + if ( start == 0 ) + { + // handle second line offsets + indentSpaces += secondLineOffset; + + // adjust allowed len + allowedLen -= secondLineOffset; + } + + os << s.substr(start,stringLen) << std::endl; + + // so we don't start a line with a space + while ( s[stringLen+start] == ' ' && start < len ) + start++; + + start += stringLen; + } + } + else + { + for ( int i = 0; i < indentSpaces; i++ ) + os << " "; + os << s << std::endl; + } +} + +} //namespace TCLAP +#endif diff --git a/deps/include/tclap/SwitchArg.h b/deps/include/tclap/SwitchArg.h new file mode 100644 index 0000000..3916109 --- /dev/null +++ b/deps/include/tclap/SwitchArg.h @@ -0,0 +1,266 @@ + +/****************************************************************************** + * + * file: SwitchArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_SWITCH_ARG_H +#define TCLAP_SWITCH_ARG_H + +#include +#include + +#include + +namespace TCLAP { + +/** + * A simple switch argument. If the switch is set on the command line, then + * the getValue method will return the opposite of the default value for the + * switch. + */ +class SwitchArg : public Arg +{ + protected: + + /** + * The value of the switch. + */ + bool _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + bool _default; + + public: + + /** + * SwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param def - The default value for this Switch. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool def = false, + Visitor* v = NULL); + + + /** + * SwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param parser - A CmdLine parser object to add this Arg to + * \param def - The default value for this Switch. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + bool def = false, + Visitor* v = NULL); + + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int* i, std::vector& args); + + /** + * Checks a string to see if any of the chars in the string + * match the flag for this Switch. + */ + bool combinedSwitchesMatch(std::string& combined); + + /** + * Returns bool, whether or not the switch has been set. + */ + bool getValue(); + + virtual void reset(); + + private: + /** + * Checks to see if we've found the last match in + * a combined string. + */ + bool lastCombined(std::string& combined); + + /** + * Does the common processing of processArg. + */ + void commonProcessing(); +}; + +////////////////////////////////////////////////////////////////////// +//BEGIN SwitchArg.cpp +////////////////////////////////////////////////////////////////////// +inline SwitchArg::SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool default_val, + Visitor* v ) +: Arg(flag, name, desc, false, false, v), + _value( default_val ), + _default( default_val ) +{ } + +inline SwitchArg::SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + bool default_val, + Visitor* v ) +: Arg(flag, name, desc, false, false, v), + _value( default_val ), + _default(default_val) +{ + parser.add( this ); +} + +inline bool SwitchArg::getValue() { return _value; } + +inline bool SwitchArg::lastCombined(std::string& combinedSwitches ) +{ + for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) + if ( combinedSwitches[i] != Arg::blankChar() ) + return false; + + return true; +} + +inline bool SwitchArg::combinedSwitchesMatch(std::string& combinedSwitches ) +{ + // make sure this is actually a combined switch + if ( combinedSwitches.length() > 0 && + combinedSwitches[0] != Arg::flagStartString()[0] ) + return false; + + // make sure it isn't a long name + if ( combinedSwitches.substr( 0, Arg::nameStartString().length() ) == + Arg::nameStartString() ) + return false; + + // make sure the delimiter isn't in the string + if ( combinedSwitches.find_first_of( Arg::delimiter() ) != std::string::npos ) + return false; + + // ok, we're not specifying a ValueArg, so we know that we have + // a combined switch list. + for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) + if ( _flag.length() > 0 && + combinedSwitches[i] == _flag[0] && + _flag[0] != Arg::flagStartString()[0] ) + { + // update the combined switches so this one is no longer present + // this is necessary so that no unlabeled args are matched + // later in the processing. + //combinedSwitches.erase(i,1); + combinedSwitches[i] = Arg::blankChar(); + return true; + } + + // none of the switches passed in the list match. + return false; +} + +inline void SwitchArg::commonProcessing() +{ + if ( _xorSet ) + throw(CmdLineParseException( + "Mutually exclusive argument already set!", toString())); + + if ( _alreadySet ) + throw(CmdLineParseException("Argument already set!", toString())); + + _alreadySet = true; + + if ( _value == true ) + _value = false; + else + _value = true; + + _checkWithVisitor(); +} + +inline bool SwitchArg::processArg(int *i, std::vector& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + // if the whole string matches the flag or name string + if ( argMatches( args[*i] ) ) + { + commonProcessing(); + + return true; + } + // if a substring matches the flag as part of a combination + else if ( combinedSwitchesMatch( args[*i] ) ) + { + // check again to ensure we don't misinterpret + // this as a MultiSwitchArg + if ( combinedSwitchesMatch( args[*i] ) ) + throw(CmdLineParseException("Argument already set!", + toString())); + + commonProcessing(); + + // We only want to return true if we've found the last combined + // match in the string, otherwise we return true so that other + // switches in the combination will have a chance to match. + return lastCombined( args[*i] ); + } + else + return false; +} + +inline void SwitchArg::reset() +{ + Arg::reset(); + _value = _default; +} +////////////////////////////////////////////////////////////////////// +//End SwitchArg.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif diff --git a/deps/include/tclap/UnlabeledMultiArg.h b/deps/include/tclap/UnlabeledMultiArg.h new file mode 100644 index 0000000..d5e1781 --- /dev/null +++ b/deps/include/tclap/UnlabeledMultiArg.h @@ -0,0 +1,301 @@ + +/****************************************************************************** + * + * file: UnlabeledMultiArg.h + * + * Copyright (c) 2003, Michael E. Smoot. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H +#define TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H + +#include +#include + +#include +#include + +namespace TCLAP { + +/** + * Just like a MultiArg, except that the arguments are unlabeled. Basically, + * this Arg will slurp up everything that hasn't been matched to another + * Arg. + */ +template +class UnlabeledMultiArg : public MultiArg +{ + + // If compiler has two stage name lookup (as gcc >= 3.4 does) + // this is requried to prevent undef. symbols + using MultiArg::_ignoreable; + using MultiArg::_hasBlanks; + using MultiArg::_extractValue; + using MultiArg::_typeDesc; + using MultiArg::_name; + using MultiArg::_description; + using MultiArg::_alreadySet; + using MultiArg::toString; + + public: + + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + bool ignoreable = false, + Visitor* v = NULL ); + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + Constraint* constraint, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + Constraint* constraint, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed from main(). + */ + virtual bool processArg(int* i, std::vector& args); + + /** + * Returns the a short id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string& val="val") const; + + /** + * Returns the a long id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string longID(const std::string& val="val") const; + + /** + * Opertor ==. + * \param a - The Arg to be compared to this. + */ + virtual bool operator==(const Arg& a) const; + + /** + * Pushes this to back of list rather than front. + * \param argList - The list this should be added to. + */ + virtual void addToList( std::list& argList ) const; +}; + +template +UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + bool ignoreable, + Visitor* v) +: MultiArg("", name, desc, req, typeDesc, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); +} + +template +UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: MultiArg("", name, desc, req, typeDesc, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); + parser.add( this ); +} + + +template +UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + Constraint* constraint, + bool ignoreable, + Visitor* v) +: MultiArg("", name, desc, req, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); +} + +template +UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + Constraint* constraint, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: MultiArg("", name, desc, req, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); + parser.add( this ); +} + + +template +bool UnlabeledMultiArg::processArg(int *i, std::vector& args) +{ + + if ( _hasBlanks( args[*i] ) ) + return false; + + // never ignore an unlabeled multi arg + + + // always take the first value, regardless of the start string + _extractValue( args[(*i)] ); + + /* + // continue taking args until we hit the end or a start string + while ( (unsigned int)(*i)+1 < args.size() && + args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && + args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) + _extractValue( args[++(*i)] ); + */ + + _alreadySet = true; + + return true; +} + +template +std::string UnlabeledMultiArg::shortID(const std::string& val) const +{ + static_cast(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + "> ..."; +} + +template +std::string UnlabeledMultiArg::longID(const std::string& val) const +{ + static_cast(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + "> (accepted multiple times)"; +} + +template +bool UnlabeledMultiArg::operator==(const Arg& a) const +{ + if ( _name == a.getName() || _description == a.getDescription() ) + return true; + else + return false; +} + +template +void UnlabeledMultiArg::addToList( std::list& argList ) const +{ + argList.push_back( const_cast(static_cast(this)) ); +} + +} + +#endif diff --git a/deps/include/tclap/UnlabeledValueArg.h b/deps/include/tclap/UnlabeledValueArg.h new file mode 100644 index 0000000..5721d61 --- /dev/null +++ b/deps/include/tclap/UnlabeledValueArg.h @@ -0,0 +1,340 @@ + +/****************************************************************************** + * + * file: UnlabeledValueArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_UNLABELED_VALUE_ARGUMENT_H +#define TCLAP_UNLABELED_VALUE_ARGUMENT_H + +#include +#include + +#include +#include + + +namespace TCLAP { + +/** + * The basic unlabeled argument that parses a value. + * This is a template class, which means the type T defines the type + * that a given object will attempt to parse when an UnlabeledValueArg + * is reached in the list of args that the CmdLine iterates over. + */ +template +class UnlabeledValueArg : public ValueArg +{ + + // If compiler has two stage name lookup (as gcc >= 3.4 does) + // this is requried to prevent undef. symbols + using ValueArg::_ignoreable; + using ValueArg::_hasBlanks; + using ValueArg::_extractValue; + using ValueArg::_typeDesc; + using ValueArg::_name; + using ValueArg::_description; + using ValueArg::_alreadySet; + using ValueArg::toString; + + public: + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + bool ignoreable = false, + Visitor* v = NULL); + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint* constraint, + bool ignoreable = false, + Visitor* v = NULL ); + + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint* constraint, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. Handling specific to + * unlabled arguments. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. + */ + virtual bool processArg(int* i, std::vector& args); + + /** + * Overrides shortID for specific behavior. + */ + virtual std::string shortID(const std::string& val="val") const; + + /** + * Overrides longID for specific behavior. + */ + virtual std::string longID(const std::string& val="val") const; + + /** + * Overrides operator== for specific behavior. + */ + virtual bool operator==(const Arg& a ) const; + + /** + * Instead of pushing to the front of list, push to the back. + * \param argList - The list to add this to. + */ + virtual void addToList( std::list& argList ) const; + +}; + +/** + * Constructor implemenation. + */ +template +UnlabeledValueArg::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + bool ignoreable, + Visitor* v) +: ValueArg("", name, desc, req, val, typeDesc, v) +{ + _ignoreable = ignoreable; + + OptionalUnlabeledTracker::check(req, toString()); + +} + +template +UnlabeledValueArg::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: ValueArg("", name, desc, req, val, typeDesc, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); + parser.add( this ); +} + +/** + * Constructor implemenation. + */ +template +UnlabeledValueArg::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint* constraint, + bool ignoreable, + Visitor* v) +: ValueArg("", name, desc, req, val, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); +} + +template +UnlabeledValueArg::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint* constraint, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: ValueArg("", name, desc, req, val, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); + parser.add( this ); +} + +/** + * Implementation of processArg(). + */ +template +bool UnlabeledValueArg::processArg(int *i, std::vector& args) +{ + + if ( _alreadySet ) + return false; + + if ( _hasBlanks( args[*i] ) ) + return false; + + // never ignore an unlabeled arg + + _extractValue( args[*i] ); + _alreadySet = true; + return true; +} + +/** + * Overriding shortID for specific output. + */ +template +std::string UnlabeledValueArg::shortID(const std::string& val) const +{ + static_cast(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + ">"; +} + +/** + * Overriding longID for specific output. + */ +template +std::string UnlabeledValueArg::longID(const std::string& val) const +{ + static_cast(val); // Ignore input, don't warn + + // Ideally we would like to be able to use RTTI to return the name + // of the type required for this argument. However, g++ at least, + // doesn't appear to return terribly useful "names" of the types. + return std::string("<") + _typeDesc + ">"; +} + +/** + * Overriding operator== for specific behavior. + */ +template +bool UnlabeledValueArg::operator==(const Arg& a ) const +{ + if ( _name == a.getName() || _description == a.getDescription() ) + return true; + else + return false; +} + +template +void UnlabeledValueArg::addToList( std::list& argList ) const +{ + argList.push_back( const_cast(static_cast(this)) ); +} + +} +#endif diff --git a/deps/include/tclap/ValueArg.h b/deps/include/tclap/ValueArg.h new file mode 100644 index 0000000..7ac2952 --- /dev/null +++ b/deps/include/tclap/ValueArg.h @@ -0,0 +1,425 @@ +/****************************************************************************** + * + * file: ValueArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_VALUE_ARGUMENT_H +#define TCLAP_VALUE_ARGUMENT_H + +#include +#include + +#include +#include + +namespace TCLAP { + +/** + * The basic labeled argument that parses a value. + * This is a template class, which means the type T defines the type + * that a given object will attempt to parse when the flag/name is matched + * on the command line. While there is nothing stopping you from creating + * an unflagged ValueArg, it is unwise and would cause significant problems. + * Instead use an UnlabeledValueArg. + */ +template +class ValueArg : public Arg +{ + protected: + + /** + * The value parsed from the command line. + * Can be of any type, as long as the >> operator for the type + * is defined. + */ + T _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + T _default; + + /** + * A human readable description of the type to be parsed. + * This is a hack, plain and simple. Ideally we would use RTTI to + * return the name of type T, but until there is some sort of + * consistent support for human readable names, we are left to our + * own devices. + */ + std::string _typeDesc; + + /** + * A Constraint this Arg must conform to. + */ + Constraint* _constraint; + + /** + * Extracts the value from the string. + * Attempts to parse string as type T, if this fails an exception + * is thrown. + * \param val - value to be parsed. + */ + void _extractValue( const std::string& val ); + + public: + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + Visitor* v = NULL); + + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint* constraint, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint* constraint, + Visitor* v = NULL ); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int* i, std::vector& args); + + /** + * Returns the value of the argument. + */ + T& getValue() ; + + /** + * Specialization of shortID. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string& val = "val") const; + + /** + * Specialization of longID. + * \param val - value to be used. + */ + virtual std::string longID(const std::string& val = "val") const; + + virtual void reset() ; + +private: + /** + * Prevent accidental copying + */ + ValueArg(const ValueArg& rhs); + ValueArg& operator=(const ValueArg& rhs); +}; + + +/** + * Constructor implementation. + */ +template +ValueArg::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( typeDesc ), + _constraint( NULL ) +{ } + +template +ValueArg::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( typeDesc ), + _constraint( NULL ) +{ + parser.add( this ); +} + +template +ValueArg::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint* constraint, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( constraint->shortID() ), + _constraint( constraint ) +{ } + +template +ValueArg::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint* constraint, + CmdLineInterface& parser, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( constraint->shortID() ), + _constraint( constraint ) +{ + parser.add( this ); +} + + +/** + * Implementation of getValue(). + */ +template +T& ValueArg::getValue() { return _value; } + +/** + * Implementation of processArg(). + */ +template +bool ValueArg::processArg(int *i, std::vector& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( _hasBlanks( args[*i] ) ) + return false; + + std::string flag = args[*i]; + + std::string value = ""; + trimFlag( flag, value ); + + if ( argMatches( flag ) ) + { + if ( _alreadySet ) + { + if ( _xorSet ) + throw( CmdLineParseException( + "Mutually exclusive argument already set!", + toString()) ); + else + throw( CmdLineParseException("Argument already set!", + toString()) ); + } + + if ( Arg::delimiter() != ' ' && value == "" ) + throw( ArgParseException( + "Couldn't find delimiter for this argument!", + toString() ) ); + + if ( value == "" ) + { + (*i)++; + if ( static_cast(*i) < args.size() ) + _extractValue( args[*i] ); + else + throw( ArgParseException("Missing a value for this argument!", + toString() ) ); + } + else + _extractValue( value ); + + _alreadySet = true; + _checkWithVisitor(); + return true; + } + else + return false; +} + +/** + * Implementation of shortID. + */ +template +std::string ValueArg::shortID(const std::string& val) const +{ + static_cast(val); // Ignore input, don't warn + return Arg::shortID( _typeDesc ); +} + +/** + * Implementation of longID. + */ +template +std::string ValueArg::longID(const std::string& val) const +{ + static_cast(val); // Ignore input, don't warn + return Arg::longID( _typeDesc ); +} + +template +void ValueArg::_extractValue( const std::string& val ) +{ + try { + ExtractValue(_value, val, typename ArgTraits::ValueCategory()); + } catch( ArgParseException &e) { + throw ArgParseException(e.error(), toString()); + } + + if ( _constraint != NULL ) + if ( ! _constraint->check( _value ) ) + throw( CmdLineParseException( "Value '" + val + + + "' does not meet constraint: " + + _constraint->description(), + toString() ) ); +} + +template +void ValueArg::reset() +{ + Arg::reset(); + _value = _default; +} + +} // namespace TCLAP + +#endif diff --git a/deps/include/tclap/ValuesConstraint.h b/deps/include/tclap/ValuesConstraint.h new file mode 100644 index 0000000..cb41f64 --- /dev/null +++ b/deps/include/tclap/ValuesConstraint.h @@ -0,0 +1,148 @@ + + +/****************************************************************************** + * + * file: ValuesConstraint.h + * + * Copyright (c) 2005, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_VALUESCONSTRAINT_H +#define TCLAP_VALUESCONSTRAINT_H + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#else +#define HAVE_SSTREAM +#endif + +#if defined(HAVE_SSTREAM) +#include +#elif defined(HAVE_STRSTREAM) +#include +#else +#error "Need a stringstream (sstream or strstream) to compile!" +#endif + +namespace TCLAP { + +/** + * A Constraint that constrains the Arg to only those values specified + * in the constraint. + */ +template +class ValuesConstraint : public Constraint +{ + + public: + + /** + * Constructor. + * \param allowed - vector of allowed values. + */ + ValuesConstraint(std::vector& allowed); + + /** + * Virtual destructor. + */ + virtual ~ValuesConstraint() {} + + /** + * Returns a description of the Constraint. + */ + virtual std::string description() const; + + /** + * Returns the short ID for the Constraint. + */ + virtual std::string shortID() const; + + /** + * The method used to verify that the value parsed from the command + * line meets the constraint. + * \param value - The value that will be checked. + */ + virtual bool check(const T& value) const; + + protected: + + /** + * The list of valid values. + */ + std::vector _allowed; + + /** + * The string used to describe the allowed values of this constraint. + */ + std::string _typeDesc; + +}; + +template +ValuesConstraint::ValuesConstraint(std::vector& allowed) +: _allowed(allowed), + _typeDesc("") +{ + for ( unsigned int i = 0; i < _allowed.size(); i++ ) + { + +#if defined(HAVE_SSTREAM) + std::ostringstream os; +#elif defined(HAVE_STRSTREAM) + std::ostrstream os; +#else +#error "Need a stringstream (sstream or strstream) to compile!" +#endif + + os << _allowed[i]; + + std::string temp( os.str() ); + + if ( i > 0 ) + _typeDesc += "|"; + _typeDesc += temp; + } +} + +template +bool ValuesConstraint::check( const T& val ) const +{ + if ( std::find(_allowed.begin(),_allowed.end(),val) == _allowed.end() ) + return false; + else + return true; +} + +template +std::string ValuesConstraint::shortID() const +{ + return _typeDesc; +} + +template +std::string ValuesConstraint::description() const +{ + return _typeDesc; +} + + +} //namespace TCLAP +#endif + diff --git a/deps/include/tclap/VersionVisitor.h b/deps/include/tclap/VersionVisitor.h new file mode 100644 index 0000000..c110d4f --- /dev/null +++ b/deps/include/tclap/VersionVisitor.h @@ -0,0 +1,81 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: VersionVisitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_VERSION_VISITOR_H +#define TCLAP_VERSION_VISITOR_H + +#include +#include +#include + +namespace TCLAP { + +/** + * A Vistor that will call the version method of the given CmdLineOutput + * for the specified CmdLine object and then exit. + */ +class VersionVisitor: public Visitor +{ + private: + /** + * Prevent accidental copying + */ + VersionVisitor(const VersionVisitor& rhs); + VersionVisitor& operator=(const VersionVisitor& rhs); + + protected: + + /** + * The CmdLine of interest. + */ + CmdLineInterface* _cmd; + + /** + * The output object. + */ + CmdLineOutput** _out; + + public: + + /** + * Constructor. + * \param cmd - The CmdLine the output is generated for. + * \param out - The type of output. + */ + VersionVisitor( CmdLineInterface* cmd, CmdLineOutput** out ) + : Visitor(), _cmd( cmd ), _out( out ) { } + + /** + * Calls the version method of the output object using the + * specified CmdLine. + */ + void visit() { + (*_out)->version(*_cmd); + throw ExitException(0); + } + +}; + +} + +#endif diff --git a/deps/include/tclap/Visitor.h b/deps/include/tclap/Visitor.h new file mode 100644 index 0000000..38ddcbd --- /dev/null +++ b/deps/include/tclap/Visitor.h @@ -0,0 +1,53 @@ + +/****************************************************************************** + * + * file: Visitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_VISITOR_H +#define TCLAP_VISITOR_H + +namespace TCLAP { + +/** + * A base class that defines the interface for visitors. + */ +class Visitor +{ + public: + + /** + * Constructor. Does nothing. + */ + Visitor() { } + + /** + * Destructor. Does nothing. + */ + virtual ~Visitor() { } + + /** + * Does nothing. Should be overridden by child. + */ + virtual void visit() { } +}; + +} + +#endif diff --git a/deps/include/tclap/XorHandler.h b/deps/include/tclap/XorHandler.h new file mode 100644 index 0000000..d9dfad3 --- /dev/null +++ b/deps/include/tclap/XorHandler.h @@ -0,0 +1,166 @@ + +/****************************************************************************** + * + * file: XorHandler.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_XORHANDLER_H +#define TCLAP_XORHANDLER_H + +#include +#include +#include +#include +#include + +namespace TCLAP { + +/** + * This class handles lists of Arg's that are to be XOR'd on the command + * line. This is used by CmdLine and you shouldn't ever use it. + */ +class XorHandler +{ + protected: + + /** + * The list of of lists of Arg's to be or'd together. + */ + std::vector< std::vector > _orList; + + public: + + /** + * Constructor. Does nothing. + */ + XorHandler( ) : _orList(std::vector< std::vector >()) {} + + /** + * Add a list of Arg*'s that will be orred together. + * \param ors - list of Arg* that will be xor'd. + */ + void add( std::vector& ors ); + + /** + * Checks whether the specified Arg is in one of the xor lists and + * if it does match one, returns the size of the xor list that the + * Arg matched. If the Arg matches, then it also sets the rest of + * the Arg's in the list. You shouldn't use this. + * \param a - The Arg to be checked. + */ + int check( const Arg* a ); + + /** + * Returns the XOR specific short usage. + */ + std::string shortUsage(); + + /** + * Prints the XOR specific long usage. + * \param os - Stream to print to. + */ + void printLongUsage(std::ostream& os); + + /** + * Simply checks whether the Arg is contained in one of the arg + * lists. + * \param a - The Arg to be checked. + */ + bool contains( const Arg* a ); + + std::vector< std::vector >& getXorList(); + +}; + + +////////////////////////////////////////////////////////////////////// +//BEGIN XOR.cpp +////////////////////////////////////////////////////////////////////// +inline void XorHandler::add( std::vector& ors ) +{ + _orList.push_back( ors ); +} + +inline int XorHandler::check( const Arg* a ) +{ + // iterate over each XOR list + for ( int i = 0; static_cast(i) < _orList.size(); i++ ) + { + // if the XOR list contains the arg.. + ArgVectorIterator ait = std::find( _orList[i].begin(), + _orList[i].end(), a ); + if ( ait != _orList[i].end() ) + { + // first check to see if a mutually exclusive switch + // has not already been set + for ( ArgVectorIterator it = _orList[i].begin(); + it != _orList[i].end(); + it++ ) + if ( a != (*it) && (*it)->isSet() ) + throw(CmdLineParseException( + "Mutually exclusive argument already set!", + (*it)->toString())); + + // go through and set each arg that is not a + for ( ArgVectorIterator it = _orList[i].begin(); + it != _orList[i].end(); + it++ ) + if ( a != (*it) ) + (*it)->xorSet(); + + // return the number of required args that have now been set + if ( (*ait)->allowMore() ) + return 0; + else + return static_cast(_orList[i].size()); + } + } + + if ( a->isRequired() ) + return 1; + else + return 0; +} + +inline bool XorHandler::contains( const Arg* a ) +{ + for ( int i = 0; static_cast(i) < _orList.size(); i++ ) + for ( ArgVectorIterator it = _orList[i].begin(); + it != _orList[i].end(); + it++ ) + if ( a == (*it) ) + return true; + + return false; +} + +inline std::vector< std::vector >& XorHandler::getXorList() +{ + return _orList; +} + + + +////////////////////////////////////////////////////////////////////// +//END XOR.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif diff --git a/deps/include/tclap/ZshCompletionOutput.h b/deps/include/tclap/ZshCompletionOutput.h new file mode 100644 index 0000000..0b37fc7 --- /dev/null +++ b/deps/include/tclap/ZshCompletionOutput.h @@ -0,0 +1,323 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: ZshCompletionOutput.h + * + * Copyright (c) 2006, Oliver Kiddle + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_ZSHCOMPLETIONOUTPUT_H +#define TCLAP_ZSHCOMPLETIONOUTPUT_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace TCLAP { + +/** + * A class that generates a Zsh completion function as output from the usage() + * method for the given CmdLine and its Args. + */ +class ZshCompletionOutput : public CmdLineOutput +{ + + public: + + ZshCompletionOutput(); + + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface& c, + ArgException& e ); + + protected: + + void basename( std::string& s ); + void quoteSpecialChars( std::string& s ); + + std::string getMutexList( CmdLineInterface& _cmd, Arg* a ); + void printOption( Arg* it, std::string mutex ); + void printArg( Arg* it ); + + std::map common; + char theDelimiter; +}; + +ZshCompletionOutput::ZshCompletionOutput() +: common(std::map()), + theDelimiter('=') +{ + common["host"] = "_hosts"; + common["hostname"] = "_hosts"; + common["file"] = "_files"; + common["filename"] = "_files"; + common["user"] = "_users"; + common["username"] = "_users"; + common["directory"] = "_directories"; + common["path"] = "_directories"; + common["url"] = "_urls"; +} + +inline void ZshCompletionOutput::version(CmdLineInterface& _cmd) +{ + std::cout << _cmd.getVersion() << std::endl; +} + +inline void ZshCompletionOutput::usage(CmdLineInterface& _cmd ) +{ + std::list argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + std::string xversion = _cmd.getVersion(); + theDelimiter = _cmd.getDelimiter(); + basename(progName); + + std::cout << "#compdef " << progName << std::endl << std::endl << + "# " << progName << " version " << _cmd.getVersion() << std::endl << std::endl << + "_arguments -s -S"; + + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + { + if ( (*it)->shortID().at(0) == '<' ) + printArg((*it)); + else if ( (*it)->getFlag() != "-" ) + printOption((*it), getMutexList(_cmd, *it)); + } + + std::cout << std::endl; +} + +inline void ZshCompletionOutput::failure( CmdLineInterface& _cmd, + ArgException& e ) +{ + static_cast(_cmd); // unused + std::cout << e.what() << std::endl; +} + +inline void ZshCompletionOutput::quoteSpecialChars( std::string& s ) +{ + size_t idx = s.find_last_of(':'); + while ( idx != std::string::npos ) + { + s.insert(idx, 1, '\\'); + idx = s.find_last_of(':', idx); + } + idx = s.find_last_of('\''); + while ( idx != std::string::npos ) + { + s.insert(idx, "'\\'"); + if (idx == 0) + idx = std::string::npos; + else + idx = s.find_last_of('\'', --idx); + } +} + +inline void ZshCompletionOutput::basename( std::string& s ) +{ + size_t p = s.find_last_of('/'); + if ( p != std::string::npos ) + { + s.erase(0, p + 1); + } +} + +inline void ZshCompletionOutput::printArg(Arg* a) +{ + static int count = 1; + + std::cout << " \\" << std::endl << " '"; + if ( a->acceptsMultipleValues() ) + std::cout << '*'; + else + std::cout << count++; + std::cout << ':'; + if ( !a->isRequired() ) + std::cout << ':'; + + std::cout << a->getName() << ':'; + std::map::iterator compArg = common.find(a->getName()); + if ( compArg != common.end() ) + { + std::cout << compArg->second; + } + else + { + std::cout << "_guard \"^-*\" " << a->getName(); + } + std::cout << '\''; +} + +inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex) +{ + std::string flag = a->flagStartChar() + a->getFlag(); + std::string name = a->nameStartString() + a->getName(); + std::string desc = a->getDescription(); + + // remove full stop and capitalisation from description as + // this is the convention for zsh function + if (!desc.compare(0, 12, "(required) ")) + { + desc.erase(0, 12); + } + if (!desc.compare(0, 15, "(OR required) ")) + { + desc.erase(0, 15); + } + size_t len = desc.length(); + if (len && desc.at(--len) == '.') + { + desc.erase(len); + } + if (len) + { + desc.replace(0, 1, 1, tolower(desc.at(0))); + } + + std::cout << " \\" << std::endl << " '" << mutex; + + if ( a->getFlag().empty() ) + { + std::cout << name; + } + else + { + std::cout << "'{" << flag << ',' << name << "}'"; + } + if ( theDelimiter == '=' && a->isValueRequired() ) + std::cout << "=-"; + quoteSpecialChars(desc); + std::cout << '[' << desc << ']'; + + if ( a->isValueRequired() ) + { + std::string arg = a->shortID(); + arg.erase(0, arg.find_last_of(theDelimiter) + 1); + if ( arg.at(arg.length()-1) == ']' ) + arg.erase(arg.length()-1); + if ( arg.at(arg.length()-1) == ']' ) + { + arg.erase(arg.length()-1); + } + if ( arg.at(0) == '<' ) + { + arg.erase(arg.length()-1); + arg.erase(0, 1); + } + size_t p = arg.find('|'); + if ( p != std::string::npos ) + { + do + { + arg.replace(p, 1, 1, ' '); + } + while ( (p = arg.find_first_of('|', p)) != std::string::npos ); + quoteSpecialChars(arg); + std::cout << ": :(" << arg << ')'; + } + else + { + std::cout << ':' << arg; + std::map::iterator compArg = common.find(arg); + if ( compArg != common.end() ) + { + std::cout << ':' << compArg->second; + } + } + } + + std::cout << '\''; +} + +inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Arg* a) +{ + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector > xorList = xorHandler.getXorList(); + + if (a->getName() == "help" || a->getName() == "version") + { + return "(-)"; + } + + std::ostringstream list; + if ( a->acceptsMultipleValues() ) + { + list << '*'; + } + + for ( int i = 0; static_cast(i) < xorList.size(); i++ ) + { + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); + it++) + if ( a == (*it) ) + { + list << '('; + for ( ArgVectorIterator iu = xorList[i].begin(); + iu != xorList[i].end(); + iu++ ) + { + bool notCur = (*iu) != a; + bool hasFlag = !(*iu)->getFlag().empty(); + if ( iu != xorList[i].begin() && (notCur || hasFlag) ) + list << ' '; + if (hasFlag) + list << (*iu)->flagStartChar() << (*iu)->getFlag() << ' '; + if ( notCur || hasFlag ) + list << (*iu)->nameStartString() << (*iu)->getName(); + } + list << ')'; + return list.str(); + } + } + + // wasn't found in xor list + if (!a->getFlag().empty()) { + list << "(" << a->flagStartChar() << a->getFlag() << ' ' << + a->nameStartString() << a->getName() << ')'; + } + + return list.str(); +} + +} //namespace TCLAP +#endif