Блок задач

3. Структуры данных

Темы
Сложность 5

Задача «Чтение конфигурации»

Разработать функцию, читающую конфигурацию из текстового файла.

Входные данные

Конфигурационный файл представляет собой текстовый файл, где строки имеют формат ключ значение. И ключ, и значение представляют собой строки:

name foo
value 20

Лишние пробелы игнорируются, также допустимы пустые строки:

     name           foo

value                  20

Допустимы комментарии:

foo 200 # 400
#bar 400

Все символы, начиная с #, считаются пробельными и игнорируются.

Для задания значений с пробелами можно использовать следующую форму:

name " Vasya Pupkin "   # пробелы в начале и конце строки
spaces '     '  # здесь 5 пробелов

Строки, содержащие символы ' и ", могут быть записаны следующим образом:

double_quote   '"'
single_quote "'"
both_quotes "'\""

Обратная косая черта \ играет роль escape-символа (аналогично C) и позволяет задавать следующие спецсимволы (при употреблении внутри закавыченной строки "…" или '…'):

  • \' – одиночная кавычка;
  • \" – двойная кавычка;
  • \n – символ перевода строки (ASCII-код 10);
  • \t – символ табуляции (ASCII-код 9).
  • \\ — сам символ обратной косой черты.

Задача

Реализовать функцию

map<string, string> readConfiguration(istream &is,
                                      string *perrors = nullptr);

… которая бы читала конфигурационный файл из входного потока и возвращала считанные значения в форме map.

Ошибки, связанные с неверным синтаксисом, нужно возвращать в строке по указателю perrors (если он ненулевой). При этом функция всё же должна вернуть то, что смогла распознать в файле.

Принципы тестирования

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