Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Library Overview

Boost , The Boost C++ Libraries BoostBook Documentation Subset , Chapter 27. Boost.Program_options

BoostC++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Library Overview

В учебном разделе мы увидели несколько примеров использования библиотеки. Здесь мы опишем общий дизайн библиотеки, включая основные компоненты и их функции.

Библиотека имеет три основных компонента:

  • Компонент описания опционов, который описывает разрешенные опционы и что делать со значениями опционов.

  • Компонент парсеров, который использует эту информацию, чтобы найти имена и значения опций в источниках ввода и вернуть их.

  • Компонент хранения, который обеспечивает интерфейс для доступа к значению опции. Он также преобразует представление строк значений, которые парсеры возвращают в желаемые типы C++.

Чтобы быть немного более конкретным, класс<options_description>является компонентом описания опций, функция<parse_command_line>- компонентом парсеров, а класс<variables_map>- компонентом хранения.

В руководстве мы узнали, как эти компоненты могут использоваться функцией<main>для анализа командной строки и файла конфигурации. Прежде чем вдаваться в подробности каждого компонента, несколько заметок о мире за пределами<main>.

Для этого внешнего мира наиболее важным является компонент хранения. Он предоставляет класс, в котором хранятся все значения опций, и этот класс может свободно передаваться по вашей программе модулям, которые нуждаются в доступе к опциям. Все остальные компоненты можно использовать только в том месте, где выполняется фактический разбор. Тем не менее, отдельные программные модули могут также иметь смысл описывать свои варианты и передавать их в основной модуль, который объединит все варианты. Конечно, это важно только тогда, когда количество вариантов велико и декларирование их в одном месте становится хлопотным.

Options Description Component

Компонент описания опций имеет три основных класса:<option_description>,<value_semantic>и<options_description>. Первые два вместе описывают один вариант. Класс<option_description>содержит имя опции, описание и указатель на<value_semantic>, который, в свою очередь, знает тип значения опции и может анализировать значение, применять значение по умолчанию и так далее. Класс<options_description>является контейнером для экземпляров<option_description>.

Почти для каждой библиотеки эти классы могут быть созданы обычным способом: то есть вы создадите новые варианты с помощью конструкторов, а затем назовете метод<add><options_description>. Однако это слишком многословно для объявления 20 или 30 вариантов. Эта проблема привела к созданию синтаксиса, который вы уже видели:

options_description desc;
desc.add_options()
    ("help", "produce help")
    ("optimization", value<int>()->default_value(10), "optimization level")
    ;

Призыв к функции<value>создает экземпляр класса, производного от класса<value_semantic>:<typed_value>. Этот класс содержит код для разбора значений определенного типа и содержит ряд методов, которые могут быть вызваны пользователем для указания дополнительной информации. (Это, по сути, эмулирует названные параметры конструктора.) Призывы<operator()>к объекту, возвращенному<add_options>, перенаправляют аргументы конструктору<option_description>класса и добавляют новый экземпляр.

Обратите внимание, что в дополнение к<value>библиотека предоставляет<bool_switch>функцию, и пользователь может написать свою собственную функцию, которая возвращает другие подклассы<value_semantic>с различным поведением. В этом разделе мы поговорим только о функции<value>.

Информация о варианте делится на синтаксическую и семантическую. Синтаксическая информация включает в себя название опции и количество токенов, которые могут быть использованы для указания значения. Эта информация используется парсерами для группирования токенов в пары (имя, значение), где значение является просто вектором строк (<std::vector<std::string>>). Семантический слой отвечает за преобразование значения опции в более удобные типы C++.

Это разделение является важной частью библиотечного дизайна. Парсеры используют только синтаксический слой, который отнимает часть свободы использования чрезмерно сложных структур. Например, не так просто разобрать синтаксис, как:

calc --expression=1 + 2/3

Потому что невозможно разобрать

1 + 2/3

Не зная, что это выражение С. С небольшой помощью пользователя задача становится тривиальной, а синтаксис понятен:

