From 91686a86876553774452d97f3f74d5f147b19164 Mon Sep 17 00:00:00 2001 From: Kevin Smith <git@kismith.co.uk> Date: Wed, 21 Apr 2010 11:45:51 +0000 Subject: Make latency stats optional. Includes boost program_options so we can use commandline parameters. Netbook mode is now activated with --netbook-mode. Latency debug is activated with --latency-debug. diff --git a/3rdParty/Boost/SConscript b/3rdParty/Boost/SConscript index 3e6897f..43f0180 100644 --- a/3rdParty/Boost/SConscript +++ b/3rdParty/Boost/SConscript @@ -61,7 +61,18 @@ if env["SCONS_STAGE"] == "build" : "src/libs/regex/src/wc_regex_traits.cpp", "src/libs/regex/src/wide_posix_api.cpp", "src/libs/regex/src/winstances.cpp", - "src/libs/regex/src/usinstances.cpp"] + "src/libs/regex/src/usinstances.cpp", + "src/libs/program_options/src/cmdline.cpp", + "src/libs/program_options/src/config_file.cpp", + "src/libs/program_options/src/convert.cpp", + "src/libs/program_options/src/options_description.cpp", + "src/libs/program_options/src/parsers.cpp", + "src/libs/program_options/src/positional_options.cpp", + "src/libs/program_options/src/split.cpp", + "src/libs/program_options/src/utf8_codecvt_facet.cpp", + "src/libs/program_options/src/value_semantic.cpp", + "src/libs/program_options/src/variables_map.cpp", + "src/libs/program_options/src/winmain.cpp"] if env["PLATFORM"] != "win32" : sources += [ @@ -82,6 +93,7 @@ if env["SCONS_STAGE"] == "build" : bcp_env.Append(CPPPATH = ["src/tools/bcp"]) bcp_env.Program("bcp", [ "src/tools/bcp/add_path.cpp", + "src/tools/bcp/add_dependent_lib.cpp", "src/tools/bcp/bcp_imp.cpp", "src/tools/bcp/copy_path.cpp", "src/tools/bcp/file_types.cpp", diff --git a/3rdParty/Boost/src/boost/program_options.hpp b/3rdParty/Boost/src/boost/program_options.hpp new file mode 100644 index 0000000..9d12b08 --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options.hpp @@ -0,0 +1,25 @@ +// Copyright Vladimir Prus 2002. +// 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) + +// See www.boost.org/libs/program_options for documentation. + +#ifndef PROGRAM_OPTIONS_VP_2003_05_19 +#define PROGRAM_OPTIONS_VP_2003_05_19 + +#if _MSC_VER >= 1020 +#pragma once +#endif + +#include <boost/program_options/options_description.hpp> +#include <boost/program_options/positional_options.hpp> +#include <boost/program_options/parsers.hpp> +#include <boost/program_options/variables_map.hpp> +#include <boost/program_options/cmdline.hpp> +#include <boost/program_options/errors.hpp> +#include <boost/program_options/option.hpp> +#include <boost/program_options/value_semantic.hpp> +#include <boost/program_options/version.hpp> + +#endif diff --git a/3rdParty/Boost/src/boost/program_options/cmdline.hpp b/3rdParty/Boost/src/boost/program_options/cmdline.hpp new file mode 100644 index 0000000..8705e60 --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/cmdline.hpp @@ -0,0 +1,90 @@ +// Copyright Vladimir Prus 2004. +// 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 BOOST_CMDLINE_HPP_VP_2004_03_13 +#define BOOST_CMDLINE_HPP_VP_2004_03_13 + +namespace boost { namespace program_options { namespace command_line_style { + /** Various possible styles of options. + + There are "long" options, which start with "--" and "short", + which start with either "-" or "/". Both kinds can be allowed or + disallowed, see allow_long and allow_short. The allowed character + for short options is also configurable. + + Option's value can be specified in the same token as name + ("--foo=bar"), or in the next token. + + It's possible to introduce long options by the same character as + short options, see allow_long_disguise. + + Finally, guessing (specifying only prefix of option) and case + insensitive processing are supported. + */ + enum style_t { + /// Allow "--long_name" style + allow_long = 1, + /// Allow "-<single character" style + allow_short = allow_long << 1, + /// Allow "-" in short options + allow_dash_for_short = allow_short << 1, + /// Allow "/" in short options + allow_slash_for_short = allow_dash_for_short << 1, + /** Allow option parameter in the same token + for long option, like in + @verbatim + --foo=10 + @endverbatim + */ + long_allow_adjacent = allow_slash_for_short << 1, + /** Allow option parameter in the next token for + long options. */ + long_allow_next = long_allow_adjacent << 1, + /** Allow option parameter in the same token for + short options. */ + short_allow_adjacent = long_allow_next << 1, + /** Allow option parameter in the next token for + short options. */ + short_allow_next = short_allow_adjacent << 1, + /** Allow to merge several short options together, + so that "-s -k" become "-sk". All of the options + but last should accept no parameter. For example, if + "-s" accept a parameter, then "k" will be taken as + parameter, not another short option. + Dos-style short options cannot be sticky. + */ + allow_sticky = short_allow_next << 1, + /** Allow abbreviated spellings for long options, + if they unambiguously identify long option. + No long option name should be prefix of other + long option name if guessing is in effect. + */ + allow_guessing = allow_sticky << 1, + /** Ignore the difference in case for long options. + */ + long_case_insensitive = allow_guessing << 1, + /** Ignore the difference in case for short options. + */ + short_case_insensitive = long_case_insensitive << 1, + /** Ignore the difference in case for all options. + */ + case_insensitive = (long_case_insensitive | short_case_insensitive), + /** Allow long options with single option starting character, + e.g <tt>-foo=10</tt> + */ + allow_long_disguise = short_case_insensitive << 1, + /** The more-or-less traditional unix style. */ + unix_style = (allow_short | short_allow_adjacent | short_allow_next + | allow_long | long_allow_adjacent | long_allow_next + | allow_sticky | allow_guessing + | allow_dash_for_short), + /** The default style. */ + default_style = unix_style + }; +}}} + + +#endif + diff --git a/3rdParty/Boost/src/boost/program_options/config.hpp b/3rdParty/Boost/src/boost/program_options/config.hpp new file mode 100644 index 0000000..0c69c14 --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/config.hpp @@ -0,0 +1,55 @@ +// Copyright (c) 2004 Hartmut Kaiser +// +// Use, modification and distribution is subject to 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 BOOST_PROGRAM_OPTIONS_CONFIG_HK_2004_01_11 +#define BOOST_PROGRAM_OPTIONS_CONFIG_HK_2004_01_11 + +#include <boost/config.hpp> +#include <boost/version.hpp> + +// Support for autolinking. +#if BOOST_VERSION >= 103100 // works beginning from Boost V1.31.0 + +/////////////////////////////////////////////////////////////////////////////// +// enable automatic library variant selection +#if !defined(BOOST_PROGRAM_OPTIONS_SOURCE) && !defined(BOOST_ALL_NO_LIB) && \ + !defined(BOOST_PROGRAM_OPTIONS_NO_LIB) + +// Set the name of our library, this will get undef'ed by auto_link.hpp +// once it's done with it: +#define BOOST_LIB_NAME boost_program_options +// tell the auto-link code to select a dll when required: +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_PROGRAM_OPTIONS_DYN_LINK) +# define BOOST_DYN_LINK +#endif + +// And include the header that does the work: +#include <boost/config/auto_link.hpp> + +#endif // auto-linking disabled + +#endif // BOOST_VERSION + +/////////////////////////////////////////////////////////////////////////////// +// Windows DLL suport +#ifdef BOOST_HAS_DECLSPEC +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_PROGRAM_OPTIONS_DYN_LINK) +// export if this is our own source, otherwise import: +#ifdef BOOST_PROGRAM_OPTIONS_SOURCE +# define BOOST_PROGRAM_OPTIONS_DECL __declspec(dllexport) +#else +# define BOOST_PROGRAM_OPTIONS_DECL __declspec(dllimport) +#endif // BOOST_PROGRAM_OPTIONS_SOURCE +#endif // DYN_LINK +#endif // BOOST_HAS_DECLSPEC + +#ifndef BOOST_PROGRAM_OPTIONS_DECL +#define BOOST_PROGRAM_OPTIONS_DECL +#endif + + +#endif // PROGRAM_OPTIONS_CONFIG_HK_2004_01_11 + diff --git a/3rdParty/Boost/src/boost/program_options/detail/cmdline.hpp b/3rdParty/Boost/src/boost/program_options/detail/cmdline.hpp new file mode 100644 index 0000000..8d60ead --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/detail/cmdline.hpp @@ -0,0 +1,138 @@ +// Copyright Vladimir Prus 2002-2004. +// 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 BOOST_CMDLINE_VP_2003_05_19 +#define BOOST_CMDLINE_VP_2003_05_19 + +#include <boost/program_options/config.hpp> +#include <boost/program_options/errors.hpp> +#include <boost/program_options/cmdline.hpp> +#include <boost/program_options/option.hpp> +#include <boost/program_options/options_description.hpp> +#include <boost/program_options/positional_options.hpp> + + +#include <boost/detail/workaround.hpp> + +#include <boost/function.hpp> + +#include <string> +#include <vector> + +namespace boost { namespace program_options { namespace detail { + + /** Command line parser class. Main requirements were: + - Powerful enough to support all common uses. + - Simple and easy to learn/use. + - Minimal code size and external dependencies. + - Extensible for custom syntaxes. + + First all options are registered. After that, elements of command line + are extracted using operator++. + + For each element, user can find + - if it's an option or an argument + - name of the option + - index of the option + - option value(s), if any + + Sometimes the registered option name is not equal to the encountered + one, for example, because name abbreviation is supported. Therefore + two option names can be obtained: + - the registered one + - the one found at the command line + + There are lot of style options, which can be used to tune the command + line parsing. In addition, it's possible to install additional parser + which will process custom option styles. + + @todo mininal match length for guessing? + */ + class BOOST_PROGRAM_OPTIONS_DECL cmdline { + public: + + typedef ::boost::program_options::command_line_style::style_t style_t; + + typedef function1<std::pair<std::string, std::string>, + const std::string&> + additional_parser; + + typedef function1<std::vector<option>, std::vector<std::string>&> + style_parser; + + /** Constructs a command line parser for (argc, argv) pair. Uses + style options passed in 'style', which should be binary or'ed values + of style_t enum. It can also be zero, in which case a "default" + style will be used. If 'allow_unregistered' is true, then allows + unregistered options. They will be assigned index 1 and are + assumed to have optional parameter. + */ + cmdline(const std::vector<std::string>& args); + + /** @overload */ + cmdline(int argc, const char*const * argv); + + void style(int style); + void allow_unregistered(); + + void set_options_description(const options_description& desc); + void set_positional_options( + const positional_options_description& m_positional); + + std::vector<option> run(); + + std::vector<option> parse_long_option(std::vector<std::string>& args); + std::vector<option> parse_short_option(std::vector<std::string>& args); + std::vector<option> parse_dos_option(std::vector<std::string>& args); + std::vector<option> parse_disguised_long_option( + std::vector<std::string>& args); + std::vector<option> parse_terminator( + std::vector<std::string>& args); + std::vector<option> handle_additional_parser( + std::vector<std::string>& args); + + + /** Set additional parser. This will be called for each token + of command line. If first string in pair is not empty, + then the token is considered matched by this parser, + and the first string will be considered an option name + (which can be long or short), while the second will be + option's parameter (if not empty). + Note that additional parser can match only one token. + */ + void set_additional_parser(additional_parser p); + + void extra_style_parser(style_parser s); + + void check_style(int style) const; + + bool is_style_active(style_t style) const; + + void init(const std::vector<std::string>& args); + + void + finish_option(option& opt, + std::vector<std::string>& other_tokens, + const std::vector<style_parser>& style_parsers); + + // Copies of input. + std::vector<std::string> args; + style_t m_style; + bool m_allow_unregistered; + + const options_description* m_desc; + const positional_options_description* m_positional; + + additional_parser m_additional_parser; + style_parser m_style_parser; + }; + + void test_cmdline_detail(); + +}}} + +#endif + diff --git a/3rdParty/Boost/src/boost/program_options/detail/config_file.hpp b/3rdParty/Boost/src/boost/program_options/detail/config_file.hpp new file mode 100644 index 0000000..91caac7 --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/detail/config_file.hpp @@ -0,0 +1,182 @@ +// Copyright Vladimir Prus 2002-2004. +// 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 BOOST_CONFIG_FILE_VP_2003_01_02 +#define BOOST_CONFIG_FILE_VP_2003_01_02 + +#include <iosfwd> +#include <string> +#include <set> + +#include <boost/noncopyable.hpp> +#include <boost/program_options/config.hpp> +#include <boost/program_options/option.hpp> +#include <boost/program_options/eof_iterator.hpp> + +#include <boost/detail/workaround.hpp> +#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3202)) +#include <boost/program_options/detail/convert.hpp> +#endif + +#if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) +#include <istream> // std::getline +#endif + +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/shared_ptr.hpp> + + + +namespace boost { namespace program_options { namespace detail { + + /** Standalone parser for config files in ini-line format. + The parser is a model of single-pass lvalue iterator, and + default constructor creates past-the-end-iterator. The typical usage is: + config_file_iterator i(is, ... set of options ...), e; + for(; i !=e; ++i) { + *i; + } + + Syntax conventions: + + - config file can not contain positional options + - '#' is comment character: it is ignored together with + the rest of the line. + - variable assignments are in the form + name '=' value. + spaces around '=' are trimmed. + - Section names are given in brackets. + + The actual option name is constructed by combining current section + name and specified option name, with dot between. If section_name + already contains dot at the end, new dot is not inserted. For example: + @verbatim + [gui.accessibility] + visual_bell=yes + @endverbatim + will result in option "gui.accessibility.visual_bell" with value + "yes" been returned. + + TODO: maybe, we should just accept a pointer to options_description + class. + */ + class common_config_file_iterator + : public eof_iterator<common_config_file_iterator, option> + { + public: + common_config_file_iterator() { found_eof(); } + common_config_file_iterator( + const std::set<std::string>& allowed_options, + bool allow_unregistered = false); + + virtual ~common_config_file_iterator() {} + + public: // Method required by eof_iterator + + void get(); + + protected: // Stubs for derived classes + + // Obtains next line from the config file + // Note: really, this design is a bit ugly + // The most clean thing would be to pass 'line_iterator' to + // constructor of this class, but to avoid templating this class + // we'd need polymorphic iterator, which does not exist yet. + virtual bool getline(std::string&) { return false; } + + private: + /** Adds another allowed option. If the 'name' ends with + '*', then all options with the same prefix are + allowed. For example, if 'name' is 'foo*', then 'foo1' and + 'foo_bar' are allowed. */ + void add_option(const char* name); + + // Returns true if 's' is a registered option name. + bool allowed_option(const std::string& s) const; + + // That's probably too much data for iterator, since + // it will be copied, but let's not bother for now. + std::set<std::string> allowed_options; + // Invariant: no element is prefix of other element. + std::set<std::string> allowed_prefixes; + std::string m_prefix; + bool m_allow_unregistered; + }; + + template<class charT> + class basic_config_file_iterator : public common_config_file_iterator { + public: + basic_config_file_iterator() + { + found_eof(); + } + + /** Creates a config file parser for the specified stream. + */ + basic_config_file_iterator(std::basic_istream<charT>& is, + const std::set<std::string>& allowed_options, + bool allow_unregistered = false); + + private: // base overrides + + bool getline(std::string&); + + private: // internal data + shared_ptr<std::basic_istream<charT> > is; + }; + + typedef basic_config_file_iterator<char> config_file_iterator; + typedef basic_config_file_iterator<wchar_t> wconfig_file_iterator; + + + struct null_deleter + { + void operator()(void const *) const {} + }; + + + template<class charT> + basic_config_file_iterator<charT>:: + basic_config_file_iterator(std::basic_istream<charT>& is, + const std::set<std::string>& allowed_options, + bool allow_unregistered) + : common_config_file_iterator(allowed_options, allow_unregistered) + { + this->is.reset(&is, null_deleter()); + get(); + } + + // Specializing this function for wchar_t causes problems on + // borland and vc7, as well as on metrowerks. On the first two + // I don't know a workaround, so make use of 'to_internal' to + // avoid specialization. + template<class charT> + bool + basic_config_file_iterator<charT>::getline(std::string& s) + { + std::basic_string<charT> in; + if (std::getline(*is, in)) { + s = to_internal(in); + return true; + } else { + return false; + } + } + + // Specialization is needed to workaround getline bug on Comeau. +#if BOOST_WORKAROUND(__COMO_VERSION__, BOOST_TESTED_AT(4303)) || \ + (defined(__sgi) && BOOST_WORKAROUND(_COMPILER_VERSION, BOOST_TESTED_AT(741))) + template<> + bool + basic_config_file_iterator<wchar_t>::getline(std::string& s); +#endif + + + +}}} + +#endif diff --git a/3rdParty/Boost/src/boost/program_options/detail/convert.hpp b/3rdParty/Boost/src/boost/program_options/detail/convert.hpp new file mode 100644 index 0000000..a22dd6f --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/detail/convert.hpp @@ -0,0 +1,107 @@ +// Copyright Vladimir Prus 2004. +// 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 BOOST_CONVERT_HPP_VP_2004_04_28 +#define BOOST_CONVERT_HPP_VP_2004_04_28 + +#include <boost/program_options/config.hpp> + +#if !defined(BOOST_NO_STD_WSTRING) + +#include <boost/detail/workaround.hpp> + +#include <string> +#include <vector> +#include <locale> +// for mbstate_t +#include <cwchar> +#include <stdexcept> + +#if defined(BOOST_NO_STDC_NAMESPACE) +#include <wchar.h> +namespace std +{ + using ::mbstate_t; +} +#endif + +namespace boost { + + /** Converts from local 8 bit encoding into wchar_t string using + the specified locale facet. */ + BOOST_PROGRAM_OPTIONS_DECL std::wstring + from_8_bit(const std::string& s, + const std::codecvt<wchar_t, char, std::mbstate_t>& cvt); + + /** Converts from wchar_t string into local 8 bit encoding into using + the specified locale facet. */ + BOOST_PROGRAM_OPTIONS_DECL std::string + to_8_bit(const std::wstring& s, + const std::codecvt<wchar_t, char, std::mbstate_t>& cvt); + + + /** Converts 's', which is assumed to be in UTF8 encoding, into wide + string. */ + BOOST_PROGRAM_OPTIONS_DECL std::wstring + from_utf8(const std::string& s); + + /** Converts wide string 's' into string in UTF8 encoding. */ + BOOST_PROGRAM_OPTIONS_DECL std::string + to_utf8(const std::wstring& s); + + /** Converts wide string 's' into local 8 bit encoding determined by + the current locale. */ + BOOST_PROGRAM_OPTIONS_DECL std::string + to_local_8_bit(const std::wstring& s); + + /** Converts 's', which is assumed to be in local 8 bit encoding, into wide + string. */ + BOOST_PROGRAM_OPTIONS_DECL std::wstring + from_local_8_bit(const std::string& s); + + namespace program_options + { + /** Convert the input string into internal encoding used by + program_options. Presence of this function allows to avoid + specializing all methods which access input on wchar_t. + */ + BOOST_PROGRAM_OPTIONS_DECL std::string to_internal(const std::string&); + /** @overload */ + BOOST_PROGRAM_OPTIONS_DECL std::string to_internal(const std::wstring&); + + template<class T> + std::vector<std::string> to_internal(const std::vector<T>& s) + { + std::vector<std::string> result; + for (unsigned i = 0; i < s.size(); ++i) + result.push_back(to_internal(s[i])); + return result; + } + + } + + + +} + +#else +#include <vector> +#include <string> +namespace boost{ + namespace program_options{ + BOOST_PROGRAM_OPTIONS_DECL std::string to_internal(const std::string&); + + template<class T> + std::vector<std::string> to_internal(const std::vector<T>& s) + { + std::vector<std::string> result; + for (unsigned i = 0; i < s.size(); ++i) + result.push_back(to_internal(s[i])); + return result; + } + } +} +#endif +#endif diff --git a/3rdParty/Boost/src/boost/program_options/detail/parsers.hpp b/3rdParty/Boost/src/boost/program_options/detail/parsers.hpp new file mode 100644 index 0000000..ee19207 --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/detail/parsers.hpp @@ -0,0 +1,146 @@ +// Copyright Vladimir Prus 2004. +// 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 BOOST_PARSERS_HPP_VP_2004_05_06 +#define BOOST_PARSERS_HPP_VP_2004_05_06 + +#include <boost/program_options/detail/convert.hpp> + +#include <iterator> + +namespace boost { namespace program_options { + + namespace detail { + template<class charT, class Iterator> + std::vector<std::basic_string<charT> > + make_vector(Iterator i, Iterator e) + { + std::vector<std::basic_string<charT> > result; + // Some compilers don't have templated constructor for + // vector, so we can't create vector from (argv+1, argv+argc) range + for(; i != e; ++i) + result.push_back(*i); + return result; + } + } + + template<class charT> + basic_command_line_parser<charT>:: + basic_command_line_parser(const std::vector< + std::basic_string<charT> >& args) + : detail::cmdline(to_internal(args)) + {} + + + template<class charT> + basic_command_line_parser<charT>:: + basic_command_line_parser(int argc, charT* argv[]) + : detail::cmdline( + // Explicit template arguments are required by gcc 3.3.1 + // (at least mingw version), and do no harm on other compilers. + to_internal(detail::make_vector<charT, charT**>(argv+1, argv+argc+!argc))) + {} + + + template<class charT> + basic_command_line_parser<charT>& + basic_command_line_parser<charT>::options(const options_description& desc) + { + detail::cmdline::set_options_description(desc); + m_desc = &desc; + return *this; + } + + template<class charT> + basic_command_line_parser<charT>& + basic_command_line_parser<charT>::positional( + const positional_options_description& desc) + { + detail::cmdline::set_positional_options(desc); + return *this; + } + + template<class charT> + basic_command_line_parser<charT>& + basic_command_line_parser<charT>::style(int style) + { + detail::cmdline::style(style); + return *this; + } + + template<class charT> + basic_command_line_parser<charT>& + basic_command_line_parser<charT>::extra_parser(ext_parser ext) + { + detail::cmdline::set_additional_parser(ext); + return *this; + } + + template<class charT> + basic_command_line_parser<charT>& + basic_command_line_parser<charT>::allow_unregistered() + { + detail::cmdline::allow_unregistered(); + return *this; + } + + template<class charT> + basic_command_line_parser<charT>& + basic_command_line_parser<charT>::extra_style_parser(style_parser s) + { + detail::cmdline::extra_style_parser(s); + return *this; + } + + + + template<class charT> + basic_parsed_options<charT> + basic_command_line_parser<charT>::run() + { + parsed_options result(m_desc); + result.options = detail::cmdline::run(); + + // Presense of parsed_options -> wparsed_options conversion + // does the trick. + return basic_parsed_options<charT>(result); + } + + + template<class charT> + basic_parsed_options<charT> + parse_command_line(int argc, charT* argv[], + const options_description& desc, + int style, + function1<std::pair<std::string, std::string>, + const std::string&> ext) + { + return basic_command_line_parser<charT>(argc, argv).options(desc). + style(style).extra_parser(ext).run(); + } + + template<class charT> + std::vector< std::basic_string<charT> > + collect_unrecognized(const std::vector< basic_option<charT> >& options, + enum collect_unrecognized_mode mode) + { + std::vector< std::basic_string<charT> > result; + for(unsigned i = 0; i < options.size(); ++i) + { + if (options[i].unregistered || + (mode == include_positional && options[i].position_key != -1)) + { + copy(options[i].original_tokens.begin(), + options[i].original_tokens.end(), + back_inserter(result)); + } + } + return result; + } + + +}} + +#endif diff --git a/3rdParty/Boost/src/boost/program_options/detail/utf8_codecvt_facet.hpp b/3rdParty/Boost/src/boost/program_options/detail/utf8_codecvt_facet.hpp new file mode 100644 index 0000000..b77b551 --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/detail/utf8_codecvt_facet.hpp @@ -0,0 +1,25 @@ +// Copyright (c) 2001 Ronald Garcia, Indiana University (garcia@osl.iu.edu) +// Andrew Lumsdaine, Indiana University (lums@osl.iu.edu). Permission to copy, +// use, modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided "as is" +// without express or implied warranty, and with no claim as to its suitability +// for any purpose. + +#ifndef BOOST_PROGRAM_OPTIONS_UTF8_CODECVT_FACET_HPP +#define BOOST_PROGRAM_OPTIONS_UTF8_CODECVT_FACET_HPP + +#include <boost/program_options/config.hpp> + +#define BOOST_UTF8_BEGIN_NAMESPACE \ + namespace boost { namespace program_options { namespace detail { + +#define BOOST_UTF8_END_NAMESPACE }}} +#define BOOST_UTF8_DECL BOOST_PROGRAM_OPTIONS_DECL + +#include <boost/detail/utf8_codecvt_facet.hpp> + +#undef BOOST_UTF8_BEGIN_NAMESPACE +#undef BOOST_UTF8_END_NAMESPACE +#undef BOOST_UTF8_DECL + +#endif diff --git a/3rdParty/Boost/src/boost/program_options/detail/value_semantic.hpp b/3rdParty/Boost/src/boost/program_options/detail/value_semantic.hpp new file mode 100644 index 0000000..464e306 --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/detail/value_semantic.hpp @@ -0,0 +1,207 @@ +// Copyright Vladimir Prus 2004. +// 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) + +// This file defines template functions that are declared in +// ../value_semantic.hpp. + +#include <boost/throw_exception.hpp> + +namespace boost { namespace program_options { + + extern BOOST_PROGRAM_OPTIONS_DECL std::string arg; + + template<class T, class charT> + std::string + typed_value<T, charT>::name() const + { + if (!m_implicit_value.empty() && !m_implicit_value_as_text.empty()) { + std::string msg = "[=arg(=" + m_implicit_value_as_text + ")]"; + if (!m_default_value.empty() && !m_default_value_as_text.empty()) + msg += " (=" + m_default_value_as_text + ")"; + return msg; + } + else if (!m_default_value.empty() && !m_default_value_as_text.empty()) { + return arg + " (=" + m_default_value_as_text + ")"; + } else { + return arg; + } + } + + template<class T, class charT> + void + typed_value<T, charT>::notify(const boost::any& value_store) const + { + const T* value = boost::any_cast<T>(&value_store); + if (m_store_to) { + *m_store_to = *value; + } + if (m_notifier) { + m_notifier(*value); + } + } + + namespace validators { + /* If v.size() > 1, throw validation_error. + If v.size() == 1, return v.front() + Otherwise, returns a reference to a statically allocated + empty string if 'allow_empty' and throws validation_error + otherwise. */ + template<class charT> + const std::basic_string<charT>& get_single_string( + const std::vector<std::basic_string<charT> >& v, + bool allow_empty = false) + { + static std::basic_string<charT> empty; + if (v.size() > 1) + boost::throw_exception(validation_error(validation_error::multiple_values_not_allowed)); + else if (v.size() == 1) + return v.front(); + else if (!allow_empty) + boost::throw_exception(validation_error(validation_error::at_least_one_value_required)); + return empty; + } + + /* Throws multiple_occurrences if 'value' is not empty. */ + BOOST_PROGRAM_OPTIONS_DECL void + check_first_occurrence(const boost::any& value); + } + + using namespace validators; + + /** Validates 's' and updates 'v'. + @pre 'v' is either empty or in the state assigned by the previous + invocation of 'validate'. + The target type is specified via a parameter which has the type of + pointer to the desired type. This is workaround for compilers without + partial template ordering, just like the last 'long/int' parameter. + */ + template<class T, class charT> + void validate(boost::any& v, + const std::vector< std::basic_string<charT> >& xs, + T*, long) + { + validators::check_first_occurrence(v); + std::basic_string<charT> s(validators::get_single_string(xs)); + try { + v = any(lexical_cast<T>(s)); + } + catch(const bad_lexical_cast&) { + boost::throw_exception(invalid_option_value(s)); + } + } + + BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v, + const std::vector<std::string>& xs, + bool*, + int); + +#if !defined(BOOST_NO_STD_WSTRING) + BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v, + const std::vector<std::wstring>& xs, + bool*, + int); +#endif + // For some reason, this declaration, which is require by the standard, + // cause gcc 3.2 to not generate code to specialization defined in + // value_semantic.cpp +#if ! ( ( BOOST_WORKAROUND(__GNUC__, <= 3) &&\ + BOOST_WORKAROUND(__GNUC_MINOR__, < 3) ) || \ + ( BOOST_WORKAROUND(BOOST_MSVC, == 1310) ) \ + ) + BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v, + const std::vector<std::string>& xs, + std::string*, + int); + +#if !defined(BOOST_NO_STD_WSTRING) + BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v, + const std::vector<std::wstring>& xs, + std::string*, + int); +#endif +#endif + + /** Validates sequences. Allows multiple values per option occurrence + and multiple occurrences. */ + template<class T, class charT> + void validate(boost::any& v, + const std::vector<std::basic_string<charT> >& s, + std::vector<T>*, + int) + { + if (v.empty()) { + v = boost::any(std::vector<T>()); + } + std::vector<T>* tv = boost::any_cast< std::vector<T> >(&v); + assert(NULL != tv); + for (unsigned i = 0; i < s.size(); ++i) + { + try { + /* We call validate so that if user provided + a validator for class T, we use it even + when parsing vector<T>. */ + boost::any a; + std::vector<std::basic_string<charT> > v; + v.push_back(s[i]); + validate(a, v, (T*)0, 0); + tv->push_back(boost::any_cast<T>(a)); + } + catch(const bad_lexical_cast& /*e*/) { + boost::throw_exception(invalid_option_value(s[i])); + } + } + } + + template<class T, class charT> + void + typed_value<T, charT>:: + xparse(boost::any& value_store, + const std::vector<std::basic_string<charT> >& new_tokens) const + { + // If no tokens were given, and the option accepts an implicit + // value, then assign the implicit value as the stored value; + // otherwise, validate the user-provided token(s). + if (new_tokens.empty() && !m_implicit_value.empty()) + value_store = m_implicit_value; + else + validate(value_store, new_tokens, (T*)0, 0); + } + + template<class T> + typed_value<T>* + value() + { + // Explicit qualification is vc6 workaround. + return boost::program_options::value<T>(0); + } + + template<class T> + typed_value<T>* + value(T* v) + { + typed_value<T>* r = new typed_value<T>(v); + + return r; + } + + template<class T> + typed_value<T, wchar_t>* + wvalue() + { + return wvalue<T>(0); + } + + template<class T> + typed_value<T, wchar_t>* + wvalue(T* v) + { + typed_value<T, wchar_t>* r = new typed_value<T, wchar_t>(v); + + return r; + } + + + +}} diff --git a/3rdParty/Boost/src/boost/program_options/environment_iterator.hpp b/3rdParty/Boost/src/boost/program_options/environment_iterator.hpp new file mode 100644 index 0000000..c815693 --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/environment_iterator.hpp @@ -0,0 +1,51 @@ +// Copyright Vladimir Prus 2004. +// 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 BOOST_ENVIRONMENT_ITERATOR_VP_2004_05_14 +#define BOOST_ENVIRONMENT_ITERATOR_VP_2004_05_14 + +#include "eof_iterator.hpp" + +#include <utility> +#include <string> +#include <cassert> + +namespace boost { + + class environment_iterator + : public eof_iterator<environment_iterator, + std::pair<std::string, std::string> > + { + public: + environment_iterator(char** environment) + : m_environment(environment) + { + get(); + } + + environment_iterator() + { + found_eof(); + } + + void get() + { + if (*m_environment == 0) + found_eof(); + else { + std::string s(*m_environment); + std::string::size_type n = s.find('='); + assert(n != s.npos); + value().first = s.substr(0, n); + value().second = s.substr(n+1); + } + ++m_environment; + } + + private: + char** m_environment; + }; +} +#endif diff --git a/3rdParty/Boost/src/boost/program_options/eof_iterator.hpp b/3rdParty/Boost/src/boost/program_options/eof_iterator.hpp new file mode 100644 index 0000000..0efa6f7 --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/eof_iterator.hpp @@ -0,0 +1,97 @@ +// Copyright Vladimir Prus 2004. +// 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 BOOST_EOF_ITERATOR_VP_2004_03_12 +#define BOOST_EOF_ITERATOR_VP_2004_03_12 + +#include <boost/iterator/iterator_facade.hpp> + +namespace boost { + + /** The 'eof_iterator' class is useful for constructing forward iterators + in cases where iterator extract data from some source and it's easy + to detect 'eof' -- i.e. the situation where there's no data. One + apparent example is reading lines from a file. + + Implementing such iterators using 'iterator_facade' directly would + require to create class with three core operation, a couple of + constructors. When using 'eof_iterator', the derived class should define + only one method to get new value, plus a couple of constructors. + + The basic idea is that iterator has 'eof' bit. Two iterators are equal + only if both have their 'eof' bits set. The 'get' method either obtains + the new value or sets the 'eof' bit. + + Specifically, derived class should define: + + 1. A default constructor, which creates iterator with 'eof' bit set. The + constructor body should call 'found_eof' method defined here. + 2. Some other constructor. It should initialize some 'data pointer' used + in iterator operation and then call 'get'. + 3. The 'get' method. It should operate this way: + - look at some 'data pointer' to see if new element is available; + if not, it should call 'found_eof'. + - extract new element and store it at location returned by the 'value' + method. + - advance the data pointer. + + Essentially, the 'get' method has the functionality of both 'increment' + and 'dereference'. It's very good for the cases where data extraction + implicitly moves data pointer, like for stream operation. + */ + template<class Derived, class ValueType> + class eof_iterator : public iterator_facade<Derived, const ValueType, + forward_traversal_tag> + { + public: + eof_iterator() + : m_at_eof(false) + {} + + protected: // interface for derived + + /** Returns the reference which should be used by derived + class to store the next value. */ + ValueType& value() + { + return m_value; + } + + /** Should be called by derived class to indicate that it can't + produce next element. */ + void found_eof() + { + m_at_eof = true; + } + + + private: // iterator core operations + friend class iterator_core_access; + + void increment() + { + static_cast<Derived&>(*this).get(); + } + + bool equal(const eof_iterator& other) const + { + if (m_at_eof && other.m_at_eof) + return true; + else + return false; + } + + const ValueType& dereference() const + { + return m_value; + } + + bool m_at_eof; + ValueType m_value; + }; +} + +#endif + diff --git a/3rdParty/Boost/src/boost/program_options/errors.hpp b/3rdParty/Boost/src/boost/program_options/errors.hpp new file mode 100644 index 0000000..116af58 --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/errors.hpp @@ -0,0 +1,236 @@ +// Copyright Vladimir Prus 2002-2004. +// 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 BOOST_ERRORS_VP_2003_01_02 +#define BOOST_ERRORS_VP_2003_01_02 + +#include <boost/program_options/config.hpp> + +#include <string> +#include <stdexcept> +#include <vector> + + + +namespace boost { namespace program_options { + + /** Base class for all errors in the library. */ + class BOOST_PROGRAM_OPTIONS_DECL error : public std::logic_error { + public: + error(const std::string& what) : std::logic_error(what) {} + }; + + class BOOST_PROGRAM_OPTIONS_DECL invalid_syntax : public error { + public: + enum kind_t { + long_not_allowed = 30, + long_adjacent_not_allowed, + short_adjacent_not_allowed, + empty_adjacent_parameter, + missing_parameter, + extra_parameter, + unrecognized_line + }; + + invalid_syntax(const std::string& tokens, kind_t kind); + + // gcc says that throw specification on dtor is loosened + // without this line + ~invalid_syntax() throw() {} + + kind_t kind() const; + + const std::string& tokens() const; + + protected: + /** Used to convert kind_t to a related error text */ + static std::string error_message(kind_t kind); + + private: + // TODO: copy ctor might throw + std::string m_tokens; + + kind_t m_kind; + }; + + /** Class thrown when option name is not recognized. */ + class BOOST_PROGRAM_OPTIONS_DECL unknown_option : public error { + public: + unknown_option(const std::string& name) + : error(std::string("unknown option ").append(name)), + m_option_name(name) + {} + + // gcc says that throw specification on dtor is loosened + // without this line + ~unknown_option() throw() {} + + const std::string& get_option_name() const throw(); + + private: + std::string m_option_name; + }; + + /** Class thrown when there's ambiguity amoung several possible options. */ + class BOOST_PROGRAM_OPTIONS_DECL ambiguous_option : public error { + public: + ambiguous_option(const std::string& name, + const std::vector<std::string>& alternatives) + : error(std::string("ambiguous option ").append(name)) + , m_alternatives(alternatives) + , m_option_name(name) + {} + + ~ambiguous_option() throw() {} + + const std::string& get_option_name() const throw(); + + const std::vector<std::string>& alternatives() const throw(); + + private: + // TODO: copy ctor might throw + std::vector<std::string> m_alternatives; + std::string m_option_name; + }; + + /** Class thrown when there are several option values, but + user called a method which cannot return them all. */ + class BOOST_PROGRAM_OPTIONS_DECL multiple_values : public error { + public: + multiple_values() + : error("multiple values") + , m_option_name() {} + + ~multiple_values() throw() {} + + void set_option_name(const std::string& option); + + const std::string& get_option_name() const throw(); + + private: + std::string m_option_name; // The name of the option which + // caused the exception. + }; + + /** Class thrown when there are several occurrences of an + option, but user called a method which cannot return + them all. */ + class BOOST_PROGRAM_OPTIONS_DECL multiple_occurrences : public error { + public: + multiple_occurrences() + : error("multiple occurrences") + , m_option_name() {} + + ~multiple_occurrences() throw() {} + + void set_option_name(const std::string& option); + + const std::string& get_option_name() const throw(); + + private: + std::string m_option_name; // The name of the option which + // caused the exception. + }; + + /** Class thrown when value of option is incorrect. */ + class BOOST_PROGRAM_OPTIONS_DECL validation_error : public error { + public: + enum kind_t { + multiple_values_not_allowed = 30, + at_least_one_value_required, + invalid_bool_value, + invalid_option_value, + invalid_option + }; + + validation_error(kind_t kind, + const std::string& option_value = "", + const std::string& option_name = ""); + + ~validation_error() throw() {} + + void set_option_name(const std::string& option); + + const std::string& get_option_name() const throw(); + + const char* what() const throw(); + + protected: + /** Used to convert kind_t to a related error text */ + static std::string error_message(kind_t kind); + + private: + kind_t m_kind; + std::string m_option_name; // The name of the option which + // caused the exception. + std::string m_option_value; // Optional: value of the option m_options_name + mutable std::string m_message; // For on-demand formatting in 'what' + + }; + + /** Class thrown if there is an invalid option value givenn */ + class BOOST_PROGRAM_OPTIONS_DECL invalid_option_value + : public validation_error + { + public: + invalid_option_value(const std::string& value); +#ifndef BOOST_NO_STD_WSTRING + invalid_option_value(const std::wstring& value); +#endif + }; + + /** Class thrown when there are too many positional options. + This is a programming error. + */ + class BOOST_PROGRAM_OPTIONS_DECL too_many_positional_options_error : public error { + public: + too_many_positional_options_error() + : error("too many positional options") + {} + }; + + /** Class thrown when there are syntax errors in given command line */ + class BOOST_PROGRAM_OPTIONS_DECL invalid_command_line_syntax : public invalid_syntax { + public: + invalid_command_line_syntax(const std::string& tokens, kind_t kind); + }; + + /** Class thrown when there are programming error related to style */ + class BOOST_PROGRAM_OPTIONS_DECL invalid_command_line_style : public error { + public: + invalid_command_line_style(const std::string& msg) + : error(msg) + {} + }; + + /** Class thrown if config file can not be read */ + class BOOST_PROGRAM_OPTIONS_DECL reading_file : public error { + public: + reading_file(const char* filename) + : error(std::string("can not read file ").append(filename)) + {} + }; + + /** Class thrown when a required/mandatory option is missing */ + class BOOST_PROGRAM_OPTIONS_DECL required_option : public error { + public: + required_option(const std::string& name) + : error(std::string("missing required option ").append(name)) + , m_option_name(name) + {} + + ~required_option() throw() {} + + const std::string& get_option_name() const throw(); + + private: + std::string m_option_name; // The name of the option which + // caused the exception. + }; +}} + + +#endif diff --git a/3rdParty/Boost/src/boost/program_options/option.hpp b/3rdParty/Boost/src/boost/program_options/option.hpp new file mode 100644 index 0000000..557c692 --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/option.hpp @@ -0,0 +1,70 @@ +// Copyright Vladimir Prus 2004. +// 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 BOOST_OPTION_HPP_VP_2004_02_25 +#define BOOST_OPTION_HPP_VP_2004_02_25 + +#include <boost/program_options/config.hpp> + +#include <string> +#include <vector> + +namespace boost { namespace program_options { + + /** Option found in input source. + Contains a key and a value. The key, in turn, can be a string (name of + an option), or an integer (position in input source) -- in case no name + is specified. The latter is only possible for command line. + The template parameter specifies the type of char used for storing the + option's value. + */ + template<class charT> + class basic_option { + public: + basic_option() + : position_key(-1) + , unregistered(false) + , case_insensitive(false) + {} + basic_option(const std::string& string_key, + const std::vector< std::string> &value) + : string_key(string_key) + , value(value) + , unregistered(false) + , case_insensitive(false) + {} + + /** String key of this option. Intentionally independent of the template + parameter. */ + std::string string_key; + /** Position key of this option. All options without an explicit name are + sequentially numbered starting from 0. If an option has explicit name, + 'position_key' is equal to -1. It is possible that both + position_key and string_key is specified, in case name is implicitly + added. + */ + int position_key; + /** Option's value */ + std::vector< std::basic_string<charT> > value; + /** The original unchanged tokens this option was + created from. */ + std::vector< std::basic_string<charT> > original_tokens; + /** True if option was not recognized. In that case, + 'string_key' and 'value' are results of purely + syntactic parsing of source. The original tokens can be + recovered from the "original_tokens" member. + */ + bool unregistered; + /** True if string_key has to be handled + case insensitive. + */ + bool case_insensitive; + }; + typedef basic_option<char> option; + typedef basic_option<wchar_t> woption; + +}} + +#endif diff --git a/3rdParty/Boost/src/boost/program_options/options_description.hpp b/3rdParty/Boost/src/boost/program_options/options_description.hpp new file mode 100644 index 0000000..0486f02 --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/options_description.hpp @@ -0,0 +1,254 @@ +// Copyright Vladimir Prus 2002-2004. +// Copyright Bertolt Mildner 2004. +// 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 BOOST_OPTION_DESCRIPTION_VP_2003_05_19 +#define BOOST_OPTION_DESCRIPTION_VP_2003_05_19 + +#include <boost/program_options/config.hpp> +#include <boost/program_options/errors.hpp> +#include <boost/program_options/value_semantic.hpp> + +#include <boost/function.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/any.hpp> + +#include <string> +#include <vector> +#include <set> +#include <map> +#include <stdexcept> + +#include <iosfwd> + +/** Boost namespace */ +namespace boost { +/** Namespace for the library. */ +namespace program_options { + + /** Describes one possible command line/config file option. There are two + kinds of properties of an option. First describe it syntactically and + are used only to validate input. Second affect interpretation of the + option, for example default value for it or function that should be + called when the value is finally known. Routines which perform parsing + never use second kind of properties -- they are side effect free. + @sa options_description + */ + class BOOST_PROGRAM_OPTIONS_DECL option_description { + public: + + option_description(); + + /** Initializes the object with the passed data. + + Note: it would be nice to make the second parameter auto_ptr, + to explicitly pass ownership. Unfortunately, it's often needed to + create objects of types derived from 'value_semantic': + options_description d; + d.add_options()("a", parameter<int>("n")->default_value(1)); + Here, the static type returned by 'parameter' should be derived + from value_semantic. + + Alas, derived->base conversion for auto_ptr does not really work, + see + http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2000/n1232.pdf + http://std.dkuug.dk/jtc1/sc22/wg21/docs/cwg_defects.html#84 + + So, we have to use plain old pointers. Besides, users are not + expected to use the constructor directly. + + + The 'name' parameter is interpreted by the following rules: + - if there's no "," character in 'name', it specifies long name + - otherwise, the part before "," specifies long name and the part + after -- long name. + */ + option_description(const char* name, + const value_semantic* s); + + /** Initializes the class with the passed data. + */ + option_description(const char* name, + const value_semantic* s, + const char* description); + + virtual ~option_description(); + + enum match_result { no_match, full_match, approximate_match }; + + /** Given 'option', specified in the input source, + return 'true' is 'option' specifies *this. + */ + match_result match(const std::string& option, bool approx, + bool long_ignore_case, bool short_ignore_case) const; + + /** Return the key that should identify the option, in + particular in the variables_map class. + The 'option' parameter is the option spelling from the + input source. + If option name contains '*', returns 'option'. + If long name was specified, it's the long name, otherwise + it's a short name with prepended '-'. + */ + const std::string& key(const std::string& option) const; + + const std::string& long_name() const; + + /// Explanation of this option + const std::string& description() const; + + /// Semantic of option's value + shared_ptr<const value_semantic> semantic() const; + + /// Returns the option name, formatted suitably for usage message. + std::string format_name() const; + + /** Return the parameter name and properties, formatted suitably for + usage message. */ + std::string format_parameter() const; + + private: + + option_description& set_name(const char* name); + + std::string m_short_name, m_long_name, m_description; + // shared_ptr is needed to simplify memory management in + // copy ctor and destructor. + shared_ptr<const value_semantic> m_value_semantic; + }; + + class options_description; + + /** Class which provides convenient creation syntax to option_description. + */ + class BOOST_PROGRAM_OPTIONS_DECL options_description_easy_init { + public: + options_description_easy_init(options_description* owner); + + options_description_easy_init& + operator()(const char* name, + const char* description); + + options_description_easy_init& + operator()(const char* name, + const value_semantic* s); + + options_description_easy_init& + operator()(const char* name, + const value_semantic* s, + const char* description); + + private: + options_description* owner; + }; + + + /** A set of option descriptions. This provides convenient interface for + adding new option (the add_options) method, and facilities to search + for options by name. + + See @ref a_adding_options "here" for option adding interface discussion. + @sa option_description + */ + class BOOST_PROGRAM_OPTIONS_DECL options_description { + public: + static const unsigned m_default_line_length; + + /** Creates the instance. */ + options_description(unsigned line_length = m_default_line_length, + unsigned min_description_length = m_default_line_length / 2); + /** Creates the instance. The 'caption' parameter gives the name of + this 'options_description' instance. Primarily useful for output. + The 'description_length' specifies the number of columns that + should be reserved for the description text; if the option text + encroaches into this, then the description will start on the next + line. + */ + options_description(const std::string& caption, + unsigned line_length = m_default_line_length, + unsigned min_description_length = m_default_line_length / 2); + /** Adds new variable description. Throws duplicate_variable_error if + either short or long name matches that of already present one. + */ + void add(shared_ptr<option_description> desc); + /** Adds a group of option description. This has the same + effect as adding all option_descriptions in 'desc' + individually, except that output operator will show + a separate group. + Returns *this. + */ + options_description& add(const options_description& desc); + + public: + /** Returns an object of implementation-defined type suitable for adding + options to options_description. The returned object will + have overloaded operator() with parameter type matching + 'option_description' constructors. Calling the operator will create + new option_description instance and add it. + */ + options_description_easy_init add_options(); + + const option_description& find(const std::string& name, + bool approx, + bool long_ignore_case = false, + bool short_ignore_case = false) const; + + const option_description* find_nothrow(const std::string& name, + bool approx, + bool long_ignore_case = false, + bool short_ignore_case = false) const; + + + const std::vector< shared_ptr<option_description> >& options() const; + + /** Produces a human readable output of 'desc', listing options, + their descriptions and allowed parameters. Other options_description + instances previously passed to add will be output separately. */ + friend BOOST_PROGRAM_OPTIONS_DECL std::ostream& operator<<(std::ostream& os, + const options_description& desc); + + /** Output 'desc' to the specified stream, calling 'f' to output each + option_description element. */ + void print(std::ostream& os) const; + + private: + typedef std::map<std::string, int>::const_iterator name2index_iterator; + typedef std::pair<name2index_iterator, name2index_iterator> + approximation_range; + + //approximation_range find_approximation(const std::string& prefix) const; + + std::string m_caption; + const unsigned m_line_length; + const unsigned m_min_description_length; + + // Data organization is chosen because: + // - there could be two names for one option + // - option_add_proxy needs to know the last added option + std::vector< shared_ptr<option_description> > m_options; + + // Whether the option comes from one of declared groups. +#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(313)) + // vector<bool> is buggy there, see + // http://support.microsoft.com/default.aspx?scid=kb;en-us;837698 + std::vector<char> belong_to_group; +#else + std::vector<bool> belong_to_group; +#endif + + std::vector< shared_ptr<options_description> > groups; + + }; + + /** Class thrown when duplicate option description is found. */ + class BOOST_PROGRAM_OPTIONS_DECL duplicate_option_error : public error { + public: + duplicate_option_error(const std::string& what) : error(what) {} + }; +}} + +#endif diff --git a/3rdParty/Boost/src/boost/program_options/parsers.hpp b/3rdParty/Boost/src/boost/program_options/parsers.hpp new file mode 100644 index 0000000..e2a4467 --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/parsers.hpp @@ -0,0 +1,262 @@ +// Copyright Vladimir Prus 2002-2004. +// 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 BOOST_PARSERS_VP_2003_05_19 +#define BOOST_PARSERS_VP_2003_05_19 + +#include <boost/program_options/config.hpp> +#include <boost/program_options/option.hpp> +#include <boost/program_options/detail/cmdline.hpp> + +#include <boost/function/function1.hpp> + +#include <iosfwd> +#include <vector> +#include <utility> + +namespace boost { namespace program_options { + + class options_description; + class positional_options_description; + + + /** Results of parsing an input source. + The primary use of this class is passing information from parsers + component to value storage component. This class does not makes + much sense itself. + */ + template<class charT> + class basic_parsed_options { + public: + explicit basic_parsed_options(const options_description* description) + : description(description) {} + /** Options found in the source. */ + std::vector< basic_option<charT> > options; + /** Options description that was used for parsing. + Parsers should return pointer to the instance of + option_description passed to them, and issues of lifetime are + up to the caller. Can be NULL. + */ + const options_description* description; + }; + + /** Specialization of basic_parsed_options which: + - provides convenient conversion from basic_parsed_options<char> + - stores the passed char-based options for later use. + */ + template<> + class BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<wchar_t> { + public: + /** Constructs wrapped options from options in UTF8 encoding. */ + explicit basic_parsed_options(const basic_parsed_options<char>& po); + + std::vector< basic_option<wchar_t> > options; + const options_description* description; + + /** Stores UTF8 encoded options that were passed to constructor, + to avoid reverse conversion in some cases. */ + basic_parsed_options<char> utf8_encoded_options; + }; + + typedef basic_parsed_options<char> parsed_options; + typedef basic_parsed_options<wchar_t> wparsed_options; + + /** Augments basic_parsed_options<wchar_t> with conversion from + 'parsed_options' */ + + + typedef function1<std::pair<std::string, std::string>, const std::string&> ext_parser; + + /** Command line parser. + + The class allows one to specify all the information needed for parsing + and to parse the command line. It is primarily needed to + emulate named function parameters -- a regular function with 5 + parameters will be hard to use and creating overloads with a smaller + nuber of parameters will be confusing. + + For the most common case, the function parse_command_line is a better + alternative. + + There are two typedefs -- command_line_parser and wcommand_line_parser, + for charT == char and charT == wchar_t cases. + */ + template<class charT> + class basic_command_line_parser : private detail::cmdline { + public: + /** Creates a command line parser for the specified arguments + list. The 'args' parameter should not include program name. + */ + basic_command_line_parser(const std::vector< + std::basic_string<charT> >& args); + /** Creates a command line parser for the specified arguments + list. The parameters should be the same as passed to 'main'. + */ + basic_command_line_parser(int argc, charT* argv[]); + + /** Sets options descriptions to use. */ + basic_command_line_parser& options(const options_description& desc); + /** Sets positional options description to use. */ + basic_command_line_parser& positional( + const positional_options_description& desc); + + /** Sets the command line style. */ + basic_command_line_parser& style(int); + /** Sets the extra parsers. */ + basic_command_line_parser& extra_parser(ext_parser); + + /** Parses the options and returns the result of parsing. + Throws on error. + */ + basic_parsed_options<charT> run(); + + /** Specifies that unregistered options are allowed and should + be passed though. For each command like token that looks + like an option but does not contain a recognized name, an + instance of basic_option<charT> will be added to result, + with 'unrecognized' field set to 'true'. It's possible to + collect all unrecognized options with the 'collect_unrecognized' + funciton. + */ + basic_command_line_parser& allow_unregistered(); + + using detail::cmdline::style_parser; + + basic_command_line_parser& extra_style_parser(style_parser s); + + private: + const options_description* m_desc; + }; + + typedef basic_command_line_parser<char> command_line_parser; + typedef basic_command_line_parser<wchar_t> wcommand_line_parser; + + /** Creates instance of 'command_line_parser', passes parameters to it, + and returns the result of calling the 'run' method. + */ + template<class charT> + basic_parsed_options<charT> + parse_command_line(int argc, charT* argv[], + const options_description&, + int style = 0, + function1<std::pair<std::string, std::string>, + const std::string&> ext + = ext_parser()); + + /** Parse a config file. + + Read from given stream. + */ + template<class charT> +#if ! BOOST_WORKAROUND(__ICL, BOOST_TESTED_AT(700)) + BOOST_PROGRAM_OPTIONS_DECL +#endif + basic_parsed_options<charT> + parse_config_file(std::basic_istream<charT>&, const options_description&, + bool allow_unregistered = false); + + /** Parse a config file. + + Read from file with the given name. The character type is + passed to the file stream. + */ + template<class charT> +#if ! BOOST_WORKAROUND(__ICL, BOOST_TESTED_AT(700)) + BOOST_PROGRAM_OPTIONS_DECL +#endif + basic_parsed_options<charT> + parse_config_file(const char* filename, const options_description&, + bool allow_unregistered = false); + + /** Controls if the 'collect_unregistered' function should + include positional options, or not. */ + enum collect_unrecognized_mode + { include_positional, exclude_positional }; + + /** Collects the original tokens for all named options with + 'unregistered' flag set. If 'mode' is 'include_positional' + also collects all positional options. + Returns the vector of origianl tokens for all collected + options. + */ + template<class charT> + std::vector< std::basic_string<charT> > + collect_unrecognized(const std::vector< basic_option<charT> >& options, + enum collect_unrecognized_mode mode); + + /** Parse environment. + + For each environment variable, the 'name_mapper' function is called to + obtain the option name. If it returns empty string, the variable is + ignored. + + This is done since naming of environment variables is typically + different from the naming of command line options. + */ + BOOST_PROGRAM_OPTIONS_DECL parsed_options + parse_environment(const options_description&, + const function1<std::string, std::string>& name_mapper); + + /** Parse environment. + + Takes all environment variables which start with 'prefix'. The option + name is obtained from variable name by removing the prefix and + converting the remaining string into lower case. + */ + BOOST_PROGRAM_OPTIONS_DECL parsed_options + parse_environment(const options_description&, const std::string& prefix); + + /** @overload + This function exists to resolve ambiguity between the two above + functions when second argument is of 'char*' type. There's implicit + conversion to both function1 and string. + */ + BOOST_PROGRAM_OPTIONS_DECL parsed_options + parse_environment(const options_description&, const char* prefix); + + /** Splits a given string to a collection of single strings which + can be passed to command_line_parser. The second parameter is + used to specify a collection of possible seperator chars used + for splitting. The seperator is defaulted to space " ". + Splitting is done in a unix style way, with respect to quotes '"' + and escape characters '\' + */ + BOOST_PROGRAM_OPTIONS_DECL std::vector<std::string> + split_unix(const std::string& cmdline, const std::string& seperator = " \t", + const std::string& quote = "'\"", const std::string& escape = "\\"); + +#ifndef BOOST_NO_STD_WSTRING + /** @overload */ + BOOST_PROGRAM_OPTIONS_DECL std::vector<std::wstring> + split_unix(const std::wstring& cmdline, const std::wstring& seperator = L" \t", + const std::wstring& quote = L"'\"", const std::wstring& escape = L"\\"); +#endif + + #ifdef _WIN32 + /** Parses the char* string which is passed to WinMain function on + windows. This function is provided for convenience, and because it's + not clear how to portably access split command line string from + runtime library and if it always exists. + This function is available only on Windows. + */ + BOOST_PROGRAM_OPTIONS_DECL std::vector<std::string> + split_winmain(const std::string& cmdline); + +#ifndef BOOST_NO_STD_WSTRING + /** @overload */ + BOOST_PROGRAM_OPTIONS_DECL std::vector<std::wstring> + split_winmain(const std::wstring& cmdline); + #endif +#endif + + +}} + +#undef DECL + +#include "boost/program_options/detail/parsers.hpp" + +#endif diff --git a/3rdParty/Boost/src/boost/program_options/positional_options.hpp b/3rdParty/Boost/src/boost/program_options/positional_options.hpp new file mode 100644 index 0000000..01406e0 --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/positional_options.hpp @@ -0,0 +1,65 @@ +// Copyright Vladimir Prus 2004. +// 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 BOOST_PROGRAM_OPTIONS_POSITIONAL_OPTIONS_VP_2004_03_02 +#define BOOST_PROGRAM_OPTIONS_POSITIONAL_OPTIONS_VP_2004_03_02 + +#include <boost/program_options/config.hpp> + +#include <vector> +#include <string> + +namespace boost { namespace program_options { + + /** Describes positional options. + + The class allows to guess option names for positional options, which + are specified on the command line and are identified by the position. + The class uses the information provided by the user to associate a name + with every positional option, or tell that no name is known. + + The primary assumption is that only the relative order of the + positional options themselves matters, and that any interleaving + ordinary options don't affect interpretation of positional options. + + The user initializes the class by specifying that first N positional + options should be given the name X1, following M options should be given + the name X2 and so on. + */ + class BOOST_PROGRAM_OPTIONS_DECL positional_options_description { + public: + positional_options_description(); + + /** Species that up to 'max_count' next positional options + should be given the 'name'. The value of '-1' means 'unlimited'. + No calls to 'add' can be made after call with 'max_value' equal to + '-1'. + */ + positional_options_description& + add(const char* name, int max_count); + + /** Returns the maximum number of positional options that can + be present. Can return (numeric_limits<unsigned>::max)() to + indicate unlimited number. */ + unsigned max_total_count() const; + + /** Returns the name that should be associated with positional + options at 'position'. + Precondition: position < max_total_count() + */ + const std::string& name_for_position(unsigned position) const; + + private: + // List of names corresponding to the positions. If the number of + // positions is unlimited, then the last name is stored in + // m_trailing; + std::vector<std::string> m_names; + std::string m_trailing; + }; + +}} + +#endif + diff --git a/3rdParty/Boost/src/boost/program_options/value_semantic.hpp b/3rdParty/Boost/src/boost/program_options/value_semantic.hpp new file mode 100644 index 0000000..033009e --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/value_semantic.hpp @@ -0,0 +1,405 @@ +// Copyright Vladimir Prus 2004. +// 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 BOOST_VALUE_SEMANTIC_HPP_VP_2004_02_24 +#define BOOST_VALUE_SEMANTIC_HPP_VP_2004_02_24 + +#include <boost/program_options/config.hpp> +#include <boost/program_options/errors.hpp> + +#include <boost/any.hpp> +#include <boost/function/function1.hpp> +#include <boost/lexical_cast.hpp> + + +#include <string> +#include <vector> +#include <typeinfo> + +namespace boost { namespace program_options { + + /** Class which specifies how the option's value is to be parsed + and converted into C++ types. + */ + class BOOST_PROGRAM_OPTIONS_DECL value_semantic { + public: + /** Returns the name of the option. The name is only meaningful + for automatic help message. + */ + virtual std::string name() const = 0; + + /** The minimum number of tokens for this option that + should be present on the command line. */ + virtual unsigned min_tokens() const = 0; + + /** The maximum number of tokens for this option that + should be present on the command line. */ + virtual unsigned max_tokens() const = 0; + + /** Returns true if values from different sources should be composed. + Otherwise, value from the first source is used and values from + other sources are discarded. + */ + virtual bool is_composing() const = 0; + + /** Returns true if value must be given. Non-optional value + + */ + virtual bool is_required() const = 0; + + /** Parses a group of tokens that specify a value of option. + Stores the result in 'value_store', using whatever representation + is desired. May be be called several times if value of the same + option is specified more than once. + */ + virtual void parse(boost::any& value_store, + const std::vector<std::string>& new_tokens, + bool utf8) const + = 0; + + /** Called to assign default value to 'value_store'. Returns + true if default value is assigned, and false if no default + value exists. */ + virtual bool apply_default(boost::any& value_store) const = 0; + + /** Called when final value of an option is determined. + */ + virtual void notify(const boost::any& value_store) const = 0; + + virtual ~value_semantic() {} + }; + + /** Helper class which perform necessary character conversions in the + 'parse' method and forwards the data further. + */ + template<class charT> + class value_semantic_codecvt_helper { + // Nothing here. Specializations to follow. + }; + + /** Helper conversion class for values that accept ascii + strings as input. + Overrides the 'parse' method and defines new 'xparse' + method taking std::string. Depending on whether input + to parse is ascii or UTF8, will pass it to xparse unmodified, + or with UTF8->ascii conversion. + */ + template<> + class BOOST_PROGRAM_OPTIONS_DECL + value_semantic_codecvt_helper<char> : public value_semantic { + private: // base overrides + void parse(boost::any& value_store, + const std::vector<std::string>& new_tokens, + bool utf8) const; + protected: // interface for derived classes. + virtual void xparse(boost::any& value_store, + const std::vector<std::string>& new_tokens) + const = 0; + }; + + /** Helper conversion class for values that accept ascii + strings as input. + Overrides the 'parse' method and defines new 'xparse' + method taking std::wstring. Depending on whether input + to parse is ascii or UTF8, will recode input to Unicode, or + pass it unmodified. + */ + template<> + class BOOST_PROGRAM_OPTIONS_DECL + value_semantic_codecvt_helper<wchar_t> : public value_semantic { + private: // base overrides + void parse(boost::any& value_store, + const std::vector<std::string>& new_tokens, + bool utf8) const; + protected: // interface for derived classes. +#if !defined(BOOST_NO_STD_WSTRING) + virtual void xparse(boost::any& value_store, + const std::vector<std::wstring>& new_tokens) + const = 0; +#endif + }; + + /** Class which specifies a simple handling of a value: the value will + have string type and only one token is allowed. */ + class BOOST_PROGRAM_OPTIONS_DECL + untyped_value : public value_semantic_codecvt_helper<char> { + public: + untyped_value(bool zero_tokens = false) + : m_zero_tokens(zero_tokens) + {} + + std::string name() const; + + unsigned min_tokens() const; + unsigned max_tokens() const; + + bool is_composing() const { return false; } + + bool is_required() const { return false; } + + /** If 'value_store' is already initialized, or new_tokens + has more than one elements, throws. Otherwise, assigns + the first string from 'new_tokens' to 'value_store', without + any modifications. + */ + void xparse(boost::any& value_store, + const std::vector<std::string>& new_tokens) const; + + /** Does nothing. */ + bool apply_default(boost::any&) const { return false; } + + /** Does nothing. */ + void notify(const boost::any&) const {} + private: + bool m_zero_tokens; + }; + + /** Base class for all option that have a fixed type, and are + willing to announce this type to the outside world. + Any 'value_semantics' for which you want to find out the + type can be dynamic_cast-ed to typed_value_base. If conversion + succeeds, the 'type' method can be called. + */ + class typed_value_base + { + public: + // Returns the type of the value described by this + // object. + virtual const std::type_info& value_type() const = 0; + // Not really needed, since deletion from this + // class is silly, but just in case. + virtual ~typed_value_base() {} + }; + + + /** Class which handles value of a specific type. */ + template<class T, class charT = char> + class typed_value : public value_semantic_codecvt_helper<charT>, + public typed_value_base + { + public: + /** Ctor. The 'store_to' parameter tells where to store + the value when it's known. The parameter can be NULL. */ + typed_value(T* store_to) + : m_store_to(store_to), m_composing(false), + m_multitoken(false), m_zero_tokens(false), + m_required(false) + {} + + /** Specifies default value, which will be used + if none is explicitly specified. The type 'T' should + provide operator<< for ostream. + */ + typed_value* default_value(const T& v) + { + m_default_value = boost::any(v); + m_default_value_as_text = boost::lexical_cast<std::string>(v); + return this; + } + + /** Specifies default value, which will be used + if none is explicitly specified. Unlike the above overload, + the type 'T' need not provide operator<< for ostream, + but textual representation of default value must be provided + by the user. + */ + typed_value* default_value(const T& v, const std::string& textual) + { + m_default_value = boost::any(v); + m_default_value_as_text = textual; + return this; + } + + /** Specifies an implicit value, which will be used + if the option is given, but without an adjacent value. + Using this implies that an explicit value is optional, but if + given, must be strictly adjacent to the option, i.e.: '-ovalue' + or '--option=value'. Giving '-o' or '--option' will cause the + implicit value to be applied. + */ + typed_value* implicit_value(const T &v) + { + m_implicit_value = boost::any(v); + m_implicit_value_as_text = + boost::lexical_cast<std::string>(v); + return this; + } + + /** Specifies an implicit value, which will be used + if the option is given, but without an adjacent value. + Using this implies that an explicit value is optional, but if + given, must be strictly adjacent to the option, i.e.: '-ovalue' + or '--option=value'. Giving '-o' or '--option' will cause the + implicit value to be applied. + Unlike the above overload, the type 'T' need not provide + operator<< for ostream, but textual representation of default + value must be provided by the user. + */ + typed_value* implicit_value(const T &v, const std::string& textual) + { + m_implicit_value = boost::any(v); + m_implicit_value_as_text = textual; + return this; + } + + /** Specifies a function to be called when the final value + is determined. */ + typed_value* notifier(function1<void, const T&> f) + { + m_notifier = f; + return this; + } + + /** Specifies that the value is composing. See the 'is_composing' + method for explanation. + */ + typed_value* composing() + { + m_composing = true; + return this; + } + + /** Specifies that the value can span multiple tokens. */ + typed_value* multitoken() + { + m_multitoken = true; + return this; + } + + typed_value* zero_tokens() + { + m_zero_tokens = true; + return this; + } + + /** Specifies that the value must occur. */ + typed_value* required() + { + m_required = true; + return this; + } + + public: // value semantic overrides + + std::string name() const; + + bool is_composing() const { return m_composing; } + + unsigned min_tokens() const + { + if (m_zero_tokens || !m_implicit_value.empty()) { + return 0; + } else { + return 1; + } + } + + unsigned max_tokens() const { + if (m_multitoken) { + return 32000; + } else if (m_zero_tokens) { + return 0; + } else { + return 1; + } + } + + bool is_required() const { return m_required; } + + /** Creates an instance of the 'validator' class and calls + its operator() to perform the actual conversion. */ + void xparse(boost::any& value_store, + const std::vector< std::basic_string<charT> >& new_tokens) + const; + + /** If default value was specified via previous call to + 'default_value', stores that value into 'value_store'. + Returns true if default value was stored. + */ + virtual bool apply_default(boost::any& value_store) const + { + if (m_default_value.empty()) { + return false; + } else { + value_store = m_default_value; + return true; + } + } + + /** If an address of variable to store value was specified + when creating *this, stores the value there. Otherwise, + does nothing. */ + void notify(const boost::any& value_store) const; + + public: // typed_value_base overrides + + const std::type_info& value_type() const + { + return typeid(T); + } + + + private: + T* m_store_to; + + // Default value is stored as boost::any and not + // as boost::optional to avoid unnecessary instantiations. + boost::any m_default_value; + std::string m_default_value_as_text; + boost::any m_implicit_value; + std::string m_implicit_value_as_text; + bool m_composing, m_implicit, m_multitoken, m_zero_tokens, m_required; + boost::function1<void, const T&> m_notifier; + }; + + + /** Creates a typed_value<T> instance. This function is the primary + method to create value_semantic instance for a specific type, which + can later be passed to 'option_description' constructor. + The second overload is used when it's additionally desired to store the + value of option into program variable. + */ + template<class T> + typed_value<T>* + value(); + + /** @overload + */ + template<class T> + typed_value<T>* + value(T* v); + + /** Creates a typed_value<T> instance. This function is the primary + method to create value_semantic instance for a specific type, which + can later be passed to 'option_description' constructor. + */ + template<class T> + typed_value<T, wchar_t>* + wvalue(); + + /** @overload + */ + template<class T> + typed_value<T, wchar_t>* + wvalue(T* v); + + /** Works the same way as the 'value<bool>' function, but the created + value_semantic won't accept any explicit value. So, if the option + is present on the command line, the value will be 'true'. + */ + BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>* + bool_switch(); + + /** @overload + */ + BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>* + bool_switch(bool* v); + +}} + +#include "boost/program_options/detail/value_semantic.hpp" + +#endif + diff --git a/3rdParty/Boost/src/boost/program_options/variables_map.hpp b/3rdParty/Boost/src/boost/program_options/variables_map.hpp new file mode 100644 index 0000000..02c4af2 --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/variables_map.hpp @@ -0,0 +1,206 @@ +// Copyright Vladimir Prus 2002-2004. +// 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 BOOST_VARIABLES_MAP_VP_2003_05_19 +#define BOOST_VARIABLES_MAP_VP_2003_05_19 + +#include <boost/program_options/config.hpp> + +#include <boost/any.hpp> +#include <boost/shared_ptr.hpp> + +#include <string> +#include <map> +#include <set> + +namespace boost { namespace program_options { + + template<class charT> + class basic_parsed_options; + + class value_semantic; + class variables_map; + + // forward declaration + + /** Stores in 'm' all options that are defined in 'options'. + If 'm' already has a non-defaulted value of an option, that value + is not changed, even if 'options' specify some value. + */ + BOOST_PROGRAM_OPTIONS_DECL + void store(const basic_parsed_options<char>& options, variables_map& m, + bool utf8 = false); + + /** Stores in 'm' all options that are defined in 'options'. + If 'm' already has a non-defaulted value of an option, that value + is not changed, even if 'options' specify some value. + This is wide character variant. + */ + BOOST_PROGRAM_OPTIONS_DECL + void store(const basic_parsed_options<wchar_t>& options, + variables_map& m); + + + /** Runs all 'notify' function for options in 'm'. */ + BOOST_PROGRAM_OPTIONS_DECL void notify(variables_map& m); + + /** Class holding value of option. Contains details about how the + value is set and allows to conveniently obtain the value. + */ + class BOOST_PROGRAM_OPTIONS_DECL variable_value { + public: + variable_value() : m_defaulted(false) {} + variable_value(const boost::any& v, bool defaulted) + : v(v), m_defaulted(defaulted) + {} + + /** If stored value if of type T, returns that value. Otherwise, + throws boost::bad_any_cast exception. */ + template<class T> + const T& as() const { + return boost::any_cast<const T&>(v); + } + /** @overload */ + template<class T> + T& as() { + return boost::any_cast<T&>(v); + } + + /// Returns true if no value is stored. + bool empty() const; + /** Returns true if the value was not explicitly + given, but has default value. */ + bool defaulted() const; + /** Returns the contained value. */ + const boost::any& value() const; + + /** Returns the contained value. */ + boost::any& value(); + private: + boost::any v; + bool m_defaulted; + // Internal reference to value semantic. We need to run + // notifications when *final* values of options are known, and + // they are known only after all sources are stored. By that + // time options_description for the first source might not + // be easily accessible, so we need to store semantic here. + shared_ptr<const value_semantic> m_value_semantic; + + friend BOOST_PROGRAM_OPTIONS_DECL + void store(const basic_parsed_options<char>& options, + variables_map& m, bool); + + friend BOOST_PROGRAM_OPTIONS_DECL class variables_map; + }; + + /** Implements string->string mapping with convenient value casting + facilities. */ + class BOOST_PROGRAM_OPTIONS_DECL abstract_variables_map { + public: + abstract_variables_map(); + abstract_variables_map(const abstract_variables_map* next); + + virtual ~abstract_variables_map() {} + + /** Obtains the value of variable 'name', from *this and + possibly from the chain of variable maps. + + - if there's no value in *this. + - if there's next variable map, returns value from it + - otherwise, returns empty value + + - if there's defaulted value + - if there's next varaible map, which has a non-defauled + value, return that + - otherwise, return value from *this + + - if there's a non-defauled value, returns it. + */ + const variable_value& operator[](const std::string& name) const; + + /** Sets next variable map, which will be used to find + variables not found in *this. */ + void next(abstract_variables_map* next); + + private: + /** Returns value of variable 'name' stored in *this, or + empty value otherwise. */ + virtual const variable_value& get(const std::string& name) const = 0; + + const abstract_variables_map* m_next; + }; + + /** Concrete variables map which store variables in real map. + + This class is derived from std::map<std::string, variable_value>, + so you can use all map operators to examine its content. + */ + class BOOST_PROGRAM_OPTIONS_DECL variables_map : public abstract_variables_map, + public std::map<std::string, variable_value> + { + public: + variables_map(); + variables_map(const abstract_variables_map* next); + + // Resolve conflict between inherited operators. + const variable_value& operator[](const std::string& name) const + { return abstract_variables_map::operator[](name); } + + void notify(); + + private: + /** Implementation of abstract_variables_map::get + which does 'find' in *this. */ + const variable_value& get(const std::string& name) const; + + /** Names of option with 'final' values -- which should not + be changed by subsequence assignments. */ + std::set<std::string> m_final; + + friend BOOST_PROGRAM_OPTIONS_DECL + void store(const basic_parsed_options<char>& options, + variables_map& xm, + bool utf8); + + /** Names of required options, filled by parser which has + access to options_description. */ + std::set<std::string> m_required; + }; + + + /* + * Templates/inlines + */ + + inline bool + variable_value::empty() const + { + return v.empty(); + } + + inline bool + variable_value::defaulted() const + { + return m_defaulted; + } + + inline + const boost::any& + variable_value::value() const + { + return v; + } + + inline + boost::any& + variable_value::value() + { + return v; + } + +}} + +#endif diff --git a/3rdParty/Boost/src/boost/program_options/version.hpp b/3rdParty/Boost/src/boost/program_options/version.hpp new file mode 100644 index 0000000..7480943 --- /dev/null +++ b/3rdParty/Boost/src/boost/program_options/version.hpp @@ -0,0 +1,19 @@ +// Copyright Vladimir Prus 2004. +// 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 BOOST_PROGRAM_OPTIONS_VERSION_HPP_VP_2004_04_05 +#define BOOST_PROGRAM_OPTIONS_VERSION_HPP_VP_2004_04_05 + +/** The version of the source interface. + The value will be incremented whenever a change is made which might + cause compilation errors for existing code. +*/ +#ifdef BOOST_PROGRAM_OPTIONS_VERSION +#error BOOST_PROGRAM_OPTIONS_VERSION already defined +#endif +#define BOOST_PROGRAM_OPTIONS_VERSION 2 + + +#endif diff --git a/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp b/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp new file mode 100644 index 0000000..be31385 --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp @@ -0,0 +1,656 @@ +// Copyright Vladimir Prus 2002-2004. +// 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) + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> + +#include <boost/config.hpp> + +#include <boost/program_options/detail/cmdline.hpp> +#include <boost/program_options/errors.hpp> +#include <boost/program_options/value_semantic.hpp> +#include <boost/program_options/options_description.hpp> +#include <boost/program_options/positional_options.hpp> +#include <boost/throw_exception.hpp> + +#include <boost/bind.hpp> + +#include <string> +#include <utility> +#include <vector> +#include <cassert> +#include <cstring> +#include <cctype> +#include <climits> + +#include <cstdio> + +#include <iostream> + +namespace boost { namespace program_options { + + using namespace std; + using namespace boost::program_options::command_line_style; + + invalid_syntax:: + invalid_syntax(const string& tokens, kind_t kind) + : error(error_message(kind).append(" in '").append(tokens).append("'")) + , m_tokens(tokens) + , m_kind(kind) + {} + + string + invalid_syntax::error_message(kind_t kind) + { + // Initially, store the message in 'const char*' variable, + // to avoid conversion to string in all cases. + const char* msg; + switch(kind) + { + case long_not_allowed: + msg = "long options are not allowed"; + break; + case long_adjacent_not_allowed: + msg = "parameters adjacent to long options not allowed"; + break; + case short_adjacent_not_allowed: + msg = "parameters adjust to short options are not allowed"; + break; + case empty_adjacent_parameter: + msg = "adjacent parameter is empty"; + break; + case missing_parameter: + msg = "required parameter is missing"; + break; + case extra_parameter: + msg = "extra parameter"; + break; + case unrecognized_line: + msg = "unrecognized line"; + break; + default: + msg = "unknown error"; + } + return msg; + } + + invalid_syntax::kind_t + invalid_syntax::kind() const + { + return m_kind; + } + + const string& + invalid_syntax::tokens() const + { + return m_tokens; + } + + invalid_command_line_syntax:: + invalid_command_line_syntax(const string& tokens, kind_t kind) + : invalid_syntax(tokens, kind) + {} + +}} + + +namespace boost { namespace program_options { namespace detail { + + // vc6 needs this, but borland chokes when this is added. +#if BOOST_WORKAROUND(_MSC_VER, < 1300) + using namespace std; + using namespace program_options; +#endif + + + cmdline::cmdline(const vector<string>& args) + { + init(args); + } + + cmdline::cmdline(int argc, const char*const * argv) + { +#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS) + vector<string> args; + copy(argv+1, argv+argc+!argc, inserter(args, args.end())); + init(args); +#else + init(vector<string>(argv+1, argv+argc+!argc)); +#endif + } + + void + cmdline::init(const vector<string>& args) + { + this->args = args; + m_style = command_line_style::default_style; + m_desc = 0; + m_positional = 0; + m_allow_unregistered = false; + } + + void + cmdline::style(int style) + { + if (style == 0) + style = default_style; + + check_style(style); + this->m_style = style_t(style); + } + + void + cmdline::allow_unregistered() + { + this->m_allow_unregistered = true; + } + + void + cmdline::check_style(int style) const + { + bool allow_some_long = + (style & allow_long) || (style & allow_long_disguise); + + const char* error = 0; + if (allow_some_long && + !(style & long_allow_adjacent) && !(style & long_allow_next)) + error = "style disallows parameters for long options"; + + if (!error && (style & allow_short) && + !(style & short_allow_adjacent) && !(style & short_allow_next)) + error = "style disallows parameters for short options"; + + if (!error && (style & allow_short) && + !(style & allow_dash_for_short) && !(style & allow_slash_for_short)) + error = "style disallows all characters for short options"; + + if (error) + boost::throw_exception(invalid_command_line_style(error)); + + // Need to check that if guessing and long disguise are enabled + // -f will mean the same as -foo + } + + bool + cmdline::is_style_active(style_t style) const + { + return ((m_style & style) ? true : false); + } + + void + cmdline::set_options_description(const options_description& desc) + { + m_desc = &desc; + } + + void + cmdline::set_positional_options( + const positional_options_description& positional) + { + m_positional = &positional; + } + + + vector<option> + cmdline::run() + { + // The parsing is done by having a set of 'style parsers' + // and trying then in order. Each parser is passed a vector + // of unparsed tokens and can consume some of them (by + // removing elements on front) and return a vector of options. + // + // We try each style parser in turn, untill some input + // is consumed. The returned vector of option may contain the + // result of just syntactic parsing of token, say --foo will + // be parsed as option with name 'foo', and the style parser + // is not required to care if that option is defined, and how + // many tokens the value may take. + // So, after vector is returned, we validate them. + assert(m_desc); + + vector<style_parser> style_parsers; + + if (m_style_parser) + style_parsers.push_back(m_style_parser); + + if (m_additional_parser) + style_parsers.push_back( + boost::bind(&cmdline::handle_additional_parser, this, _1)); + + if (m_style & allow_long) + style_parsers.push_back( + boost::bind(&cmdline::parse_long_option, this, _1)); + + if ((m_style & allow_long_disguise)) + style_parsers.push_back( + boost::bind(&cmdline::parse_disguised_long_option, this, _1)); + + if ((m_style & allow_short) && (m_style & allow_dash_for_short)) + style_parsers.push_back( + boost::bind(&cmdline::parse_short_option, this, _1)); + + if ((m_style & allow_short) && (m_style & allow_slash_for_short)) + style_parsers.push_back(boost::bind(&cmdline::parse_dos_option, this, _1)); + + style_parsers.push_back(boost::bind(&cmdline::parse_terminator, this, _1)); + + vector<option> result; + while(!args.empty()) + { + bool ok = false; + for(unsigned i = 0; i < style_parsers.size(); ++i) + { + unsigned current_size = args.size(); + vector<option> next = style_parsers[i](args); + + // Check that option names + // are valid, and that all values are in place. + if (!next.empty()) + { + vector<string> e; + for(unsigned k = 0; k < next.size()-1; ++k) { + finish_option(next[k], e, style_parsers); + } + // For the last option, pass the unparsed tokens + // so that they can be added to next.back()'s values + // if appropriate. + finish_option(next.back(), args, style_parsers); + for (unsigned j = 0; j < next.size(); ++j) + result.push_back(next[j]); + } + + if (args.size() != current_size) { + ok = true; + break; + } + } + + if (!ok) { + option opt; + opt.value.push_back(args[0]); + opt.original_tokens.push_back(args[0]); + result.push_back(opt); + args.erase(args.begin()); + } + } + + /* If an key option is followed by a positional option, + can can consume more tokens (e.g. it's multitoke option), + give those tokens to it. */ + vector<option> result2; + for (unsigned i = 0; i < result.size(); ++i) + { + result2.push_back(result[i]); + option& opt = result2.back(); + + if (opt.string_key.empty()) + continue; + + const option_description* xd = + m_desc->find_nothrow(opt.string_key, + is_style_active(allow_guessing), + is_style_active(long_case_insensitive), + is_style_active(short_case_insensitive)); + if (!xd) + continue; + + unsigned min_tokens = xd->semantic()->min_tokens(); + unsigned max_tokens = xd->semantic()->max_tokens(); + if (min_tokens < max_tokens && opt.value.size() < max_tokens) + { + // This option may grab some more tokens. + // We only allow to grab tokens that are not already + // recognized as key options. + + int can_take_more = max_tokens - opt.value.size(); + unsigned j = i+1; + for (; can_take_more && j < result.size(); --can_take_more, ++j) + { + option& opt2 = result[j]; + if (!opt2.string_key.empty()) + break; + + if (opt2.position_key == INT_MAX) + { + // We use INT_MAX to mark positional options that + // were found after the '--' terminator and therefore + // should stay positional forever. + break; + } + + assert(opt2.value.size() == 1); + + opt.value.push_back(opt2.value[0]); + + assert(opt2.original_tokens.size() == 1); + + opt.original_tokens.push_back(opt2.original_tokens[0]); + } + i = j-1; + } + } + result.swap(result2); + + + // Assign position keys to positional options. + int position_key = 0; + for(unsigned i = 0; i < result.size(); ++i) { + if (result[i].string_key.empty()) + result[i].position_key = position_key++; + } + + if (m_positional) + { + unsigned position = 0; + for (unsigned i = 0; i < result.size(); ++i) { + option& opt = result[i]; + if (opt.position_key != -1) { + if (position >= m_positional->max_total_count()) + { + boost::throw_exception(too_many_positional_options_error()); + } + opt.string_key = m_positional->name_for_position(position); + ++position; + } + } + } + + // set case sensitive flag + for (unsigned i = 0; i < result.size(); ++i) { + if (result[i].string_key.size() > 2 || + (result[i].string_key.size() > 1 && result[i].string_key[0] != '-')) + { + // it is a long option + result[i].case_insensitive = is_style_active(long_case_insensitive); + } + else + { + // it is a short option + result[i].case_insensitive = is_style_active(short_case_insensitive); + } + } + + return result; + } + + void + cmdline::finish_option(option& opt, + vector<string>& other_tokens, + const vector<style_parser>& style_parsers) + { + if (opt.string_key.empty()) + return; + + // First check that the option is valid, and get its description. + const option_description* xd = m_desc->find_nothrow(opt.string_key, + is_style_active(allow_guessing), + is_style_active(long_case_insensitive), + is_style_active(short_case_insensitive)); + + if (!xd) + { + if (m_allow_unregistered) { + opt.unregistered = true; + return; + } else { + boost::throw_exception(unknown_option(opt.string_key)); + } + } + const option_description& d = *xd; + + // Canonize the name + opt.string_key = d.key(opt.string_key); + + // We check that the min/max number of tokens for the option + // agrees with the number of tokens we have. The 'adjacent_value' + // (the value in --foo=1) counts as a separate token, and if present + // must be consumed. The following tokens on the command line may be + // left unconsumed. + + // We don't check if those tokens look like option, or not! + + unsigned min_tokens = d.semantic()->min_tokens(); + unsigned max_tokens = d.semantic()->max_tokens(); + + unsigned present_tokens = opt.value.size() + other_tokens.size(); + + if (present_tokens >= min_tokens) + { + if (!opt.value.empty() && max_tokens == 0) + { + boost::throw_exception(invalid_command_line_syntax(opt.string_key, + invalid_command_line_syntax::extra_parameter)); + } + + // If an option wants, at minimum, N tokens, we grab them there, + // when adding these tokens as values to current option we check + // if they look like options + if (opt.value.size() <= min_tokens) + { + min_tokens -= opt.value.size(); + } + else + { + min_tokens = 0; + } + + // Everything's OK, move the values to the result. + for(;!other_tokens.empty() && min_tokens--; ) + { + // check if extra parameter looks like a known option + // we use style parsers to check if it is syntactically an option, + // additionally we check if an option_description exists + vector<option> followed_option; + vector<string> next_token(1, other_tokens[0]); + for (unsigned i = 0; followed_option.empty() && i < style_parsers.size(); ++i) + { + followed_option = style_parsers[i](next_token); + } + if (!followed_option.empty()) + { + const option_description* od = m_desc->find_nothrow(other_tokens[0], + is_style_active(allow_guessing), + is_style_active(long_case_insensitive), + is_style_active(short_case_insensitive)); + if (od) + boost::throw_exception(invalid_command_line_syntax(opt.string_key, + invalid_command_line_syntax::missing_parameter)); + } + opt.value.push_back(other_tokens[0]); + opt.original_tokens.push_back(other_tokens[0]); + other_tokens.erase(other_tokens.begin()); + } + } + else + { + boost::throw_exception(invalid_command_line_syntax(opt.string_key, + invalid_command_line_syntax::missing_parameter)); + + } + } + + vector<option> + cmdline::parse_long_option(vector<string>& args) + { + vector<option> result; + const string& tok = args[0]; + if (tok.size() >= 3 && tok[0] == '-' && tok[1] == '-') + { + string name, adjacent; + + string::size_type p = tok.find('='); + if (p != tok.npos) + { + name = tok.substr(2, p-2); + adjacent = tok.substr(p+1); + if (adjacent.empty()) + boost::throw_exception( invalid_command_line_syntax(name, + invalid_command_line_syntax::empty_adjacent_parameter) ); + } + else + { + name = tok.substr(2); + } + option opt; + opt.string_key = name; + if (!adjacent.empty()) + opt.value.push_back(adjacent); + opt.original_tokens.push_back(tok); + result.push_back(opt); + args.erase(args.begin()); + } + return result; + } + + + vector<option> + cmdline::parse_short_option(vector<string>& args) + { + const string& tok = args[0]; + if (tok.size() >= 2 && tok[0] == '-' && tok[1] != '-') + { + vector<option> result; + + string name = tok.substr(0,2); + string adjacent = tok.substr(2); + + // Short options can be 'grouped', so that + // "-d -a" becomes "-da". Loop, processing one + // option at a time. We exit the loop when either + // we've processed all the token, or when the remainder + // of token is considered to be value, not further grouped + // option. + for(;;) { + const option_description* d + = m_desc->find_nothrow(name, false, false, + is_style_active(short_case_insensitive)); + + // FIXME: check for 'allow_sticky'. + if (d && (m_style & allow_sticky) && + d->semantic()->max_tokens() == 0 && !adjacent.empty()) { + // 'adjacent' is in fact further option. + option opt; + opt.string_key = name; + result.push_back(opt); + + if (adjacent.empty()) + { + args.erase(args.begin()); + break; + } + + name = string("-") + adjacent[0]; + adjacent.erase(adjacent.begin()); + } else { + + option opt; + opt.string_key = name; + opt.original_tokens.push_back(tok); + if (!adjacent.empty()) + opt.value.push_back(adjacent); + result.push_back(opt); + args.erase(args.begin()); + break; + } + } + return result; + } + return vector<option>(); + } + + vector<option> + cmdline::parse_dos_option(vector<string>& args) + { + vector<option> result; + const string& tok = args[0]; + if (tok.size() >= 2 && tok[0] == '/') + { + string name = "-" + tok.substr(1,1); + string adjacent = tok.substr(2); + + option opt; + opt.string_key = name; + if (!adjacent.empty()) + opt.value.push_back(adjacent); + opt.original_tokens.push_back(tok); + result.push_back(opt); + args.erase(args.begin()); + } + return result; + } + + vector<option> + cmdline::parse_disguised_long_option(vector<string>& args) + { + const string& tok = args[0]; + if (tok.size() >= 2 && + ((tok[0] == '-' && tok[1] != '-') || + ((m_style & allow_slash_for_short) && tok[0] == '/'))) + { + if (m_desc->find_nothrow(tok.substr(1, tok.find('=')-1), + is_style_active(allow_guessing), + is_style_active(long_case_insensitive), + is_style_active(short_case_insensitive))) + { + args[0].insert(0, "-"); + if (args[0][1] == '/') + args[0][1] = '-'; + return parse_long_option(args); + } + } + return vector<option>(); + } + + vector<option> + cmdline::parse_terminator(vector<string>& args) + { + vector<option> result; + const string& tok = args[0]; + if (tok == "--") + { + for(unsigned i = 1; i < args.size(); ++i) + { + option opt; + opt.value.push_back(args[i]); + opt.original_tokens.push_back(args[i]); + opt.position_key = INT_MAX; + result.push_back(opt); + } + args.clear(); + } + return result; + } + + vector<option> + cmdline::handle_additional_parser(vector<string>& args) + { + vector<option> result; + pair<string, string> r = m_additional_parser(args[0]); + if (!r.first.empty()) { + option next; + next.string_key = r.first; + if (!r.second.empty()) + next.value.push_back(r.second); + result.push_back(next); + args.erase(args.begin()); + } + return result; + } + + void + cmdline::set_additional_parser(additional_parser p) + { + m_additional_parser = p; + } + + void + cmdline::extra_style_parser(style_parser s) + { + m_style_parser = s; + } + + + +}}} diff --git a/3rdParty/Boost/src/libs/program_options/src/config_file.cpp b/3rdParty/Boost/src/libs/program_options/src/config_file.cpp new file mode 100644 index 0000000..a12844c --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/config_file.cpp @@ -0,0 +1,196 @@ +// Copyright Vladimir Prus 2002-2004. +// 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) + + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> + +#include <boost/program_options/detail/config_file.hpp> +#include <boost/program_options/errors.hpp> +#include <boost/program_options/detail/convert.hpp> +#include <boost/throw_exception.hpp> + +#include <iostream> +#include <fstream> +#include <cassert> + +namespace boost { namespace program_options { namespace detail { + + using namespace std; + + common_config_file_iterator::common_config_file_iterator( + const std::set<std::string>& allowed_options, + bool allow_unregistered) + : allowed_options(allowed_options), + m_allow_unregistered(allow_unregistered) + { + for(std::set<std::string>::const_iterator i = allowed_options.begin(); + i != allowed_options.end(); + ++i) + { + add_option(i->c_str()); + } + } + + void + common_config_file_iterator::add_option(const char* name) + { + string s(name); + assert(!s.empty()); + if (*s.rbegin() == '*') { + s.resize(s.size()-1); + bool bad_prefixes(false); + // If 's' is a prefix of one of allowed suffix, then + // lower_bound will return that element. + // If some element is prefix of 's', then lower_bound will + // return the next element. + set<string>::iterator i = allowed_prefixes.lower_bound(s); + if (i != allowed_prefixes.end()) { + if (i->find(s) == 0) + bad_prefixes = true; + } + if (i != allowed_prefixes.begin()) { + --i; + if (s.find(*i) == 0) + bad_prefixes = true; + } + if (bad_prefixes) + boost::throw_exception(error("bad prefixes")); + allowed_prefixes.insert(s); + } + } + + namespace { + string trim_ws(const string& s) + { + string::size_type n, n2; + n = s.find_first_not_of(" \t\r\n"); + if (n == string::npos) + return string(); + else { + n2 = s.find_last_not_of(" \t\r\n"); + return s.substr(n, n2-n+1); + } + } + } + + + void common_config_file_iterator::get() + { + string s; + string::size_type n; + bool found = false; + + while(this->getline(s)) { + + // strip '#' comments and whitespace + if ((n = s.find('#')) != string::npos) + s = s.substr(0, n); + s = trim_ws(s); + + if (!s.empty()) { + // Handle section name + if (*s.begin() == '[' && *s.rbegin() == ']') { + m_prefix = s.substr(1, s.size()-2); + if (*m_prefix.rbegin() != '.') + m_prefix += '.'; + } + else if ((n = s.find('=')) != string::npos) { + + string name = m_prefix + trim_ws(s.substr(0, n)); + string value = trim_ws(s.substr(n+1)); + + bool registered = allowed_option(name); + if (!registered && !m_allow_unregistered) + boost::throw_exception(unknown_option(name)); + + found = true; + this->value().string_key = name; + this->value().value.clear(); + this->value().value.push_back(value); + this->value().unregistered = !registered; + this->value().original_tokens.clear(); + this->value().original_tokens.push_back(name); + this->value().original_tokens.push_back(value); + break; + + } else { + boost::throw_exception(invalid_syntax(s, invalid_syntax::unrecognized_line)); + } + } + } + if (!found) + found_eof(); + } + + + bool + common_config_file_iterator::allowed_option(const std::string& s) const + { + set<string>::const_iterator i = allowed_options.find(s); + if (i != allowed_options.end()) + return true; + // If s is "pa" where "p" is allowed prefix then + // lower_bound should find the element after "p". + // This depends on 'allowed_prefixes' invariant. + i = allowed_prefixes.lower_bound(s); + if (i != allowed_prefixes.begin() && s.find(*--i) == 0) + return true; + return false; + } + +#if BOOST_WORKAROUND(__COMO_VERSION__, BOOST_TESTED_AT(4303)) || \ + (defined(__sgi) && BOOST_WORKAROUND(_COMPILER_VERSION, BOOST_TESTED_AT(741))) + template<> + bool + basic_config_file_iterator<wchar_t>::getline(std::string& s) + { + std::wstring ws; + // On Comeau, using two-argument version causes + // call to some internal function with std::wstring, and '\n' + // (not L'\n') and compile can't resolve that call. + + if (std::getline(*is, ws, L'\n')) { + s = to_utf8(ws); + return true; + } else { + return false; + } + } +#endif + +}}} + +#if 0 +using boost::program_options::config_file; + +#include <sstream> +#include <cassert> + +int main() +{ + try { + stringstream s( + "a = 1\n" + "b = 2\n"); + + config_file cf(s); + cf.add_option("a"); + cf.add_option("b"); + + assert(++cf); + assert(cf.name() == "a"); + assert(cf.value() == "1"); + assert(++cf); + assert(cf.name() == "b"); + assert(cf.value() == "2"); + assert(!++cf); + } + catch(exception& e) + { + cout << e.what() << "\n"; + } +} +#endif diff --git a/3rdParty/Boost/src/libs/program_options/src/convert.cpp b/3rdParty/Boost/src/libs/program_options/src/convert.cpp new file mode 100644 index 0000000..9be759e --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/convert.cpp @@ -0,0 +1,161 @@ +// Copyright Vladimir Prus 2004. +// 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) + +#include <fstream> +#include <locale.h> +#include <locale> +#include <iostream> +#include <string> +#include <locale> +#include <stdexcept> + +#include <boost/config.hpp> + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> +#include <boost/program_options/detail/convert.hpp> +#include <boost/program_options/detail/utf8_codecvt_facet.hpp> +#include <boost/throw_exception.hpp> + +#include <boost/bind.hpp> + +using namespace std; + +namespace boost { namespace detail { + + /* Internal function to actually perform conversion. + The logic in from_8_bit and to_8_bit function is exactly + the same, except that one calls 'in' method of codecvt and another + calls the 'out' method, and that syntax difference makes straightforward + template implementation impossible. + + This functions takes a 'fun' argument, which should have the same + parameters and return type and the in/out methods. The actual converting + function will pass functional objects created with boost::bind. + Experiments show that the performance loss is less than 10%. + */ + template<class ToChar, class FromChar, class Fun> + std::basic_string<ToChar> + convert(const std::basic_string<FromChar>& s, Fun fun) + + { + std::basic_string<ToChar> result; + + std::mbstate_t state = std::mbstate_t(); + + const FromChar* from = s.data(); + const FromChar* from_end = s.data() + s.size(); + // The interface of cvt is not really iterator-like, and it's + // not possible the tell the required output size without the conversion. + // All we can is convert data by pieces. + while(from != from_end) { + + // std::basic_string does not provide non-const pointers to the data, + // so converting directly into string is not possible. + ToChar buffer[32]; + + ToChar* to_next = buffer; + // Need variable because boost::bind doesn't work with rvalues. + ToChar* to_end = buffer + 32; + std::codecvt_base::result r = + fun(state, from, from_end, from, buffer, to_end, to_next); + + if (r == std::codecvt_base::error) + boost::throw_exception( + std::logic_error("character conversion failed")); + // 'partial' is not an error, it just means not all source + // characters were converted. However, we need to check that at + // least one new target character was produced. If not, it means + // the source data is incomplete, and since we don't have extra + // data to add to source, it's error. + if (to_next == buffer) + boost::throw_exception( + std::logic_error("character conversion failed")); + + // Add converted characters + result.append(buffer, to_next); + } + + return result; + } +}} + +namespace boost { + +#ifndef BOOST_NO_STD_WSTRING + BOOST_PROGRAM_OPTIONS_DECL std::wstring + from_8_bit(const std::string& s, + const std::codecvt<wchar_t, char, std::mbstate_t>& cvt) + { + return detail::convert<wchar_t>( + s, + boost::bind(&std::codecvt<wchar_t, char, mbstate_t>::in, + &cvt, + _1, _2, _3, _4, _5, _6, _7)); + } + + BOOST_PROGRAM_OPTIONS_DECL std::string + to_8_bit(const std::wstring& s, + const std::codecvt<wchar_t, char, std::mbstate_t>& cvt) + { + return detail::convert<char>( + s, + boost::bind(&codecvt<wchar_t, char, mbstate_t>::out, + &cvt, + _1, _2, _3, _4, _5, _6, _7)); + } + + + namespace { + boost::program_options::detail::utf8_codecvt_facet + utf8_facet; + } + + BOOST_PROGRAM_OPTIONS_DECL std::wstring + from_utf8(const std::string& s) + { + return from_8_bit(s, utf8_facet); + } + + BOOST_PROGRAM_OPTIONS_DECL std::string + to_utf8(const std::wstring& s) + { + return to_8_bit(s, utf8_facet); + } + + BOOST_PROGRAM_OPTIONS_DECL std::wstring + from_local_8_bit(const std::string& s) + { + typedef codecvt<wchar_t, char, mbstate_t> facet_type; + return from_8_bit(s, + BOOST_USE_FACET(facet_type, locale())); + } + + BOOST_PROGRAM_OPTIONS_DECL std::string + to_local_8_bit(const std::wstring& s) + { + typedef codecvt<wchar_t, char, mbstate_t> facet_type; + return to_8_bit(s, + BOOST_USE_FACET(facet_type, locale())); + } +#endif + + namespace program_options + { + BOOST_PROGRAM_OPTIONS_DECL std::string to_internal(const std::string& s) + { + return s; + } + +#ifndef BOOST_NO_STD_WSTRING + BOOST_PROGRAM_OPTIONS_DECL std::string to_internal(const std::wstring& s) + { + return to_utf8(s); + } +#endif + } + + +} diff --git a/3rdParty/Boost/src/libs/program_options/src/options_description.cpp b/3rdParty/Boost/src/libs/program_options/src/options_description.cpp new file mode 100644 index 0000000..bfd113d --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/options_description.cpp @@ -0,0 +1,621 @@ +// Copyright Vladimir Prus 2002-2004. +// Copyright Bertolt Mildner 2004. +// 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) + + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> +#include <boost/program_options/options_description.hpp> +// FIXME: this is only to get multiple_occurences class +// should move that to a separate headers. +#include <boost/program_options/parsers.hpp> + + +#include <boost/lexical_cast.hpp> +#include <boost/tokenizer.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/throw_exception.hpp> + +#include <cassert> +#include <climits> +#include <cstring> +#include <cstdarg> +#include <sstream> +#include <iterator> +using namespace std; + +namespace boost { namespace program_options { + + namespace { + + template< class charT > + std::basic_string< charT > tolower_(const std::basic_string< charT >& str) + { + std::basic_string< charT > result; + for (typename std::basic_string< charT >::size_type i = 0; i < str.size(); ++i) + { + result.append(1, static_cast< charT >(std::tolower(str[i]))); + } + return result; + } + + } // unnamed namespace + + + option_description::option_description() + { + } + + option_description:: + option_description(const char* name, + const value_semantic* s) + : m_value_semantic(s) + { + this->set_name(name); + } + + + option_description:: + option_description(const char* name, + const value_semantic* s, + const char* description) + : m_description(description), m_value_semantic(s) + { + this->set_name(name); + } + + option_description::~option_description() + { + } + + option_description::match_result + option_description::match(const std::string& option, + bool approx, + bool long_ignore_case, + bool short_ignore_case) const + { + match_result result = no_match; + + std::string local_long_name((long_ignore_case ? tolower_(m_long_name) : m_long_name)); + + if (!local_long_name.empty()) { + + std::string local_option = (long_ignore_case ? tolower_(option) : option); + + if (*local_long_name.rbegin() == '*') + { + // The name ends with '*'. Any specified name with the given + // prefix is OK. + if (local_option.find(local_long_name.substr(0, local_long_name.length()-1)) + == 0) + result = approximate_match; + } + + if (local_long_name == local_option) + { + result = full_match; + } + else if (approx) + { + if (local_long_name.find(local_option) == 0) + { + result = approximate_match; + } + } + } + + if (result != full_match) + { + std::string local_option(short_ignore_case ? tolower_(option) : option); + std::string local_short_name(short_ignore_case ? tolower_(m_short_name) : m_short_name); + + if (local_short_name == local_option) + { + result = full_match; + } + } + + return result; + } + + const std::string& + option_description::key(const std::string& option) const + { + if (!m_long_name.empty()) + if (m_long_name.find('*') != string::npos) + // The '*' character means we're long_name + // matches only part of the input. So, returning + // long name will remove some of the information, + // and we have to return the option as specified + // in the source. + return option; + else + return m_long_name; + else + return m_short_name; + } + + const std::string& + option_description::long_name() const + { + return m_long_name; + } + + option_description& + option_description::set_name(const char* _name) + { + std::string name(_name); + string::size_type n = name.find(','); + if (n != string::npos) { + assert(n == name.size()-2); + m_long_name = name.substr(0, n); + m_short_name = '-' + name.substr(n+1,1); + } else { + m_long_name = name; + } + return *this; + } + + const std::string& + option_description::description() const + { + return m_description; + } + + shared_ptr<const value_semantic> + option_description::semantic() const + { + return m_value_semantic; + } + + std::string + option_description::format_name() const + { + if (!m_short_name.empty()) + return string(m_short_name).append(" [ --"). + append(m_long_name).append(" ]"); + else + return string("--").append(m_long_name); + } + + std::string + option_description::format_parameter() const + { + if (m_value_semantic->max_tokens() != 0) + return m_value_semantic->name(); + else + return ""; + } + + options_description_easy_init:: + options_description_easy_init(options_description* owner) + : owner(owner) + {} + + options_description_easy_init& + options_description_easy_init:: + operator()(const char* name, + const char* description) + { + // Create untypes semantic which accepts zero tokens: i.e. + // no value can be specified on command line. + // FIXME: does not look exception-safe + shared_ptr<option_description> d( + new option_description(name, new untyped_value(true), description)); + + owner->add(d); + return *this; + } + + options_description_easy_init& + options_description_easy_init:: + operator()(const char* name, + const value_semantic* s) + { + shared_ptr<option_description> d(new option_description(name, s)); + owner->add(d); + return *this; + } + + options_description_easy_init& + options_description_easy_init:: + operator()(const char* name, + const value_semantic* s, + const char* description) + { + shared_ptr<option_description> d(new option_description(name, s, description)); + + owner->add(d); + return *this; + } + + const unsigned options_description::m_default_line_length = 80; + + options_description::options_description(unsigned line_length, + unsigned min_description_length) + : m_line_length(line_length) + , m_min_description_length(min_description_length) + { + // we require a space between the option and description parts, so add 1. + assert(m_min_description_length < m_line_length - 1); + } + + options_description::options_description(const std::string& caption, + unsigned line_length, + unsigned min_description_length) + : m_caption(caption) + , m_line_length(line_length) + , m_min_description_length(min_description_length) + { + // we require a space between the option and description parts, so add 1. + assert(m_min_description_length < m_line_length - 1); + } + + void + options_description::add(shared_ptr<option_description> desc) + { + m_options.push_back(desc); + belong_to_group.push_back(false); + } + + options_description& + options_description::add(const options_description& desc) + { + shared_ptr<options_description> d(new options_description(desc)); + groups.push_back(d); + + for (size_t i = 0; i < desc.m_options.size(); ++i) { + add(desc.m_options[i]); + belong_to_group.back() = true; + } + + return *this; + } + + options_description_easy_init + options_description::add_options() + { + return options_description_easy_init(this); + } + + const option_description& + options_description::find(const std::string& name, + bool approx, + bool long_ignore_case, + bool short_ignore_case) const + { + const option_description* d = find_nothrow(name, approx, + long_ignore_case, short_ignore_case); + if (!d) + boost::throw_exception(unknown_option(name)); + return *d; + } + + const std::vector< shared_ptr<option_description> >& + options_description::options() const + { + return m_options; + } + + const option_description* + options_description::find_nothrow(const std::string& name, + bool approx, + bool long_ignore_case, + bool short_ignore_case) const + { + shared_ptr<option_description> found; + vector<string> approximate_matches; + vector<string> full_matches; + + // We use linear search because matching specified option + // name with the declared option name need to take care about + // case sensitivity and trailing '*' and so we can't use simple map. + for(unsigned i = 0; i < m_options.size(); ++i) + { + option_description::match_result r = + m_options[i]->match(name, approx, long_ignore_case, short_ignore_case); + + if (r == option_description::no_match) + continue; + + if (r == option_description::full_match) + { + full_matches.push_back(m_options[i]->key(name)); + } + else + { + // FIXME: the use of 'key' here might not + // be the best approach. + approximate_matches.push_back(m_options[i]->key(name)); + } + + found = m_options[i]; + } + if (full_matches.size() > 1) + boost::throw_exception( + ambiguous_option(name, full_matches)); + + // If we have a full match, and an approximate match, + // ignore approximate match instead of reporting error. + // Say, if we have options "all" and "all-chroots", then + // "--all" on the command line should select the first one, + // without ambiguity. + if (full_matches.empty() && approximate_matches.size() > 1) + boost::throw_exception( + ambiguous_option(name, approximate_matches)); + + return found.get(); + } + + BOOST_PROGRAM_OPTIONS_DECL + std::ostream& operator<<(std::ostream& os, const options_description& desc) + { + desc.print(os); + return os; + } + + namespace { + + /* Given a string 'par', that contains no newline characters + outputs it to 'os' with wordwrapping, that is, as several + line. + + Each output line starts with 'indent' space characters, + following by characters from 'par'. The total length of + line is no longer than 'line_length'. + + */ + void format_paragraph(std::ostream& os, + std::string par, + unsigned indent, + unsigned line_length) + { + // Through reminder of this function, 'line_length' will + // be the length available for characters, not including + // indent. + assert(indent < line_length); + line_length -= indent; + + // index of tab (if present) is used as additional indent relative + // to first_column_width if paragrapth is spanned over multiple + // lines if tab is not on first line it is ignored + string::size_type par_indent = par.find('\t'); + + if (par_indent == string::npos) + { + par_indent = 0; + } + else + { + // only one tab per paragraph allowed + if (count(par.begin(), par.end(), '\t') > 1) + { + boost::throw_exception(program_options::error( + "Only one tab per paragraph is allowed")); + } + + // erase tab from string + par.erase(par_indent, 1); + + // this assert may fail due to user error or + // environment conditions! + assert(par_indent < line_length); + + // ignore tab if not on first line + if (par_indent >= line_length) + { + par_indent = 0; + } + } + + if (par.size() < line_length) + { + os << par; + } + else + { + string::const_iterator line_begin = par.begin(); + const string::const_iterator par_end = par.end(); + + bool first_line = true; // of current paragraph! + + while (line_begin < par_end) // paragraph lines + { + if (!first_line) + { + // If line starts with space, but second character + // is not space, remove the leading space. + // We don't remove double spaces because those + // might be intentianal. + if ((*line_begin == ' ') && + ((line_begin + 1 < par_end) && + (*(line_begin + 1) != ' '))) + { + line_begin += 1; // line_begin != line_end + } + } + + // Take care to never increment the iterator past + // the end, since MSVC 8.0 (brokenly), assumes that + // doing that, even if no access happens, is a bug. + unsigned remaining = distance(line_begin, par_end); + string::const_iterator line_end = line_begin + + ((remaining < line_length) ? remaining : line_length); + + // prevent chopped words + // Is line_end between two non-space characters? + if ((*(line_end - 1) != ' ') && + ((line_end < par_end) && (*line_end != ' '))) + { + // find last ' ' in the second half of the current paragraph line + string::const_iterator last_space = + find(reverse_iterator<string::const_iterator>(line_end), + reverse_iterator<string::const_iterator>(line_begin), + ' ') + .base(); + + if (last_space != line_begin) + { + // is last_space within the second half ot the + // current line + if (static_cast<unsigned>(distance(last_space, line_end)) < + (line_length / 2)) + { + line_end = last_space; + } + } + } // prevent chopped words + + // write line to stream + copy(line_begin, line_end, ostream_iterator<char>(os)); + + if (first_line) + { + indent += par_indent; + line_length -= par_indent; // there's less to work with now + first_line = false; + } + + // more lines to follow? + if (line_end != par_end) + { + os << '\n'; + + for(unsigned pad = indent; pad > 0; --pad) + { + os.put(' '); + } + } + + // next line starts after of this line + line_begin = line_end; + } // paragraph lines + } + } + + void format_description(std::ostream& os, + const std::string& desc, + unsigned first_column_width, + unsigned line_length) + { + // we need to use one char less per line to work correctly if actual + // console has longer lines + assert(line_length > 1); + if (line_length > 1) + { + --line_length; + } + + // line_length must be larger than first_column_width + // this assert may fail due to user error or environment conditions! + assert(line_length > first_column_width); + + // Note: can't use 'tokenizer' as name of typedef -- borland + // will consider uses of 'tokenizer' below as uses of + // boost::tokenizer, not typedef. + typedef boost::tokenizer<boost::char_separator<char> > tok; + + tok paragraphs( + desc, + char_separator<char>("\n", "", boost::keep_empty_tokens)); + + tok::const_iterator par_iter = paragraphs.begin(); + const tok::const_iterator par_end = paragraphs.end(); + + while (par_iter != par_end) // paragraphs + { + format_paragraph(os, *par_iter, first_column_width, + line_length); + + ++par_iter; + + // prepair next line if any + if (par_iter != par_end) + { + os << '\n'; + + for(unsigned pad = first_column_width; pad > 0; --pad) + { + os.put(' '); + } + } + } // paragraphs + } + + void format_one(std::ostream& os, const option_description& opt, + unsigned first_column_width, unsigned line_length) + { + stringstream ss; + ss << " " << opt.format_name() << ' ' << opt.format_parameter(); + + // Don't use ss.rdbuf() since g++ 2.96 is buggy on it. + os << ss.str(); + + if (!opt.description().empty()) + { + if (ss.str().size() >= first_column_width) + { + os.put('\n'); // first column is too long, lets put description in new line + for (unsigned pad = first_column_width; pad > 0; --pad) + { + os.put(' '); + } + } else { + for(unsigned pad = first_column_width - ss.str().size(); pad > 0; --pad) + { + os.put(' '); + } + } + + format_description(os, opt.description(), + first_column_width, line_length); + } + } + } + + void + options_description::print(std::ostream& os) const + { + if (!m_caption.empty()) + os << m_caption << ":\n"; + + /* Find the maximum width of the option column */ + unsigned width(23); + unsigned i; // vc6 has broken for loop scoping + for (i = 0; i < m_options.size(); ++i) + { + const option_description& opt = *m_options[i]; + stringstream ss; + ss << " " << opt.format_name() << ' ' << opt.format_parameter(); + width = (max)(width, static_cast<unsigned>(ss.str().size())); + } + /* this is the column were description should start, if first + column is longer, we go to a new line */ + const unsigned start_of_description_column = m_line_length - m_min_description_length; + + width = (min)(width, start_of_description_column-1); + + /* add an additional space to improve readability */ + ++width; + + /* The options formatting style is stolen from Subversion. */ + for (i = 0; i < m_options.size(); ++i) + { + if (belong_to_group[i]) + continue; + + const option_description& opt = *m_options[i]; + + format_one(os, opt, width, m_line_length); + + os << "\n"; + } + + for (unsigned j = 0; j < groups.size(); ++j) { + os << "\n" << *groups[j]; + } + } + +}} diff --git a/3rdParty/Boost/src/libs/program_options/src/parsers.cpp b/3rdParty/Boost/src/libs/program_options/src/parsers.cpp new file mode 100644 index 0000000..bc3b858 --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/parsers.cpp @@ -0,0 +1,245 @@ +// Copyright Vladimir Prus 2002-2004. +// 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) + + +#include <boost/config.hpp> + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> +#include <boost/program_options/parsers.hpp> +#include <boost/program_options/options_description.hpp> +#include <boost/program_options/positional_options.hpp> +#include <boost/program_options/detail/cmdline.hpp> +#include <boost/program_options/detail/config_file.hpp> +#include <boost/program_options/environment_iterator.hpp> +#include <boost/program_options/detail/convert.hpp> + +#include <boost/bind.hpp> +#include <boost/throw_exception.hpp> + +#include <cctype> +#include <fstream> + +#if !defined(__GNUC__) || __GNUC__ < 3 +#include <iostream> +#else +#include <istream> +#endif + +#ifdef _WIN32 +#include <stdlib.h> +#else +#include <unistd.h> +#endif + +// The 'environ' should be declared in some cases. E.g. Linux man page says: +// (This variable must be declared in the user program, but is declared in +// the header file unistd.h in case the header files came from libc4 or libc5, +// and in case they came from glibc and _GNU_SOURCE was defined.) +// To be safe, declare it here. + +// It appears that on Mac OS X the 'environ' variable is not +// available to dynamically linked libraries. +// See: http://article.gmane.org/gmane.comp.lib.boost.devel/103843 +// See: http://lists.gnu.org/archive/html/bug-guile/2004-01/msg00013.html +#if defined(__APPLE__) && defined(__DYNAMIC__) +#include <crt_externs.h> +#define environ (*_NSGetEnviron()) +#else +#if defined(__MWERKS__) +#include <crtl.h> +#else +#if !defined(_WIN32) || defined(__COMO_VERSION__) +extern char** environ; +#endif +#endif +#endif + +using namespace std; + +namespace boost { namespace program_options { + +#ifndef BOOST_NO_STD_WSTRING + namespace { + woption woption_from_option(const option& opt) + { + woption result; + result.string_key = opt.string_key; + result.position_key = opt.position_key; + result.unregistered = opt.unregistered; + + std::transform(opt.value.begin(), opt.value.end(), + back_inserter(result.value), + boost::bind(from_utf8, _1)); + + std::transform(opt.original_tokens.begin(), + opt.original_tokens.end(), + back_inserter(result.original_tokens), + boost::bind(from_utf8, _1)); + return result; + } + } + + basic_parsed_options<wchar_t> + ::basic_parsed_options(const parsed_options& po) + : description(po.description), + utf8_encoded_options(po) + { + for (unsigned i = 0; i < po.options.size(); ++i) + options.push_back(woption_from_option(po.options[i])); + } +#endif + + template<class charT> + basic_parsed_options<charT> + parse_config_file(std::basic_istream<charT>& is, + const options_description& desc, + bool allow_unregistered) + { + set<string> allowed_options; + + const vector<shared_ptr<option_description> >& options = desc.options(); + for (unsigned i = 0; i < options.size(); ++i) + { + const option_description& d = *options[i]; + + if (d.long_name().empty()) + boost::throw_exception( + error("long name required for config file")); + + allowed_options.insert(d.long_name()); + } + + // Parser return char strings + parsed_options result(&desc); + copy(detail::basic_config_file_iterator<charT>( + is, allowed_options, allow_unregistered), + detail::basic_config_file_iterator<charT>(), + back_inserter(result.options)); + // Convert char strings into desired type. + return basic_parsed_options<charT>(result); + } + + template + BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<char> + parse_config_file(std::basic_istream<char>& is, + const options_description& desc, + bool allow_unregistered); + +#ifndef BOOST_NO_STD_WSTRING + template + BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<wchar_t> + parse_config_file(std::basic_istream<wchar_t>& is, + const options_description& desc, + bool allow_unregistered); +#endif + + template<class charT> + basic_parsed_options<charT> + parse_config_file(const char* filename, + const options_description& desc, + bool allow_unregistered) + { + // Parser return char strings + std::basic_ifstream< charT > strm(filename); + if (!strm) + { + boost::throw_exception(reading_file(filename)); + } + return parse_config_file(strm, desc, allow_unregistered); + } + + template + BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<char> + parse_config_file(const char* filename, + const options_description& desc, + bool allow_unregistered); + +#ifndef BOOST_NO_STD_WSTRING + template + BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<wchar_t> + parse_config_file(const char* filename, + const options_description& desc, + bool allow_unregistered); +#endif + + +// This versio, which accepts any options without validation, is disabled, +// in the hope that nobody will need it and we cant drop it altogether. +// Besides, probably the right way to handle all options is the '*' name. +#if 0 + BOOST_PROGRAM_OPTIONS_DECL parsed_options + parse_config_file(std::istream& is) + { + detail::config_file_iterator cf(is, false); + parsed_options result(0); + copy(cf, detail::config_file_iterator(), + back_inserter(result.options)); + return result; + } +#endif + + BOOST_PROGRAM_OPTIONS_DECL parsed_options + parse_environment(const options_description& desc, + const function1<std::string, std::string>& name_mapper) + { + parsed_options result(&desc); + + for(environment_iterator i(environ), e; i != e; ++i) { + string option_name = name_mapper(i->first); + + if (!option_name.empty()) { + option n; + n.string_key = option_name; + n.value.push_back(i->second); + result.options.push_back(n); + } + } + + return result; + } + + namespace detail { + class prefix_name_mapper { + public: + prefix_name_mapper(const std::string& prefix) + : prefix(prefix) + {} + + std::string operator()(const std::string& s) + { + string result; + if (s.find(prefix) == 0) { + for(string::size_type n = prefix.size(); n < s.size(); ++n) + { + // Intel-Win-7.1 does not understand + // push_back on string. + result += tolower(s[n]); + } + } + return result; + } + private: + std::string prefix; + }; + } + + BOOST_PROGRAM_OPTIONS_DECL parsed_options + parse_environment(const options_description& desc, + const std::string& prefix) + { + return parse_environment(desc, detail::prefix_name_mapper(prefix)); + } + + BOOST_PROGRAM_OPTIONS_DECL parsed_options + parse_environment(const options_description& desc, const char* prefix) + { + return parse_environment(desc, string(prefix)); + } + + + + +}} diff --git a/3rdParty/Boost/src/libs/program_options/src/positional_options.cpp b/3rdParty/Boost/src/libs/program_options/src/positional_options.cpp new file mode 100644 index 0000000..55995d7 --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/positional_options.cpp @@ -0,0 +1,53 @@ +// Copyright Vladimir Prus 2004. +// 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) + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> + +#include <boost/program_options/positional_options.hpp> + +#include <boost/limits.hpp> + +#include <cassert> + +namespace boost { namespace program_options { + + positional_options_description::positional_options_description() + {} + + positional_options_description& + positional_options_description::add(const char* name, int max_count) + { + assert(max_count != -1 || m_trailing.empty()); + + if (max_count == -1) + m_trailing = name; + else { + m_names.resize(m_names.size() + max_count, name); + } + return *this; + } + + unsigned + positional_options_description::max_total_count() const + { + return m_trailing.empty() ? + m_names.size() : (std::numeric_limits<unsigned>::max)(); + } + + const std::string& + positional_options_description::name_for_position(unsigned position) const + { + assert(position < max_total_count()); + + if (position < m_names.size()) + return m_names[position]; + else + return m_trailing; + } + + +}} + diff --git a/3rdParty/Boost/src/libs/program_options/src/split.cpp b/3rdParty/Boost/src/libs/program_options/src/split.cpp new file mode 100644 index 0000000..96da068 --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/split.cpp @@ -0,0 +1,62 @@ +// Copyright Sascha Ochsenknecht 2009. +// 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) + +#define BOOST_PROGRAM_OPTIONS_SOURCE + +#include <boost/program_options/parsers.hpp> +#include <boost/tokenizer.hpp> + +#include <string> +#include <vector> + +namespace boost { namespace program_options { namespace detail { + + template< class charT > + std::vector<std::basic_string<charT> > + split_unix( + const std::basic_string<charT>& cmdline, + const std::basic_string<charT>& seperator, + const std::basic_string<charT>& quote, + const std::basic_string<charT>& escape) + { + typedef boost::tokenizer< boost::escaped_list_separator<charT>, + typename std::basic_string<charT>::const_iterator, + std::basic_string<charT> > tokenizerT; + + tokenizerT tok(cmdline.begin(), cmdline.end(), + boost::escaped_list_separator< charT >(escape, seperator, quote)); + + std::vector< std::basic_string<charT> > result; + for (typename tokenizerT::iterator cur_token(tok.begin()), end_token(tok.end()); cur_token != end_token; ++cur_token) { + if (!cur_token->empty()) + result.push_back(*cur_token); + } + return result; + } + +}}} // namespace + +namespace boost { namespace program_options { + + // Take a command line string and splits in into tokens, according + // to the given collection of seperators chars. + BOOST_PROGRAM_OPTIONS_DECL std::vector<std::string> + split_unix(const std::string& cmdline, const std::string& seperator, + const std::string& quote, const std::string& escape) + { + return detail::split_unix< char >(cmdline, seperator, quote, escape); + } + +#ifndef BOOST_NO_STD_WSTRING + BOOST_PROGRAM_OPTIONS_DECL std::vector<std::wstring> + split_unix(const std::wstring& cmdline, const std::wstring& seperator, + const std::wstring& quote, const std::wstring& escape) + { + return detail::split_unix< wchar_t >(cmdline, seperator, quote, escape); + } +#endif + +}} // namespace + diff --git a/3rdParty/Boost/src/libs/program_options/src/utf8_codecvt_facet.cpp b/3rdParty/Boost/src/libs/program_options/src/utf8_codecvt_facet.cpp new file mode 100644 index 0000000..c0fd7c0 --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/utf8_codecvt_facet.cpp @@ -0,0 +1,21 @@ +// Copyright Vladimir Prus 2004. +// 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) + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> + +#define BOOST_UTF8_BEGIN_NAMESPACE \ + namespace boost { namespace program_options { namespace detail { + +#define BOOST_UTF8_END_NAMESPACE }}} +#define BOOST_UTF8_DECL BOOST_PROGRAM_OPTIONS_DECL + +#include "../../detail/utf8_codecvt_facet.cpp" + + +#undef BOOST_UTF8_BEGIN_NAMESPACE +#undef BOOST_UTF8_END_NAMESPACE +#undef BOOST_UTF8_DECL + diff --git a/3rdParty/Boost/src/libs/program_options/src/value_semantic.cpp b/3rdParty/Boost/src/libs/program_options/src/value_semantic.cpp new file mode 100644 index 0000000..f5770f1 --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/value_semantic.cpp @@ -0,0 +1,335 @@ +// Copyright Vladimir Prus 2004. +// 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) + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> +#include <boost/program_options/value_semantic.hpp> +#include <boost/program_options/detail/convert.hpp> + +#include <cctype> + +namespace boost { namespace program_options { + + using namespace std; + + void + value_semantic_codecvt_helper<char>:: + parse(boost::any& value_store, + const std::vector<std::string>& new_tokens, + bool utf8) const + { + if (utf8) { +#ifndef BOOST_NO_STD_WSTRING + // Need to convert to local encoding. + std::vector<string> local_tokens; + for (unsigned i = 0; i < new_tokens.size(); ++i) { + std::wstring w = from_utf8(new_tokens[i]); + local_tokens.push_back(to_local_8_bit(w)); + } + xparse(value_store, local_tokens); +#else + boost::throw_exception( + std::runtime_error("UTF-8 conversion not supported.")); +#endif + } else { + // Already in local encoding, pass unmodified + xparse(value_store, new_tokens); + } + } + +#ifndef BOOST_NO_STD_WSTRING + void + value_semantic_codecvt_helper<wchar_t>:: + parse(boost::any& value_store, + const std::vector<std::string>& new_tokens, + bool utf8) const + { + std::vector<wstring> tokens; + if (utf8) { + // Convert from utf8 + for (unsigned i = 0; i < new_tokens.size(); ++i) { + tokens.push_back(from_utf8(new_tokens[i])); + } + + } else { + // Convert from local encoding + for (unsigned i = 0; i < new_tokens.size(); ++i) { + tokens.push_back(from_local_8_bit(new_tokens[i])); + } + } + + xparse(value_store, tokens); + } +#endif + + BOOST_PROGRAM_OPTIONS_DECL std::string arg("arg"); + + std::string + untyped_value::name() const + { + return arg; + } + + unsigned + untyped_value::min_tokens() const + { + if (m_zero_tokens) + return 0; + else + return 1; + } + + unsigned + untyped_value::max_tokens() const + { + if (m_zero_tokens) + return 0; + else + return 1; + } + + + void + untyped_value::xparse(boost::any& value_store, + const std::vector<std::string>& new_tokens) const + { + if (!value_store.empty()) + boost::throw_exception( + multiple_occurrences()); + if (new_tokens.size() > 1) + boost::throw_exception(multiple_values()); + value_store = new_tokens.empty() ? std::string("") : new_tokens.front(); + } + + BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>* + bool_switch() + { + return bool_switch(0); + } + + BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>* + bool_switch(bool* v) + { + typed_value<bool>* r = new typed_value<bool>(v); + r->default_value(0); + r->zero_tokens(); + + return r; + } + + /* Validates bool value. + Any of "1", "true", "yes", "on" will be converted to "1".<br> + Any of "0", "false", "no", "off" will be converted to "0".<br> + Case is ignored. The 'xs' vector can either be empty, in which + case the value is 'true', or can contain explicit value. + */ + BOOST_PROGRAM_OPTIONS_DECL void validate(any& v, const vector<string>& xs, + bool*, int) + { + check_first_occurrence(v); + string s(get_single_string(xs, true)); + + for (size_t i = 0; i < s.size(); ++i) + s[i] = char(tolower(s[i])); + + if (s.empty() || s == "on" || s == "yes" || s == "1" || s == "true") + v = any(true); + else if (s == "off" || s == "no" || s == "0" || s == "false") + v = any(false); + else + boost::throw_exception(validation_error(validation_error::invalid_bool_value, s)); + } + + // This is blatant copy-paste. However, templating this will cause a problem, + // since wstring can't be constructed/compared with char*. We'd need to + // create auxiliary 'widen' routine to convert from char* into + // needed string type, and that's more work. +#if !defined(BOOST_NO_STD_WSTRING) + BOOST_PROGRAM_OPTIONS_DECL + void validate(any& v, const vector<wstring>& xs, bool*, int) + { + check_first_occurrence(v); + wstring s(get_single_string(xs, true)); + + for (size_t i = 0; i < s.size(); ++i) + s[i] = wchar_t(tolower(s[i])); + + if (s.empty() || s == L"on" || s == L"yes" || s == L"1" || s == L"true") + v = any(true); + else if (s == L"off" || s == L"no" || s == L"0" || s == L"false") + v = any(false); + else + boost::throw_exception(validation_error(validation_error::invalid_bool_value)); + } +#endif + BOOST_PROGRAM_OPTIONS_DECL + void validate(any& v, const vector<string>& xs, std::string*, int) + { + check_first_occurrence(v); + v = any(get_single_string(xs)); + } + +#if !defined(BOOST_NO_STD_WSTRING) + BOOST_PROGRAM_OPTIONS_DECL + void validate(any& v, const vector<wstring>& xs, std::string*, int) + { + check_first_occurrence(v); + v = any(get_single_string(xs)); + } +#endif + + namespace validators { + + BOOST_PROGRAM_OPTIONS_DECL + void check_first_occurrence(const boost::any& value) + { + if (!value.empty()) + boost::throw_exception( + multiple_occurrences()); + } + } + + + invalid_option_value:: + invalid_option_value(const std::string& bad_value) + : validation_error(validation_error::invalid_option_value, bad_value) + {} + +#ifndef BOOST_NO_STD_WSTRING + namespace + { + std::string convert_value(const std::wstring& s) + { + try { + return to_local_8_bit(s); + } + catch(const std::exception&) { + return "<unrepresentable unicode string>"; + } + } + } + + invalid_option_value:: + invalid_option_value(const std::wstring& bad_value) + : validation_error(validation_error::invalid_option_value, convert_value(bad_value)) + {} +#endif + const std::string& + unknown_option::get_option_name() const throw() + { + return m_option_name; + } + + const std::string& + ambiguous_option::get_option_name() const throw() + { + return m_option_name; + } + + const std::vector<std::string>& + ambiguous_option::alternatives() const throw() + { + return m_alternatives; + } + + void + multiple_values::set_option_name(const std::string& option_name) + { + m_option_name = option_name; + } + + const std::string& + multiple_values::get_option_name() const throw() + { + return m_option_name; + } + + void + multiple_occurrences::set_option_name(const std::string& option_name) + { + m_option_name = option_name; + } + + const std::string& + multiple_occurrences::get_option_name() const throw() + { + return m_option_name; + } + + validation_error:: + validation_error(kind_t kind, + const std::string& option_value, + const std::string& option_name) + : error("") + , m_kind(kind) + , m_option_name(option_name) + , m_option_value(option_value) + , m_message(error_message(kind)) + { + if (!option_value.empty()) + { + m_message.append(std::string("'") + option_value + std::string("'")); + } + } + + void + validation_error::set_option_name(const std::string& option_name) + { + m_option_name = option_name; + } + + const std::string& + validation_error::get_option_name() const throw() + { + return m_option_name; + } + + std::string + validation_error::error_message(kind_t kind) + { + // Initially, store the message in 'const char*' variable, + // to avoid conversion to std::string in all cases. + const char* msg; + switch(kind) + { + case multiple_values_not_allowed: + msg = "multiple values not allowed"; + break; + case at_least_one_value_required: + msg = "at least one value required"; + break; + case invalid_bool_value: + msg = "invalid bool value"; + break; + case invalid_option_value: + msg = "invalid option value"; + break; + case invalid_option: + msg = "invalid option"; + break; + default: + msg = "unknown error"; + } + return msg; + } + + const char* + validation_error::what() const throw() + { + if (!m_option_name.empty()) + { + m_message = "in option '" + m_option_name + "': " + + error_message(m_kind); + } + return m_message.c_str(); + } + + const std::string& + required_option::get_option_name() const throw() + { + return m_option_name; + } + +}} diff --git a/3rdParty/Boost/src/libs/program_options/src/variables_map.cpp b/3rdParty/Boost/src/libs/program_options/src/variables_map.cpp new file mode 100644 index 0000000..29b1de9 --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/variables_map.cpp @@ -0,0 +1,231 @@ +// Copyright Vladimir Prus 2002-2004. +// 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) + + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> +#include <boost/program_options/parsers.hpp> +#include <boost/program_options/options_description.hpp> +#include <boost/program_options/value_semantic.hpp> +#include <boost/program_options/variables_map.hpp> + +#include <cassert> + +namespace boost { namespace program_options { + + using namespace std; + + // First, performs semantic actions for 'oa'. + // Then, stores in 'm' all options that are defined in 'desc'. + BOOST_PROGRAM_OPTIONS_DECL + void store(const parsed_options& options, variables_map& xm, + bool utf8) + { + // TODO: what if we have different definition + // for the same option name during different calls + // 'store'. + assert(options.description); + const options_description& desc = *options.description; + + // We need to access map's operator[], not the overriden version + // variables_map. Ehmm.. messy. + std::map<std::string, variable_value>& m = xm; + + std::set<std::string> new_final; + + // Declared once, to please Intel in VC++ mode; + unsigned i; + + // First, convert/store all given options + for (i = 0; i < options.options.size(); ++i) { + + const string& name = options.options[i].string_key; + // Skip positional options without name + if (name.empty()) + continue; + + // Ignore unregistered option. The 'unregistered' + // field can be true only if user has explicitly asked + // to allow unregistered options. We can't store them + // to variables map (lacking any information about paring), + // so just ignore them. + if (options.options[i].unregistered) + continue; + + // If option has final value, skip this assignment + if (xm.m_final.count(name)) + continue; + + const option_description& d = desc.find(name, false, + false, false); + + variable_value& v = m[name]; + if (v.defaulted()) { + // Explicit assignment here erases defaulted value + v = variable_value(); + } + + try { + d.semantic()->parse(v.value(), options.options[i].value, utf8); + } +#ifndef BOOST_NO_EXCEPTIONS + catch(validation_error& e) + { + e.set_option_name(name); + throw; + } + catch(multiple_occurrences& e) + { + e.set_option_name(name); + throw; + } + catch(multiple_values& e) + { + e.set_option_name(name); + throw; + } +#endif + v.m_value_semantic = d.semantic(); + + // The option is not composing, and the value is explicitly + // provided. Ignore values of this option for subsequent + // calls to 'store'. We store this to a temporary set, + // so that several assignment inside *this* 'store' call + // are allowed. + if (!d.semantic()->is_composing()) + new_final.insert(name); + } + xm.m_final.insert(new_final.begin(), new_final.end()); + + + + // Second, apply default values and store required options. + const vector<shared_ptr<option_description> >& all = desc.options(); + for(i = 0; i < all.size(); ++i) + { + const option_description& d = *all[i]; + string key = d.key(""); + // FIXME: this logic relies on knowledge of option_description + // internals. + // The 'key' is empty if options description contains '*'. + // In that + // case, default value makes no sense at all. + if (key.empty()) + { + continue; + } + if (m.count(key) == 0) { + + boost::any def; + if (d.semantic()->apply_default(def)) { + m[key] = variable_value(def, true); + m[key].m_value_semantic = d.semantic(); + } + } + + // add empty value if this is an required option + if (d.semantic()->is_required()) { + xm.m_required.insert(key); + } + } + } + + BOOST_PROGRAM_OPTIONS_DECL + void store(const wparsed_options& options, variables_map& m) + { + store(options.utf8_encoded_options, m, true); + } + + BOOST_PROGRAM_OPTIONS_DECL + void notify(variables_map& vm) + { + vm.notify(); + } + + abstract_variables_map::abstract_variables_map() + : m_next(0) + {} + + abstract_variables_map:: + abstract_variables_map(const abstract_variables_map* next) + : m_next(next) + {} + + const variable_value& + abstract_variables_map::operator[](const std::string& name) const + { + const variable_value& v = get(name); + if (v.empty() && m_next) + return (*m_next)[name]; + else if (v.defaulted() && m_next) { + const variable_value& v2 = (*m_next)[name]; + if (!v2.empty() && !v2.defaulted()) + return v2; + else return v; + } else { + return v; + } + } + + void + abstract_variables_map::next(abstract_variables_map* next) + { + m_next = next; + } + + variables_map::variables_map() + {} + + variables_map::variables_map(const abstract_variables_map* next) + : abstract_variables_map(next) + {} + + const variable_value& + variables_map::get(const std::string& name) const + { + static variable_value empty; + const_iterator i = this->find(name); + if (i == this->end()) + return empty; + else + return i->second; + } + + void + variables_map::notify() + { + // This checks if all required options occur + for (set<string>::const_iterator r = m_required.begin(); + r != m_required.end(); + ++r) + { + const string& opt = *r; + map<string, variable_value>::const_iterator iter = find(opt); + if (iter == end() || iter->second.empty()) + { + boost::throw_exception(required_option(opt)); + + } + } + + // Lastly, run notify actions. + for (map<string, variable_value>::iterator k = begin(); + k != end(); + ++k) + { + /* Users might wish to use variables_map to store their own values + that are not parsed, and therefore will not have value_semantics + defined. Do no crash on such values. In multi-module programs, + one module might add custom values, and the 'notify' function + will be called after that, so we check that value_sematics is + not NULL. See: + https://svn.boost.org/trac/boost/ticket/2782 + */ + if (k->second.m_value_semantic) + k->second.m_value_semantic->notify(k->second.value()); + } + } + +}} diff --git a/3rdParty/Boost/src/libs/program_options/src/winmain.cpp b/3rdParty/Boost/src/libs/program_options/src/winmain.cpp new file mode 100644 index 0000000..64cc790 --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/winmain.cpp @@ -0,0 +1,96 @@ +// Copyright Vladimir Prus 2002-2004. +// 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) + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/parsers.hpp> +#include <cctype> + +#ifdef _WIN32 +namespace boost { namespace program_options { + + // Take a command line string and splits in into tokens, according + // to the rules windows command line processor uses. + // + // The rules are pretty funny, see + // http://article.gmane.org/gmane.comp.lib.boost.user/3005 + // http://msdn.microsoft.com/library/en-us/vccelng/htm/progs_12.asp + BOOST_PROGRAM_OPTIONS_DECL + std::vector<std::string> split_winmain(const std::string& input) + { + std::vector<std::string> result; + + std::string::const_iterator i = input.begin(), e = input.end(); + for(;i != e; ++i) + if (!isspace((unsigned char)*i)) + break; + + if (i != e) { + + std::string current; + bool inside_quoted = false; + int backslash_count = 0; + + for(; i != e; ++i) { + if (*i == '"') { + // '"' preceded by even number (n) of backslashes generates + // n/2 backslashes and is a quoted block delimiter + if (backslash_count % 2 == 0) { + current.append(backslash_count / 2, '\\'); + inside_quoted = !inside_quoted; + // '"' preceded by odd number (n) of backslashes generates + // (n-1)/2 backslashes and is literal quote. + } else { + current.append(backslash_count / 2, '\\'); + current += '"'; + } + backslash_count = 0; + } else if (*i == '\\') { + ++backslash_count; + } else { + // Not quote or backslash. All accumulated backslashes should be + // added + if (backslash_count) { + current.append(backslash_count, '\\'); + backslash_count = 0; + } + if (isspace((unsigned char)*i) && !inside_quoted) { + // Space outside quoted section terminate the current argument + result.push_back(current); + current.resize(0); + for(;i != e && isspace((unsigned char)*i); ++i) + ; + --i; + } else { + current += *i; + } + } + } + + // If we have trailing backslashes, add them + if (backslash_count) + current.append(backslash_count, '\\'); + + // If we have non-empty 'current' or we're still in quoted + // section (even if 'current' is empty), add the last token. + if (!current.empty() || inside_quoted) + result.push_back(current); + } + return result; + } + +#ifndef BOOST_NO_STD_WSTRING + BOOST_PROGRAM_OPTIONS_DECL std::vector<std::wstring> + split_winmain(const std::wstring& cmdline) + { + std::vector<std::wstring> result; + std::vector<std::string> aux = split_winmain(to_internal(cmdline)); + for (unsigned i = 0, e = aux.size(); i < e; ++i) + result.push_back(from_utf8(aux[i])); + return result; + } +#endif + +}} +#endif diff --git a/3rdParty/Boost/update.sh b/3rdParty/Boost/update.sh index ed1ce06..1ef3aa5 100755 --- a/3rdParty/Boost/update.sh +++ b/3rdParty/Boost/update.sh @@ -15,8 +15,9 @@ TARGET_DIR=src noncopyable.hpp \ numeric/conversion/cast.hpp \ shared_ptr.hpp \ - optional.hpp \ + optional.hpp \ signals.hpp \ + program_options.hpp \ thread.hpp \ asio.hpp \ regex.hpp \ @@ -25,7 +26,7 @@ TARGET_DIR=src rm -rf $TARGET_DIR/libs/config rm -rf $TARGET_DIR/libs/smart_ptr -LIBS="date_time regex system thread signals filesystem" +LIBS="date_time regex system thread signals filesystem program_options" for lib in $LIBS; do rm -rf $TARGET_DIR/libs/$lib/build $TARGET_DIR/libs/$lib/*.doc $TARGET_DIR/libs/$lib/src/*.doc $TARGET_DIR/libs/$lib/src/CMakeLists.txt $TARGET_DIR/libs/$lib/test done diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp index d05826a..6056fc5 100644 --- a/Swift/Controllers/Chat/ChatController.cpp +++ b/Swift/Controllers/Chat/ChatController.cpp @@ -21,8 +21,9 @@ namespace Swift { /** * The controller does not gain ownership of the stanzaChannel, nor the factory. */ -ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC) - : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager) { +ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency) + : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency) { + isInMUC_ = isInMUC; chatStateNotifier_ = new ChatStateNotifier(); chatStateMessageSender_ = new ChatStateMessageSender(chatStateNotifier_, stanzaChannel, contact); chatStateTracker_ = new ChatStateTracker(); diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h index b044633..3821a6e 100644 --- a/Swift/Controllers/Chat/ChatController.h +++ b/Swift/Controllers/Chat/ChatController.h @@ -17,7 +17,7 @@ namespace Swift { class NickResolver; class ChatController : public ChatControllerBase { public: - ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC); + ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency); virtual void setToJID(const JID& jid); private: @@ -35,6 +35,7 @@ namespace Swift { ChatStateNotifier* chatStateNotifier_; ChatStateMessageSender* chatStateMessageSender_; ChatStateTracker* chatStateTracker_; + bool isInMUC_; }; } #endif diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp index abd346a..f3e6bbe 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.cpp +++ b/Swift/Controllers/Chat/ChatControllerBase.cpp @@ -22,7 +22,7 @@ namespace Swift { -ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager) { +ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager), useDelayForLatency_(useDelayForLatency) { chatWindow_ = chatWindowFactory_->createChatWindow(toJID); chatWindow_->onAllMessagesRead.connect(boost::bind(&ChatControllerBase::handleAllMessagesRead, this)); chatWindow_->onSendMessageRequest.connect(boost::bind(&ChatControllerBase::handleSendMessageRequest, this, _1)); @@ -73,9 +73,7 @@ void ChatControllerBase::handleSendMessageRequest(const String &body) { label = boost::optional<SecurityLabel>(chatWindow_->getSelectedSecurityLabel()); } preSendMessageRequest(message); - //FIXME: optional - bool useSwiftDelay = true; - if (useSwiftDelay) { + if (useDelayForLatency_) { boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time(); message->addPayload(boost::shared_ptr<Delay>(new Delay(now, selfJID_))); } @@ -113,6 +111,10 @@ void ChatControllerBase::addMessage(const String& message, const String& senderN } } +bool ChatControllerBase::isFromContact(const JID& from) { + return from.toBare() == toJID_.toBare(); +} + void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent) { if (messageEvent->isReadable()) { unreadMessages_.push_back(messageEvent); @@ -131,16 +133,19 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m return; } showChatWindow(); - boost::shared_ptr<Delay> delayPayload = message->getPayload<Delay>(); - if (delayPayload) { + JID from = message->getFrom(); + std::vector<boost::shared_ptr<Delay> > delayPayloads = message->getPayloads<Delay>(); + for (size_t i = 0; useDelayForLatency_ && i < delayPayloads.size(); i++) { + if (!delayPayloads[i]->getFrom()) { + continue; + } boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time(); std::ostringstream s; - s << "The following message took " << (now - delayPayload->getStamp()).total_milliseconds() << " milliseconds to be delivered."; + s << "The following message took " << (now - delayPayloads[i]->getStamp()).total_milliseconds() / 1000.0 << " seconds to be delivered from " << delayPayloads[i]->getFrom()->toString() << "."; chatWindow_->addSystemMessage(String(s.str())); } boost::shared_ptr<SecurityLabel> label = message->getPayload<SecurityLabel>(); boost::optional<SecurityLabel> maybeLabel = label ? boost::optional<SecurityLabel>(*label) : boost::optional<SecurityLabel>(); - JID from = message->getFrom(); addMessage(body, senderDisplayNameFromMessage(from), isIncomingMessageFromMe(message), maybeLabel, String(avatarManager_->getAvatarPath(from).string())); } } diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h index a2dfd6a..8317da8 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.h +++ b/Swift/Controllers/Chat/ChatControllerBase.h @@ -40,14 +40,14 @@ namespace Swift { void setEnabled(bool enabled); virtual void setToJID(const JID& jid) {toJID_ = jid;}; protected: - ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager); + ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency); virtual void postSendMessage(const String&) {}; virtual String senderDisplayNameFromMessage(const JID& from) = 0; virtual bool isIncomingMessageFromMe(boost::shared_ptr<Message>) = 0; virtual void preHandleIncomingMessage(boost::shared_ptr<Message>) {}; virtual void preSendMessageRequest(boost::shared_ptr<Message>) {}; - + virtual bool isFromContact(const JID& from); private: void handleSendMessageRequest(const String &body); @@ -66,6 +66,7 @@ namespace Swift { bool labelsEnabled_; PresenceOracle* presenceOracle_; AvatarManager* avatarManager_; + bool useDelayForLatency_; }; } diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp index a490a3f..6aacdbd 100644 --- a/Swift/Controllers/Chat/ChatsManager.cpp +++ b/Swift/Controllers/Chat/ChatsManager.cpp @@ -25,7 +25,7 @@ namespace Swift { typedef std::pair<JID, ChatController*> JIDChatControllerPair; typedef std::pair<JID, MUCController*> JIDMUCControllerPair; -ChatsManager::ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, TreeWidgetFactory* treeWidgetFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, boost::shared_ptr<DiscoInfo> serverDiscoInfo, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory) : jid_(jid) { +ChatsManager::ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, TreeWidgetFactory* treeWidgetFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, boost::shared_ptr<DiscoInfo> serverDiscoInfo, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency) : jid_(jid), useDelayForLatency_(useDelayForLatency) { eventController_ = eventController; stanzaChannel_ = stanzaChannel; iqRouter_ = iqRouter; @@ -165,7 +165,7 @@ ChatController* ChatsManager::getChatControllerOrFindAnother(const JID &contact) } ChatController* ChatsManager::createNewChatController(const JID& contact) { - ChatController* controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, isMUC(contact.toBare())); + ChatController* controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, isMUC(contact.toBare()), useDelayForLatency_); chatControllers_[contact] = controller; controller->setAvailableServerFeatures(serverDiscoInfo_); return controller; @@ -201,7 +201,7 @@ void ChatsManager::handleJoinMUCRequest(const JID &muc, const boost::optional<St //FIXME: What's correct behaviour here? } else { String nick = nickMaybe ? nickMaybe.get() : "Swift user"; - MUCController* controller = new MUCController(jid_, muc, nick, stanzaChannel_, presenceSender_, iqRouter_, chatWindowFactory_, treeWidgetFactory_, presenceOracle_, avatarManager_, uiEventStream_); + MUCController* controller = new MUCController(jid_, muc, nick, stanzaChannel_, presenceSender_, iqRouter_, chatWindowFactory_, treeWidgetFactory_, presenceOracle_, avatarManager_, uiEventStream_, false); mucControllers_[muc] = controller; controller->setAvailableServerFeatures(serverDiscoInfo_); controller->onUserLeft.connect(boost::bind(&ChatsManager::handleUserLeftMUC, this, controller)); diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h index df49b0a..d45d81d 100644 --- a/Swift/Controllers/Chat/ChatsManager.h +++ b/Swift/Controllers/Chat/ChatsManager.h @@ -37,7 +37,7 @@ namespace Swift { class ChatsManager : public MUCRegistry { public: - ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, TreeWidgetFactory* treeWidgetFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, boost::shared_ptr<DiscoInfo> serverDiscoInfo, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory); + ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, TreeWidgetFactory* treeWidgetFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, boost::shared_ptr<DiscoInfo> serverDiscoInfo, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency); ~ChatsManager(); void setAvatarManager(AvatarManager* avatarManager); void setEnabled(bool enabled); @@ -75,5 +75,6 @@ namespace Swift { boost::shared_ptr<DiscoInfo> serverDiscoInfo_; ChatListWindow* chatListWindow_; boost::bsignals::scoped_connection uiEventConnection_; + bool useDelayForLatency_; }; } diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp index f22bc18..737ad82 100644 --- a/Swift/Controllers/Chat/MUCController.cpp +++ b/Swift/Controllers/Chat/MUCController.cpp @@ -38,8 +38,9 @@ MUCController::MUCController ( TreeWidgetFactory *treeWidgetFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, - UIEventStream* uiEventStream) : - ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc, presenceOracle, avatarManager), + UIEventStream* uiEventStream, + bool useDelayForLatency) : + ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc, presenceOracle, avatarManager, useDelayForLatency), muc_(new MUC(stanzaChannel, presenceSender, muc)), nick_(nick), treeWidgetFactory_(treeWidgetFactory) { diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h index d0e1980..2252357 100644 --- a/Swift/Controllers/Chat/MUCController.h +++ b/Swift/Controllers/Chat/MUCController.h @@ -32,7 +32,7 @@ namespace Swift { class MUCController : public ChatControllerBase { public: - MUCController(const JID& self, const JID &muc, const String &nick, StanzaChannel* stanzaChannel, PresenceSender* presenceSender, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, TreeWidgetFactory *treeWidgetFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events); + MUCController(const JID& self, const JID &muc, const String &nick, StanzaChannel* stanzaChannel, PresenceSender* presenceSender, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, TreeWidgetFactory *treeWidgetFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency); ~MUCController(); boost::signal<void ()> onUserLeft; diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp index d493cf6..5caedab 100644 --- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp +++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp @@ -63,7 +63,7 @@ public: uiEventStream_ = new UIEventStream(); chatListWindowFactory_ = mocks_->InterfaceMock<ChatListWindowFactory>(); mocks_->ExpectCall(chatListWindowFactory_, ChatListWindowFactory::createWindow).With(uiEventStream_).Return(NULL); - manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, treeWidgetFactory_, nickResolver_, presenceOracle_, serverDiscoInfo_, presenceSender_, uiEventStream_, chatListWindowFactory_); + manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, treeWidgetFactory_, nickResolver_, presenceOracle_, serverDiscoInfo_, presenceSender_, uiEventStream_, chatListWindowFactory_, true); avatarManager_ = new MockAvatarManager(); manager_->setAvatarManager(avatarManager_); }; diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index 341fc09..3656de3 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -61,8 +61,8 @@ static const String CLIENT_VERSION = "0.3"; static const String CLIENT_NODE = "http://swift.im"; -MainController::MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, TreeWidgetFactory *treeWidgetFactory, EventWindowFactory* eventWindowFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer, XMLConsoleWidgetFactory* xmlConsoleWidgetFactory, ChatListWindowFactory* chatListWindowFactory) - : timerFactory_(&boostIOServiceThread_.getIOService()), idleDetector_(&idleQuerier_, &timerFactory_, 100), chatWindowFactory_(chatWindowFactory), mainWindowFactory_(mainWindowFactory), loginWindowFactory_(loginWindowFactory), treeWidgetFactory_(treeWidgetFactory), settings_(settings), loginWindow_(NULL) { +MainController::MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, TreeWidgetFactory *treeWidgetFactory, EventWindowFactory* eventWindowFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer, XMLConsoleWidgetFactory* xmlConsoleWidgetFactory, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency) + : timerFactory_(&boostIOServiceThread_.getIOService()), idleDetector_(&idleQuerier_, &timerFactory_, 100), chatWindowFactory_(chatWindowFactory), mainWindowFactory_(mainWindowFactory), loginWindowFactory_(loginWindowFactory), treeWidgetFactory_(treeWidgetFactory), settings_(settings), loginWindow_(NULL), useDelayForLatency_(useDelayForLatency) { application_ = application; presenceOracle_ = NULL; avatarManager_ = NULL; @@ -180,7 +180,7 @@ void MainController::handleConnected() { rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2)); rosterController_->onSignOutRequest.connect(boost::bind(&MainController::signOut, this)); - chatsManager_ = new ChatsManager(jid_, client_, client_, eventController_, chatWindowFactory_, treeWidgetFactory_, nickResolver_, presenceOracle_, serverDiscoInfo_, presenceSender_, uiEventStream_, chatListWindowFactory_); + chatsManager_ = new ChatsManager(jid_, client_, client_, eventController_, chatWindowFactory_, treeWidgetFactory_, nickResolver_, presenceOracle_, serverDiscoInfo_, presenceSender_, uiEventStream_, chatListWindowFactory_, useDelayForLatency_); nickResolver_->setMUCRegistry(chatsManager_); client_->onMessageReceived.connect(boost::bind(&ChatsManager::handleIncomingMessage, chatsManager_, _1)); chatsManager_->setAvatarManager(avatarManager_); diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h index 5ed3641..2ed922c 100644 --- a/Swift/Controllers/MainController.h +++ b/Swift/Controllers/MainController.h @@ -62,7 +62,7 @@ namespace Swift { class MainController { public: - MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, TreeWidgetFactory* treeWidgetFactory, EventWindowFactory* eventWindowFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer, XMLConsoleWidgetFactory* xmlConsoleWidgetFactory, ChatListWindowFactory* chatListWindowFactory_); + MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, TreeWidgetFactory* treeWidgetFactory, EventWindowFactory* eventWindowFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer, XMLConsoleWidgetFactory* xmlConsoleWidgetFactory, ChatListWindowFactory* chatListWindowFactory_, bool useDelayForLatency); ~MainController(); @@ -127,5 +127,6 @@ namespace Swift { String certificateFile_; ChatListWindowFactory* chatListWindowFactory_; boost::shared_ptr<ErrorEvent> lastDisconnectError_; + bool useDelayForLatency_; }; } diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp index 258a7b6..fc5f4cb 100644 --- a/Swift/QtUI/QtSwift.cpp +++ b/Swift/QtUI/QtSwift.cpp @@ -40,9 +40,19 @@ namespace Swift{ #define SWIFT_APPCAST_URL "" #endif +po::options_description QtSwift::getOptionsDescription() { + po::options_description result("Options"); + result.add_options() + ("help", "produce help message") + ("netbook-mode", "use netbook mode display") + ("latency-debug", "use latency debugging") + ; + return result; +} + -QtSwift::QtSwift(bool netbookMode) : autoUpdater_(NULL) { - if (netbookMode) { +QtSwift::QtSwift(po::variables_map options) : autoUpdater_(NULL) { + if (options.count("netbook-mode")) { splitter_ = new QSplitter(); } else { splitter_ = NULL; @@ -67,7 +77,7 @@ QtSwift::QtSwift(bool netbookMode) : autoUpdater_(NULL) { if (splitter_) { splitter_->show(); } - mainController_ = new MainController(chatWindowFactory_, rosterWindowFactory_, loginWindowFactory_, treeWidgetFactory_, eventWindowFactory_, settings_, application_, systemTray_, soundPlayer_, xmlConsoleWidgetFactory_, chatListWindowFactory_); + mainController_ = new MainController(chatWindowFactory_, rosterWindowFactory_, loginWindowFactory_, treeWidgetFactory_, eventWindowFactory_, settings_, application_, systemTray_, soundPlayer_, xmlConsoleWidgetFactory_, chatListWindowFactory_, options.count("latency-debug") > 0); PlatformAutoUpdaterFactory autoUpdaterFactory; if (autoUpdaterFactory.isSupported()) { diff --git a/Swift/QtUI/QtSwift.h b/Swift/QtUI/QtSwift.h index 2ebc3d5..72343d8 100644 --- a/Swift/QtUI/QtSwift.h +++ b/Swift/QtUI/QtSwift.h @@ -7,6 +7,9 @@ #ifndef SWIFT_QtSwift_H #define SWIFT_QtSwift_H +#include <boost/program_options/variables_map.hpp> +#include <boost/program_options/options_description.hpp> + #include "Swiften/Base/String.h" #include "Swiften/EventLoop/Qt/QtEventLoop.h" #include "QtLoginWindowFactory.h" @@ -14,6 +17,8 @@ #include "QtChatWindowFactory.h" #include "QtSettingsProvider.h" +namespace po = boost::program_options; + class QSplitter; namespace Swift { @@ -33,7 +38,8 @@ namespace Swift { class QtSwift : public QObject { Q_OBJECT public: - QtSwift(bool netbookMode); + QtSwift(po::variables_map options); + static po::options_description getOptionsDescription(); ~QtSwift(); private: MainController *mainController_; diff --git a/Swift/QtUI/main.cpp b/Swift/QtUI/main.cpp index 971d536..f8b805c 100644 --- a/Swift/QtUI/main.cpp +++ b/Swift/QtUI/main.cpp @@ -4,13 +4,21 @@ * See Documentation/Licenses/GPLv3.txt for more information. */ +#include <boost/program_options/options_description.hpp> +#include <boost/program_options/variables_map.hpp> +#include <boost/program_options.hpp> + + #include <QApplication> #include "QtSwift.h" int main(int argc, char* argv[]) { QApplication app(argc, argv); - bool netbookMode = argc > 1; - Swift::QtSwift swift(netbookMode); + boost::program_options::options_description desc = Swift::QtSwift::getOptionsDescription(); + boost::program_options::variables_map vm; + boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm); + boost::program_options::notify(vm); + Swift::QtSwift swift(vm); return app.exec(); } diff --git a/Swiften/Elements/Stanza.h b/Swiften/Elements/Stanza.h index aa1cf4f..f42048e 100644 --- a/Swiften/Elements/Stanza.h +++ b/Swiften/Elements/Stanza.h @@ -32,6 +32,19 @@ namespace Swift { return boost::shared_ptr<T>(); } + template<typename T> + std::vector< boost::shared_ptr<T> > getPayloads() const { + std::vector< boost::shared_ptr<T> > results; + foreach (const boost::shared_ptr<Payload>& i, payloads_) { + boost::shared_ptr<T> result(boost::dynamic_pointer_cast<T>(i)); + if (result) { + results.push_back(result); + } + } + return results; + } + + const std::vector< boost::shared_ptr<Payload> >& getPayloads() const { return payloads_; } diff --git a/Swiften/Elements/UnitTest/StanzaTest.cpp b/Swiften/Elements/UnitTest/StanzaTest.cpp index fb9b8a5..1e7e9c4 100644 --- a/Swiften/Elements/UnitTest/StanzaTest.cpp +++ b/Swiften/Elements/UnitTest/StanzaTest.cpp @@ -19,6 +19,7 @@ class StanzaTest : public CppUnit::TestFixture CPPUNIT_TEST_SUITE(StanzaTest); CPPUNIT_TEST(testConstructor_Copy); CPPUNIT_TEST(testGetPayload); + CPPUNIT_TEST(testGetPayloads); CPPUNIT_TEST(testGetPayload_NoSuchPayload); CPPUNIT_TEST(testDestructor); CPPUNIT_TEST(testDestructor_Copy); @@ -113,6 +114,21 @@ class StanzaTest : public CppUnit::TestFixture CPPUNIT_ASSERT(!p); } + void testGetPayloads() { + Message m; + boost::shared_ptr<MyPayload2> payload1(new MyPayload2()); + boost::shared_ptr<MyPayload2> payload2(new MyPayload2()); + m.addPayload(boost::shared_ptr<MyPayload1>(new MyPayload1())); + m.addPayload(payload1); + m.addPayload(boost::shared_ptr<MyPayload3>(new MyPayload3())); + m.addPayload(payload2); + + CPPUNIT_ASSERT_EQUAL((size_t)2, m.getPayloads<MyPayload2>().size()); + CPPUNIT_ASSERT_EQUAL(payload1, m.getPayloads<MyPayload2>()[0]); + CPPUNIT_ASSERT_EQUAL(payload2, m.getPayloads<MyPayload2>()[1]); + } + + void testUpdatePayload_ExistingPayload() { Message m; m.addPayload(boost::shared_ptr<MyPayload1>(new MyPayload1())); -- cgit v0.10.2-6-g49f6