diff --git a/libs/main/containers/picontainers.h b/libs/main/containers/picontainers.h index fb364e94..78821cf8 100644 --- a/libs/main/containers/picontainers.h +++ b/libs/main/containers/picontainers.h @@ -1,17 +1,17 @@ -/*! \addtogroup Containers - * \{ - * \file picontainers.h - * \brief - * \~english Base macros for generic containers - * \~russian Базовые макросы для контейнеров - * \~\authors - * \~english - * Ivan Pelipenko peri4ko@yandex.ru; - * Andrey Bychkov work.a.b@yandex.ru; - * \~russian - * Иван Пелипенко peri4ko@yandex.ru; - * Андрей Бычков work.a.b@yandex.ru; - * \~\} */ +//! \addtogroup Containers +//! \{ +//! \file picontainers.h +//! \brief +//! \~english Base macros for generic containers +//! \~russian Базовые макросы для контейнеров +//! \~\authors +//! \~english +//! Ivan Pelipenko peri4ko@yandex.ru; +//! Andrey Bychkov work.a.b@yandex.ru; +//! \~russian +//! Иван Пелипенко peri4ko@yandex.ru; +//! Андрей Бычков work.a.b@yandex.ru; +//! \~\} /* PIP - Platform Independent Primitives Base macros for generic containers @@ -61,105 +61,99 @@ private: }; -/*! \brief - * \~english Template reverse wrapper over any container - * \~russian Шаблонная функция обертки любого контейнера для обратного доступа через итераторы - */ +//! \brief +//! \~english Template reverse wrapper over any container +//! \~russian Шаблонная функция обертки любого контейнера для обратного доступа через итераторы template _PIReverseWrapper PIReverseWrap(C & c) {return _PIReverseWrapper(c);} template _PIReverseWrapper PIReverseWrap(const C & c) {return _PIReverseWrapper(c);} -/*! \brief - * \~english Macro for short replacement of standart "for" - * \~russian Макрос для короткой записи стандартного цикла "for" - * \~\param c - * \~english Iteration times in loop - * \~russian Количество итераций цикла - */ +//! \brief +//! \~english Macro for short replacement of standart "for" +//! \~russian Макрос для короткой записи стандартного цикла "for" +//! \~\param c +//! \~english Iteration times in loop +//! \~russian Количество итераций цикла #define piForTimes(c) for(int _i##c = 0; _i##c < c; ++_i##c) -/*! \brief - * \~english Macro for iterate any container - * \~russian Макрос для перебора любых контейнеров - * \~\deprecated - * \~english Deprecated, using only for backward compatibility. Use - * [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for). - * \~russian Устарело, используется только для обратной совместимости. Используйте - * [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for). - * \~\details - * \~english Get read/write access to each element of container. - * Iterating in forward direction. - * Example of using: - * \~russian Перебор всех элементов контейнера с доступом на чтение и запись. - * Перебор осуществляется в прямом порядке. - * Пример использования: - * \~\code - * PIVector vec; - * vec << 1 << 2 << 3; - * piForeach(int & i, vec) piCout << i; - * // 1 - * // 2 - * // 3 - * piForeach(int & i, vec) i++; - * piForeach(int & i, vec) piCout << i; - * // 2 - * // 3 - * // 4 - * \endcode - * \sa \a piForeachC, \a piForeachR, \a piForeachRC - */ +//! \brief +//! \~english Macro for iterate any container +//! \~russian Макрос для перебора любых контейнеров +//! \~\deprecated +//! \~english Deprecated, using only for backward compatibility. Use +//! [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for). +//! \~russian Устарело, используется только для обратной совместимости. Используйте +//! [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for). +//! \~\details +//! \~english Get read/write access to each element of container. +//! Iterating in forward direction. +//! Example of using: +//! \~russian Перебор всех элементов контейнера с доступом на чтение и запись. +//! Перебор осуществляется в прямом порядке. +//! Пример использования: +//! \~\code +//! PIVector vec; +//! vec << 1 << 2 << 3; +//! piForeach(int & i, vec) piCout << i; +//! // 1 +//! // 2 +//! // 3 +//! piForeach(int & i, vec) i++; +//! piForeach(int & i, vec) piCout << i; +//! // 2 +//! // 3 +//! // 4 +//! \endcode +//! \sa \a piForeachC, \a piForeachR, \a piForeachRC #define piForeach(i, c) for(i : c) -/*! \brief - * \~english Macro for iterate any container - * \~russian Макрос для перебора любых контейнеров - * \~\deprecated - * \~english Deprecated, using only for backward compatibility. Use - * [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for). - * \~russian Устарело, используется только для обратной совместимости. Используйте - * [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for). - * \~\details - * \~english Get read only access to each element of container. - * Iterating in forward direction. - * \~russian Перебор всех элементов контейнера с доступом только на чтение. - * Перебор осуществляется в прямом порядке. - * \~ \sa \a piForeach, \a piForeachR, \a piForeachRC - */ +//! \brief +//! \~english Macro for iterate any container +//! \~russian Макрос для перебора любых контейнеров +//! \~\deprecated +//! \~english Deprecated, using only for backward compatibility. Use +//! [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for). +//! \~russian Устарело, используется только для обратной совместимости. Используйте +//! [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for). +//! \~\details +//! \~english Get read only access to each element of container. +//! Iterating in forward direction. +//! \~russian Перебор всех элементов контейнера с доступом только на чтение. +//! Перебор осуществляется в прямом порядке. +//! \~ \sa \a piForeach, \a piForeachR, \a piForeachRC #define piForeachC(i, c) for(const i : c) -/*! \brief - * \~english Macro for iterate any container - * \~russian Макрос для перебора любых контейнеров - * \~\deprecated - * \~english Deprecated, using only for backward compatibility. Use - * [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for). - * \~russian Устарело, используется только для обратной совместимости. Используйте - * [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for). - * \~\details - * \~english Get read/write access to each element of container. - * Iterating in backward direction. - * \~russian Перебор всех элементов контейнера с доступом на чтение и запись. - * Перебор осуществляется в обратном порядке. - * \~ \sa \a piForeach, \a piForeachC, \a piForeachRC - */ +//! \brief +//! \~english Macro for iterate any container +//! \~russian Макрос для перебора любых контейнеров +//! \~\deprecated +//! \~english Deprecated, using only for backward compatibility. Use +//! [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for). +//! \~russian Устарело, используется только для обратной совместимости. Используйте +//! [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for). +//! \~\details +//! \~english Get read/write access to each element of container. +//! Iterating in backward direction. +//! \~russian Перебор всех элементов контейнера с доступом на чтение и запись. +//! Перебор осуществляется в обратном порядке. +//! \~ \sa \a piForeach, \a piForeachC, \a piForeachRC #define piForeachR(i, c) for(i : PIReverseWrap(c)) -/*! \brief - * \~english Macro for iterate any container - * \~russian Макрос для перебора любых контейнеров - * \~\deprecated - * \~english Deprecated, using only for backward compatibility. Use - * [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for). - * \~russian Устарело, используется только для обратной совместимости. Используйте - * [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for). - * \~\details - * \~english Get read only access to each element of container. - * Iterating in backward direction. Also has alias **piForeachCR** - * \~russian Перебор всех элементов контейнера с доступом только на чтение. - * Перебор осуществляется в обратном порядке. Также можно писать **piForeachCR** - * \~ \sa \a piForeach, \a piForeachC, \a piForeachR - */ +//! \brief +//! \~english Macro for iterate any container +//! \~russian Макрос для перебора любых контейнеров +//! \~\deprecated +//! \~english Deprecated, using only for backward compatibility. Use +//! [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for). +//! \~russian Устарело, используется только для обратной совместимости. Используйте +//! [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for). +//! \~\details +//! \~english Get read only access to each element of container. +//! Iterating in backward direction. Also has alias **piForeachCR** +//! \~russian Перебор всех элементов контейнера с доступом только на чтение. +//! Перебор осуществляется в обратном порядке. Также можно писать **piForeachCR** +//! \~ \sa \a piForeach, \a piForeachC, \a piForeachR #define piForeachRC(i, c) for(const i : PIReverseWrap(c)) #define piForeachCR piForeachRC diff --git a/libs/main/containers/picontainersmodule.h b/libs/main/containers/picontainersmodule.h index 32e19e48..aaf1e446 100644 --- a/libs/main/containers/picontainersmodule.h +++ b/libs/main/containers/picontainersmodule.h @@ -16,30 +16,139 @@ You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ -/** \defgroup Containers - * \~\brief - * \~english This module contains various standart containers realization. - * \~russian Модуль содержит основные классы контейнеров. - * - * \~\details - * Scope | Use - * ----- | ------- - * C++ | #include - * CMake | PIP - * - * \~english This includes - * \~russian В него входят - * \~ \a PIVector, \a PIDeque, \a PIMap, \a PISet, - * \a PIStack, \a PIQueue, \a PIPair, \a PIVector2D. - * - * \authors - * \~english - * Ivan Pelipenko peri4ko@yandex.ru; - * Andrey Bychkov work.a.b@yandex.ru; - * \~russian - * Иван Пелипенко peri4ko@yandex.ru; - * Андрей Бычков work.a.b@yandex.ru; -*/ +//! \defgroup Containers +//! \~\brief +//! \~english This module contains various standart containers realization. +//! \~russian Модуль содержит основные классы контейнеров. +//! \~\details +//! Scope | Use +//! ----- | ------- +//! C++ | `#include ` +//! CMake | PIP +//! +//! \~english This includes +//! \~russian В него входят +//! \~ \a PIVector, \a PIDeque, \a PIMap, \a PISet, +//! \a PIStack, \a PIQueue, \a PIPair, \a PIVector2D. +//! +//! \~english \section stl_iterators STL-Style Iterators +//! \~russian \section stl_iterators Итераторы в стиле STL +//! \~\addindex stl_iterators +//! \~english +//! \brief They are compatible with Qt's and STL's generic algorithms and are optimized for speed. +//! \details +//! For each container class, there are two STL-style iterator types: +//! one that provides read-only access and one that provides read-write access. +//! Read-only iterators should be used wherever possible +//! because they are faster than read-write iterators. +//! Read-only iterator - `const_iterator.` +//! Read-write iterator - `iterator.` +//! +//! The API of the STL iterators is modelled on pointers in an array. +//! For example, the `++` operator advances the iterator to the next item, +//! and the `*` operator returns the item that the iterator points to. +//! The `iterator` type is just a `typedef` for `T *`, +//! and the `const_iterator` type is just a `typedef` for `const T *`. +//! STL-style iterators point directly at items. +//! The `begin()` function of a container +//! returns an iterator that points to the first item in the container. +//! The `end()` function of a container returns an iterator to the imaginary item +//! one position past the last item in the container. +//! `end()` marks an invalid position; it must never be dereferenced. +//! It is typically used in a loop's break condition. +//! +//! Example: +//! \code +//! for (PIVector::const_iterator i = v.begin(); i != v.end(); ++i) piCout << *i; +//! std::for_each(v.begin(), v.end(), [](int n){std::cout << n << ' ';}); +//! \endcode +//! +//! If the list is empty, `begin()` equals `end()`, so we never execute the loop. +//! +//! ![iterators](doc/images/pivector_rbegin.png) +//! +//! The following table summarizes the STL-style iterators' API: +//! Expression | Behavior +//! ---------- | -------------------- +//! `*i` | Returns the current item +//! `++i` | Advances the iterator to the next item +//! `i += n` | Advances the iterator by `n` items +//! `--i` | Moves the iterator back by one item +//! `i -= n` | Moves the iterator back by `n` items +//! `i - j` | Returns the number of items between iterators `i` and `j` +//! +//! The `++` and `--` operators are available both as prefix `(++i, --i)` +//! and postfix `(i++, i--)` operators. +//! The prefix versions modify the iterators +//! and return a reference to the modified iterator; +//! the postfix versions take a copy of the iterator before they modify it, and return that copy. +//! In expressions where the return value is ignored, +//! we recommend that you use the prefix operators `(++i, --i)`, as these are slightly faster. +//! For non-const iterator types, the return value of the unary `*` operator +//! can be used on the left side of the assignment operator. +//! +//! \~russian +//! \brief Они совместимы с базовыми алгоритмами Qt и STL и оптимизированы по скорости. +//! \details +//! Для каждого контейнерного класса есть два типа итераторов в стиле STL: +//! один из них предоставляет доступ только для чтения, а другой - доступ для чтения-записи. +//! Итераторы только для чтения должны использоваться везде, где это только возможно, +//! так как они быстрее, чем итераторы для чтения-записи. +//! Итератор только для чтения - `const_iterator.` +//! Итератор для чтения-записи - `iterator.` +//! +//! API итераторов в стиле STL сделан по образцу указателей в массиве. +//! Например, оператор `++` перемещает итератор к следующему элементу, +//! а оператор `*` возвращает элемент, на который позиционирован итератор. +//! Тип `iterator` - это как `typedef` для `T *`, +//! а тип `const_iterator` - как `typedef` для `const T *`. +//! Итераторы в стиле STL указывают непосредственно на элемент. +//! Функция контейнера `begin()` возвращает итератор, указывающий на первый элемент контейнера. +//! Функция контейнера `end()` возвращает итератор, указывающий на воображаемый элемент, +//! находящийся в позиции, следующей за последним элементом контейнера. +//! `end()` обозначает несуществующую позицию; +//! он никогда не должен разыменовываться. +//! Обычно, он используется, как условие выхода из цикла. +//! +//! Например: +//! \code +//! for (PIVector::const_iterator i = v.begin(); i != v.end(); ++i) piCout << *i; +//! std::for_each(v.begin(), v.end(), [](int n){std::cout << n << ' ';}); +//! \endcode +//! +//! Если список пуст, то begin() равен end(), поэтому цикл никогда не выполнится. +//! +//! ![итераторы](doc/images/pivector_rbegin.png) +//! +//! В следующей таблице подводится итог API итераторов в стиле STL: +//! Выражение | Поведение +//! --------- | -------------------- +//! `*i` | Возвращает текущий элемент +//! `++i` | Перемещает итератор к следующему элементу +//! `i += n` | Перемещает итератор вперед на `n` элементов +//! `--i` | Перемещает итератор на один элемент назад +//! `i -= n` | Перемещает итератор назад на `n` элементов +//! `i - j` | Возвращает количество элементов, находящихся между итераторами `i` и `j` +//! +//! Оба оператора `++` и `--` могут использоваться и как префиксные `(++i, --i)` +//! и как постфиксные `(i++, i--)` операторы. +//! Префиксная версия изменяет итератор, и возвращает ссылку на измененный итератор; +//! постфиксная версия, берет копию итератора перед его изменением, и возвращает эту копию. +//! В выражениях, в которых возвращаемое значение игнорируется, +//! мы рекомендуем использовать префиксную версию `(++i, --i)`, +//! так как она несколько быстрее. +//! +//! Для неконстантных итераторов, возвращаемое значение унарного оператора `*` +//! может быть использовано с левой стороны от оператора присваивания. +//! +//! \authors +//! \~english +//! Ivan Pelipenko peri4ko@yandex.ru; +//! Andrey Bychkov work.a.b@yandex.ru; +//! \~russian +//! Иван Пелипенко peri4ko@yandex.ru; +//! Андрей Бычков work.a.b@yandex.ru; + #ifndef PICONTAINERSMODULE_H #define PICONTAINERSMODULE_H @@ -52,4 +161,5 @@ #include "pistack.h" #include "pivector2d.h" + #endif // PICONTAINERSMODULE_H diff --git a/libs/main/containers/pivector.h b/libs/main/containers/pivector.h index 86390327..2b44ea67 100644 --- a/libs/main/containers/pivector.h +++ b/libs/main/containers/pivector.h @@ -11,7 +11,7 @@ //! \~russian //! Иван Пелипенко peri4ko@yandex.ru; //! Андрей Бычков work.a.b@yandex.ru; -//! \~\} */ +//! \~\} /* PIP - Platform Independent Primitives Sequence linear container aka dynamic size array of any type @@ -130,8 +130,7 @@ public: //! \~\details //! \~\code //! PIVector v{1,2,3}; - //! piCout << v; - //! // {1, 2, 3} + //! piCout << v; // {1, 2, 3} //! \endcode inline PIVector(std::initializer_list init_list): piv_data(0), piv_size(0), piv_rsize(0) { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) @@ -155,8 +154,7 @@ public: //! \~russian Позволяет передавать [Лямбда-выражения](https://ru.cppreference.com/w/cpp/language/lambda) для создания элементов в конструкторе. //! \~\code //! PIVector v(5, [](size_t i){return i*2;}); - //! piCout << v; - //! // {0, 2, 4, 6, 8} + //! piCout << v; // {0, 2, 4, 6, 8} //! \endcode inline PIVector(size_t size, std::function f): piv_data(0), piv_size(0), piv_rsize(0) { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) @@ -284,6 +282,7 @@ public: //! //! \~english If the vector is empty, the returned iterator is equal to \a end. //! \~russian Если массив - пуст, возвращаемый итератор будет равен \a end. + //! \~\return \ref stl_iterators //! \~\sa \a end, \a rbegin, \a rend inline iterator begin() {return iterator(this, 0);} @@ -292,9 +291,11 @@ public: //! \~russian Итератор на элемент, следующий за последним элементом. //! \~\details ![begin, end](doc/images/pivector_begin.png) //! - //! \~english This element acts as a placeholder; attempting to access it results in undefined behavior. + //! \~english This element acts as a placeholder; + //! attempting to access it results in undefined behavior. //! \~russian Этот элемент существует лишь условно, //! попытка доступа к нему приведёт к выходу за разрешенную память. + //! \~\return \ref stl_iterators //! \~\sa \a begin, \a rbegin, \a rend inline iterator end() {return iterator(this, piv_size);} @@ -311,6 +312,7 @@ public: //! \~russian Итератор для прохода массива в обратном порядке. //! Указывает на последний элемент. //! Если массив пустой, то совпадает с итератором \a rend. + //! \~\return \ref stl_iterators //! \~\sa \a rend, \a begin, \a end inline reverse_iterator rbegin() {return reverse_iterator(this, piv_size - 1);} @@ -325,6 +327,7 @@ public: //! Указывает на элемент, предшествующий первому элементу. //! Этот элемент существует лишь условно, //! попытка доступа к нему приведёт к выходу за разрешенную память. + //! \~\return \ref stl_iterators //! \~\sa \a rbegin, \a begin, \a end inline reverse_iterator rend() {return reverse_iterator(this, -1);} @@ -382,12 +385,11 @@ public: //! \~russian **true** если хотя бы для одного элемента передаваемая функция возвращает **true**, //! в остальных случаях **false**. //! Метод возвращает **false** при любом условии для пустого массива. + //! \~\details //! \~\code //! PIVector v{1, 2, 8, 9}; - //! piCout << v.any([](int e){return e % 2 == 0;}); - //! // true - //! piCout << v.any([](int e){return e == 3;}); - //! // false + //! piCout << v.any([](int e){return e % 2 == 0;}); // true + //! piCout << v.any([](int e){return e == 3;}); // false //! \endcode //! \~\sa \a every, \a contains, \a etries, \a forEach inline bool any(std::function test) const { @@ -406,12 +408,11 @@ public: //! \~russian **true** если для всех элементов передаваемая функция возвращает **true**, //! в остальных случаях **false**. //! Метод возвращает **true** при любом условии для пустого массива. + //! \~\details //! \~\code //! PIVector v{1, 2, 8, 9}; - //! piCout << v.every([](int e){return e % 2 == 0;}); - //! // false - //! piCout << v.every([](int e){return e > 0;}); - //! // true + //! piCout << v.every([](int e){return e % 2 == 0;}); // false + //! piCout << v.every([](int e){return e > 0;}); // true //! \endcode //! \~\sa \a any, \a contains, \a entries, \a forEach inline bool every(std::function test) const { @@ -433,11 +434,9 @@ public: //! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти. //! \~\code //! PIVector v{1, 2, 8, 9}; - //! piCout << v[2]; - //! // 8 + //! piCout << v[2]; // 8 //! v[2] = 5; - //! piCout << v; - //! // 1, 2, 5, 9 + //! piCout << v; // 1, 2, 5, 9 //! \endcode //! \~\sa \a at inline T & operator [](size_t index) {return piv_data[index];} @@ -501,78 +500,141 @@ public: //! \~russian Оператор сравнения с массивом `t`. inline bool operator !=(const PIVector & t) const {return !(*this == t);} - inline bool operator <(const PIVector & t) const { - if (piv_size != t.piv_size) return piv_size < t.piv_size; - for (size_t i = 0; i < piv_size; ++i) { - if ((*this)[i] != t[i]) return (*this)[i] < t[i]; - } - return false; - } - inline bool operator >(const PIVector & t) const { - if (piv_size != t.piv_size) return piv_size > t.piv_size; - for (size_t i = 0; i < piv_size; ++i) { - if ((*this)[i] != t[i]) return (*this)[i] > t[i]; - } - return false; - } - //! \~\brief //! \~english Tests if element `e` exists in the array. //! \~russian Проверяет наличие элемента `e` в массиве. + //! \~\details + //! \~english Optional argument `start` - the position in this array at which to begin searching. + //! If the index is greater than or equal to the array's size, + //! **false** is returned, which means the array will not be searched. + //! If the provided index value is a negative number, + //! it is taken as the offset from the end of the array. + //! Note: if the provided index is negative, + //! the array is still searched from front to back. + //! Default: 0 (entire array is searched). + //! \~russian Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск. + //! Если индекс больше или равен длине массива, + //! возвращается **false**, что означает, что массив даже не просматривается. + //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива. + //! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив. + //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу. + //! Значение по умолчанию равно 0, что означает, что просматривается весь массив. + //! \~\code + //! PIVector v{1, 2, 3, 4}; + //! piCout << v.contains(3); // true + //! piCout << v.contains(5); // false + //! piCout << v.contains(3, 3); // false + //! piCout << v.contains(3, -2); // true + //! piCout << v.contains(3, -99); // true + //! \endcode //! \~\return //! \~english **true** if the array contains an occurrence of element `e`, //! otherwise it returns **false**. //! \~russian **true** если элемент `e` присутствует в массиве, //! в остальных случаях **false**. - //! \~\code - //! PIVector v{1, 2, 3, 4}; - //! piCout << v.contains(3); - //! // true - //! \endcode //! \~\sa \a every, \a any, \a etries, \a forEach - inline bool contains(const T & e) const { - for (size_t i = 0; i < piv_size; ++i) { - if (e == piv_data[i]) { - return true; - } + inline bool contains(const T & e, ssize_t start = 0) const { + if (start < 0) { + start = piv_size + start; + if (start < 0) start = 0; + } + for (size_t i = start; i < piv_size; ++i) { + if (e == piv_data[i]) return true; } return false; } - inline int entries(const T & e, size_t start = 0) const { + //! \~\brief + //! \~english Count elements equal `e` in the array. + //! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве. + //! \~\details + //! \~english Optional argument `start` - the position in this array at which to begin searching. + //! If the index is greater than or equal to the array's size, + //! 0 is returned, which means the array will not be searched. + //! If the provided index value is a negative number, + //! it is taken as the offset from the end of the array. + //! Note: if the provided index is negative, + //! the array is still searched from front to back. + //! Default: 0 (entire array is searched). + //! \~russian Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск. + //! Если индекс больше или равен длине массива, + //! возвращается 0, что означает, что массив даже не просматривается. + //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива. + //! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив. + //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу. + //! Значение по умолчанию равно 0, что означает, что просматривается весь массив. + //! \~\code + //! PIVector v{2, 2, 4, 2, 6}; + //! piCout << v.entries(2); // 3 + //! piCout << v.entries(2, 2); // 1 + //! piCout << v.entries(2, -4); // 2 + //! \endcode + //! \~\sa \a every, \a any, \a contains, \a forEach + inline int entries(const T & e, ssize_t start = 0) const { int ec = 0; - if (start >= piv_size) return ec; + if (start < 0) { + start = piv_size + start; + if (start < 0) start = 0; + } for (size_t i = start; i < piv_size; ++i) { if (e == piv_data[i]) ++ec; } return ec; } - inline int entries(std::function test, size_t start = 0) const { + //! \~\brief + //! \~english Count elements in the array passes the test implemented by the provided function `test`. + //! \~russian Подсчитывает количество элементов в массиве, проходящих по условию, заданному в передаваемой функции `test`. + //! \~\details + //! \~english Overloaded function. + //! Optional argument `start` - the position in this array at which to begin searching. + //! If the index is greater than or equal to the array's size, + //! 0 is returned, which means the array will not be searched. + //! If the provided index value is a negative number, + //! it is taken as the offset from the end of the array. + //! Note: if the provided index is negative, + //! the array is still searched from front to back. + //! Default: 0 (entire array is searched). + //! \~russian Перегруженная функция. + //! Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск. + //! Если индекс больше или равен длине массива, + //! возвращается 0, что означает, что массив даже не просматривается. + //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива. + //! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив. + //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу. + //! Значение по умолчанию равно 0, что означает, что просматривается весь массив. + //! \~\sa \a every, \a any, \a contains, \a forEach + inline int entries(std::function test, ssize_t start = 0) const { int ec = 0; - if (start >= piv_size) return ec; + if (start < 0) { + start = piv_size + start; + if (start < 0) start = 0; + } for (size_t i = start; i < piv_size; ++i) { if (test(piv_data[i])) ++ec; } return ec; } - inline ssize_t indexOf(const T & e, size_t start = 0) const { - if (start >= piv_size) return -1; + + inline ssize_t indexOf(const T & e, ssize_t start = 0) const { + if (start < 0) { + start = piv_size + start; + if (start < 0) start = 0; + } for (size_t i = start; i < piv_size; ++i) { - if (e == piv_data[i]) { - return i; - } + if (e == piv_data[i]) return i; } return -1; } - inline ssize_t indexWhere(std::function test, size_t start = 0) const { - if (start >= piv_size) return -1; + inline ssize_t indexWhere(std::function test, ssize_t start = 0) const { + if (start < 0) { + start = piv_size + start; + if (start < 0) start = 0; + } for (size_t i = start; i < piv_size; ++i) { - if (test(piv_data[i])) { - return i; - } + if (test(piv_data[i])) return i; } return -1; } @@ -581,9 +643,7 @@ public: if (start < 0) start = piv_size - 1; else start = piMin(piv_size - 1, start); for (ssize_t i = start; i >= 0; --i) { - if (e == piv_data[i]) { - return i; - } + if (e == piv_data[i]) return i; } return -1; } @@ -592,9 +652,7 @@ public: if (start < 0) start = piv_size - 1; else start = piMin(piv_size - 1, start); for (ssize_t i = start; i >= 0; --i) { - if (test(piv_data[i])) { - return i; - } + if (test(piv_data[i])) return i; } return -1; }