calc --expression="1 + 2/3"

Syntactic Information

Синтаксическая информация предоставляется классом<boost::program_options::options_description>и некоторыми методами класса<boost::program_options::value_semantic>и включает:

  • название опции, используемой для идентификации опции внутри программы,

  • описание опции, которая может быть представлена пользователю,

  • допустимое количество исходных токенов, содержащих значение опционов, которое используется при разборе.

Рассмотрим следующий пример:

options_description desc;
desc.add_options()
    ("help", "produce help message")
    ("compression", value<string>(), "compression level")
    ("verbose", value<string>()->implicit_value("0"), "verbosity level")
    ("email", value<string>()->multitoken(), "email to send to")
    ;
      

Для первого параметра мы указываем только название и описание. Никакое значение не может быть указано в парсируемом источнике. Для первого варианта пользователь должен указать значение, используя один токен. Для третьего варианта пользователь может либо предоставить один токен для значения, либо вообще не предоставлять токен. Для последнего варианта значение может охватывать несколько токенов. Например, следующая командная строка ОК:

          test --help --compression 10 --verbose --email beadle@mars beadle2@mars
      

Description formatting

Иногда описание может получиться довольно длинным, например, когда несколько значений опции нуждаются в отдельной документации. Ниже мы опишем некоторые простые механизмы форматирования, которые вы можете использовать.

Строка описания имеет один или несколько абзацев, разделенных символом новой строки («n»). Когда выводится опция, библиотека вычисляет отступ для описания опций. Каждый пункт выводится в виде отдельной строки с таким указанием. Если абзац не помещается на одной строке, он накладывается на несколько строк (которые будут иметь один и тот же отступ).

Вы можете указать дополнительный отступ для первого указанного, вставив пробелы в начале абзаца. Например:

