Files
pip/libs/main/containers/picontainers.h
2026-03-07 17:00:45 +03:00

277 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! \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
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICONTAINERS_H
#define PICONTAINERS_H
#include "picout.h"
#include "piintrospection_containers.h"
#ifdef MAC_OS
# include <stdlib.h>
#else
# include <malloc.h>
#endif
#include <algorithm>
#include <functional>
#include <initializer_list>
#include <new>
#include <string.h>
#include <type_traits>
//! \ingroup Containers
//! \~\brief
//! \~english Reverse-iteration wrapper for range-based loops.
//! \~russian Обёртка для обратного обхода в range-based циклах.
template<typename C>
class _PIReverseWrapper {
public:
//! \~english Wraps container `c` for reverse iteration.
//! \~russian Оборачивает контейнер `c` для обратного обхода.
_PIReverseWrapper(C & c): c_(c) {}
//! \~english Wraps constant container `c` for reverse iteration.
//! \~russian Оборачивает константный контейнер `c` для обратного обхода.
_PIReverseWrapper(const C & c): c_(const_cast<C &>(c)) {}
//! \~english Returns iterator to the first element in reverse order.
//! \~russian Возвращает итератор на первый элемент в обратном порядке.
typename C::reverse_iterator begin() { return c_.rbegin(); }
//! \~english Returns iterator following the last reversed element.
//! \~russian Возвращает итератор на элемент за последним при обратном обходе.
typename C::reverse_iterator end() { return c_.rend(); }
//! \~english Returns constant iterator to the first element in reverse order.
//! \~russian Возвращает константный итератор на первый элемент в обратном порядке.
typename C::const_reverse_iterator begin() const { return c_.rbegin(); }
//! \~english Returns constant iterator following the last reversed element.
//! \~russian Возвращает константный итератор на элемент за последним при обратном обходе.
typename C::const_reverse_iterator end() const { return c_.rend(); }
private:
C & c_;
};
//! \ingroup Containers
//! \~\brief
//! \~english Common growth constants for generic containers.
//! \~russian Общие константы роста для универсальных контейнеров.
class PIP_EXPORT _PIContainerConstantsBase {
public:
//! \~english Calculates minimum power-of-two capacity for element size `szof`.
//! \~russian Вычисляет минимальную ёмкость степени двойки для элемента размера `szof`.
static size_t calcMinCountPoT(size_t szof);
//! \~english Calculates the last capacity that still grows by powers of two.
//! \~russian Вычисляет последнюю ёмкость, которая ещё растёт степенями двойки.
static size_t calcMaxCountForPoT(size_t szof);
//! \~english Calculates linear growth step after power-of-two expansion.
//! \~russian Вычисляет линейный шаг роста после расширения степенями двойки.
static size_t calcStepAfterPoT(size_t szof);
};
//! \ingroup Containers
//! \~\brief
//! \~english Type-specific container growth constants.
//! \~russian Константы роста контейнеров для заданного типа.
template<typename T>
class _PIContainerConstants {
public:
//! \~english Returns the minimum power-of-two capacity for type `T`.
//! \~russian Возвращает минимальную ёмкость степени двойки для типа `T`.
static size_t minCountPoT() {
static const size_t ret = _PIContainerConstantsBase::calcMinCountPoT(sizeof(T));
return ret;
}
//! \~english Returns the maximum capacity that still grows by powers of two for type `T`.
//! \~russian Возвращает максимальную ёмкость со степенным ростом для типа `T`.
static size_t maxCountForPoT() {
static const size_t ret = _PIContainerConstantsBase::calcMaxCountForPoT(sizeof(T));
return ret;
}
//! \~english Returns the linear growth step used after power-of-two expansion for type `T`.
//! \~russian Возвращает линейный шаг роста после степенного расширения для типа `T`.
static size_t stepAfterPoT() {
static const size_t ret = _PIContainerConstantsBase::calcStepAfterPoT(sizeof(T));
return ret;
}
//! \~english Calculates capacity needed to fit `new_size` elements.
//! \~russian Вычисляет ёмкость, достаточную для размещения `new_size` элементов.
static size_t calcNewSize(size_t old_size, size_t new_size) {
if (new_size == 0) return 0;
if (new_size < maxCountForPoT()) {
if (old_size * 2 >= new_size && old_size < new_size) {
return old_size * 2;
}
ssize_t t = minCountPoT();
new_size -= 1;
while (new_size >> t)
++t;
return (1 << t);
} else {
size_t ret = old_size;
while (ret < new_size)
ret += stepAfterPoT();
return ret;
}
return 0;
}
};
//! \~\brief
//! \~english Template reverse wrapper over any container
//! \~russian Шаблонная функция обертки любого контейнера для обратного доступа через итераторы
template<typename C>
_PIReverseWrapper<C> PIReverseWrap(C & c) {
return _PIReverseWrapper<C>(c);
}
//! \~english Template reverse wrapper over constant container.
//! \~russian Шаблонная функция-обёртка константного контейнера для обратного доступа через итераторы.
template<typename C>
_PIReverseWrapper<C> PIReverseWrap(const C & c) {
return _PIReverseWrapper<C>(c);
}
//! \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<int> 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
#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
#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
#define piForeachRC(i, c) for (const i: PIReverseWrap(c))
#define piForeachCR piForeachRC
//! \~\brief
//! \~english Reshape order enum for reshape() function.
//! \~russian Порядок обхода для функции изменения размерности reshape().
//! \~ \sa \a PIVector::reshape(), \a PIDeque::reshape()
enum ReshapeOrder {
ReshapeByRow /*! \~english Traversing elements by line, just as they stay in memory \~russian Обход элементов построчно, так же как они
находятся в памяти */
,
ReshapeByColumn /*! \~english Traversing elements by column \~russian Обход элементов по столбцам */,
};
#endif // PICONTAINERS_H