diff options
Diffstat (limited to 'src/third_party/boost/libs/program_options/src/options_description.cpp')
-rw-r--r-- | src/third_party/boost/libs/program_options/src/options_description.cpp | 624 |
1 files changed, 0 insertions, 624 deletions
diff --git a/src/third_party/boost/libs/program_options/src/options_description.cpp b/src/third_party/boost/libs/program_options/src/options_description.cpp deleted file mode 100644 index 0d8dfd48be5..00000000000 --- a/src/third_party/boost/libs/program_options/src/options_description.cpp +++ /dev/null @@ -1,624 +0,0 @@ -// 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; - bool had_full_match = false; - 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)); - found = m_options[i]; - had_full_match = true; - } - else - { - // FIXME: the use of 'key' here might not - // be the best approach. - approximate_matches.push_back(m_options[i]->key(name)); - if (!had_full_match) - 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]; - } - } - -}} |