options.add_options()
    ("help", "   A long help msg a long help msg a long help msg a long help
msg a long help msg a long help msg a long help msg a long help msg ")
    ;
        

Укажите четырехмерный отступ для первой строки. Результат будет выглядеть так:

  --help                    A long help msg a long
                        help msg a long help msg
                        a long help msg a long
                        help msg a long help msg
                        a long help msg a long
                        help msg
        

Для случая, когда строка завернута, вы можете захотеть дополнительный отступ для завернутого текста. Это можно сделать, вставив символ табулятора ('\t') в нужное положение. Например:

options.add_options()
      ("well_formated", "As you can see this is a very well formatted
option description.\n"
                        "You can do this for example:\n\n"
                        "Values:\n"
                        "  Value1: \tdoes this and that, bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla\n"
                        "  Value2: \tdoes something else, bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla\n\n"
                        "    This paragraph has a first line indent only,
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla");
        

будет производить:

  --well_formated       As you can see this is a
                        very well formatted
                        option description.
                        You can do this for
                        example:
                        Values:
                          Value1: does this and
                                  that, bla bla
                                  bla bla bla bla
                                  bla bla bla bla
                                  bla bla bla bla
                                  bla
                          Value2: does something
                                  else, bla bla
                                  bla bla bla bla
                                  bla bla bla bla
                                  bla bla bla bla
                                  bla
                            This paragraph has a
                        first line indent only,
                        bla bla bla bla bla bla
                        bla bla bla bla bla bla
                        bla bla bla
        

Характер вкладки удаляется перед выходом. Допускается только один табулатор на абзац, в противном случае за исключением типа program_options::error. Наконец, табулатор игнорируется, если он не находится на первой строке абзаца или находится на последней возможной позиции первой строки.

Semantic Information

Семантическая информация полностью предоставлена классом<boost::program_options::value_semantic>. Например:

options_description desc;
desc.add_options()
    ("compression", value<int>()->default_value(10), "compression level")
    ("email", value< vector<string> >()
        ->composing()->notifier(&your_function), "email")
    ;

В этих декларациях указывается, что значение по умолчанию первого варианта составляет 10, что второй вариант может появиться несколько раз и все экземпляры должны быть объединены, и что после проведения разбора библиотека вызовет функцию<&your_function>, передавая значение опции «электронная почта» в качестве аргумента.

Positional Options

Наше определение опции как пары (имя, значение) просто и полезно, но в одном особом случае командной строки есть проблема. Командная строка может включать в себяпозиционную опцию, которая вообще не указывает никакого имени, например:

          archiver --compression=9 /etc/passwd
        

Здесь элемент «/etc/passwd» не имеет названия опции.

Одно из решений заключается в том, чтобы попросить пользователя самостоятельно извлечь позиционные опции и обрабатывать их по своему усмотрению. Тем не менее, есть более приятный подход - предоставить метод автоматического присвоения имен для позиционных опций, чтобы вышеуказанная командная строка могла интерпретироваться так же, как:

          archiver --compression=9 --input-file=/etc/passwd
        

Класс<positional_options_description>позволяет парсеру командной строки присваивать имена. Класс определяет, сколько позиционных опций разрешено, и для каждого разрешенного опциона указывает название. Например:

positional_options_description pd; pd.add("input-file", 1);

Уточняется, что для ровно одного, во-первых, позиционного варианта имя будет «вход-файл».

Можно указать, что номеру или даже всем позиционным опциям присваивается одно и то же имя.

positional_options_description pd;
pd.add("output-file", 2).add("input-file", -1);

В приведенном выше примере первые два позиционных варианта будут связаны с именем «выход-файл», а любые другие с именем «вход-файл».

[Warning] Warning

Класс<positional_options_description>определяет только перевод с позиции на имя, и имя опции должно быть зарегистрировано с экземпляром класса<options_description>.

Parsers Component

Компонент парсера разделяет источники входа на пары (имя, значение). Каждый парсер ищет возможные варианты и консультируется с компонентом описания вариантов, чтобы определить, известен ли вариант и как определяется его значение. В простейшем случае явно указывается название, что позволяет библиотеке решать, известен ли такой вариант. Если это известно, то<value_semantic>пример определяет, как указана величина. (Если не известно, то делается исключение.) Распространены случаи, когда значение явно указано пользователем, и когда значение не может быть указано пользователем, но наличие опции подразумевает некоторое значение (например,<true>). Таким образом, парсер проверяет, что значение указывается при необходимости и не указывается, когда не требуется, и возвращает новую (имя, значение) пару.

Чтобы вызвать парсер, вы обычно вызываете функцию, передавая описание опций и командную строку или файл конфигурации или что-то еще. Результаты парсинга возвращаются как экземпляр класса<parsed_options>. Как правило, этот объект передается непосредственно компоненту хранения. Тем не менее, он также может быть использован непосредственно или пройти некоторую дополнительную обработку.

Есть три исключения из вышеупомянутой модели — все они связаны с традиционным использованием командной строки. Хотя они требуют некоторой поддержки со стороны компонента описания опций, дополнительная сложность допустима.

  • Имя, указанное в командной строке, может отличаться от имени опции — обычно используется псевдоним «короткое имя опции» для более длинного имени. Также принято позволять указывать сокращенное имя в командной строке.

  • Иногда желательно указать значение в виде нескольких токенов. Например, опция «--email-recipient» может сопровождаться несколькими электронными письмами, каждое из которых является отдельным маркером командной строки. Это поведение поддерживается, хотя оно может привести к разбору неясностей и не включено по умолчанию.

  • Командная строка может содержать позиционные опции — элементы, не имеющие названия. Парсер командной строки предоставляет механизм для угадывания имен для таких опций, как мы видели в руководстве.

Storage Component

Компонент хранения отвечает за:

  • Хранение конечных значений опциона в специальном классе и в обычных переменных

  • Распределение приоритетов между различными источниками.

  • Функции, определяемые пользователем<notify>, с конечными значениями опций.

Рассмотрим пример:

variables_map vm;
store(parse_command_line(argc, argv, desc), vm);
store(parse_config_file("example.cfg", desc), vm);
notify(vm);

Класс<variables_map>используется для хранения значений опции. Два вызова к функции<store>добавляют значения, найденные в командной строке и в файле конфигурации. Наконец, вызов функции<notify>запускает функции уведомлений, определенные пользователем, и сохраняет значения в регулярные переменные, если это необходимо.

Приоритет обрабатывается простым способом: функция<store>не изменит значение опции, если она уже назначена. В этом случае, если командная строка указывает значение опции, любое значение в файле конфигурации игнорируется.

[Warning] Warning

Не забудьте вызвать функцию<notify>после того, как вы сохранили все парсированные значения.

Specific parsers

Configuration file parser

Функция<parse_config_file>реализует разбор простых INI-подобных конфигурационных файлов. Синтаксис файла конфигурации основан на строке:

  • Линия в форме:

    <
    name=value
           
    >

    дает значение опциону.

  • Линия в форме:

    <
    [section name]
           
    >

    вводит новый раздел в файл конфигурации.

  • Персонаж<#>вводит комментарий, который охватывает до конца строки.

Имена опций относятся к именам разделов, поэтому следующая часть файла конфигурации:

[gui.accessibility]
visual_bell=yes
      

является эквивалентным

gui.accessibility.visual_bell=yes
      

Environment variables parser

Переменные средыявляются струнными переменными, которые доступны для всех программ через<getenv>функцию библиотеки времени выполнения C. Операционная система позволяет устанавливать начальные значения для данного пользователя, а значения могут быть дополнительно изменены в командной строке. Например, в Windows можно использовать<autoexec.bat>файл или (в последних версиях) диалог<Control Panel/System/Advanced/Environment Variables>, а также Unix & #8212; файлы</etc/profile>,<~/.profile>и<~/.bash_profile>. Поскольку переменные среды могут быть установлены для всей системы, они особенно подходят для опций, которые применяются ко всем программам.

Переменные среды можно разобрать с помощью функции<parse_environment>. Функция имеет несколько перегруженных версий. Первый параметр всегда является экземпляром<options_description>, а второй определяет, какие переменные должны быть обработаны, и какие имена опций должны соответствовать ему. Для описания второго параметра необходимо рассмотреть условности имен переменных среды.

Если у вас есть опция, которая должна быть указана через переменную среды, вам нужно составить имя переменной. Чтобы избежать столкновений имен, мы предлагаем использовать достаточно уникальный префикс для переменных среды. Кроме того, в то время как имена опций наиболее вероятны в нижнем случае, переменные среды обычно используют верхний случай. Так, для названия опции<proxy>переменная среды может быть названа<BOOST_PROXY>. Во время разбора необходимо выполнить обратное преобразование имен. Это достигается путем прохождения выбранного префикса в качестве второго параметра функции<parse_environment>. Скажем, если вы передадите<BOOST_>в качестве префикса, и есть две переменные,<CVSROOT>и<BOOST_PROXY>, первая переменная будет проигнорирована, а вторая будет преобразована в опцию<proxy>.

Вышеприведенная логика во многих случаях достаточна, но также можно пройти, как второй параметр функции<parse_environment>, любую функцию, принимающую<std::string>и возвращающую<std::string>. Эта функция будет вызываться для каждой переменной среды и должна возвращать либо название опции, либо пустую строку, если переменная должна быть проигнорирована.

Annotated List of Symbols

Следующая таблица описывает все важные символы в библиотеке для быстрого доступа.

Symbol Description
Options description component
<options_description> описывает ряд вариантов
<value> определяет стоимость опциона
Parsers component
<parse_command_line> парсинг командной строки (упрощенный интерфейс)
<basic_command_line_parser> Парс командной строки (расширенный интерфейс)
<parse_config_file> parses config файл
<parse_environment> парсовая среда
Storage component
<variables_map> Хранение для значений опционов

PrevUpHomeNext

Статья Library Overview раздела The Boost C++ Libraries BoostBook Documentation Subset Chapter 27. Boost.Program_options может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: Chapter 27. Boost.Program_options ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 17:38:01/0.011981010437012/0