Набор ret_lines инициализируется с использования того конструктора, который получает пару итераторов. Функции-члены begin() и end() класса QueryResult возвращают итераторы на номера строк набора. Таким образом, набор ret_lines создается при копировании элементов из набора left. Затем для вставки элементов из набора right вызывается функция insert(). После этого вызова набор ret_lines содержит номера строк из наборов, которые присутствуют в наборах left или right.

Функция eval() завершает работу, создавая и возвращая объект класса QueryResult, представляющий объединение соответствий. Конструктор QueryResult() (см. раздел 12.3.2) получает три аргумента: строку, представляющую запрос, указатель shared_ptr на набор соответствующих номеров строк и указатель shared_ptr на вектор, представляющий входной файл. Вызов функции rep() позволяет создать строку, а вызов функции get_file() — получить указатель shared_ptr на файл. Поскольку оба набора, left и right, относятся к тому же файлу, не имеет значения, который из них использовать для функции get_file().

Функция AndQuery::eval()

Версия функции eval() класса AndQuery подобна версии класса OrQuery, за исключением того, что она использует библиотечный алгоритм для поиска строк, общих для обоих запросов:

// возвращает пересечение наборов результатов своих операндов

QueryResult

AndQuery::eval(const TextQuery& text) const {

 // виртуальный вызов через операнды класса Query для получения

 // результирующих наборов для операндов

 auto left = lhs.eval(text), right = rhs.eval(text);

 // набор для хранения пересечения left и right

 auto ret_lines = make_shared>();

 // выводит пересечение двух диапазонов в итератор назначения

 // итератор назначения в этом вызове добавляет элементы в ret

 set_intersection(left.begin(), left.end(),

                  right.begin(), right.end(),

                  inserter(*ret_lines, ret_lines->begin()));

 return QueryResult(rep(), ret_lines, left.get_file());

}

Здесь для объединения двух наборов используется библиотечный алгоритм set_intersection, описанный в приложении А.2.8.

Алгоритм set_intersection получает пять итераторов. Первые четыре он использует для обозначения двух исходных последовательностей (см. раздел 10.5.2). Его последний аргумент обозначает получателя. Алгоритм выводит элементы, присутствующие в обеих исходных последовательностях, в результирующую.

В данном вызове получателем является итератор вставки (см. раздел 10.4.1). Результатом записи алгоритмом set_intersection в этот итератор будет вставка нового элемента в набор ret_lines.

Подобно функции eval() класса OrQuery, эта завершается созданием и возвращением объекта класса QueryResult, представляющего объединение соответствий.

Функция NotQuery::eval()

Функция eval() класса NotQuery ищет в тексте все строки, в которых операнд отсутствует.

// возвращает строки, отсутствующие в наборе результатов

// операнда QueryResult

NotQuery::eval(const TextQuery& text) const {

 // виртуальный вызов для вычисления операнда Query

 auto result = query.eval(text);

 // начать с пустого результирующего набора данных

 auto ret_lines = make_shared>();

 // следует перебрать строки, в которых присутствует операнд

 auto beg = result.begin(), end = result.end();

 // для каждой строки во входном файле, если она отсутствует

 // в result, добавить ее номер в ret_lines

 auto sz = result.get_file()->size();

 for (size_t n = 0; n != sz; ++n) {

  // если не обработаны все строки в result

  // проверить присутствие этой строки

  if (beg == end || *beg != n)

Перейти на страницу:

Похожие книги