diff --git a/doc/images/pivector_begin.png b/doc/images/pivector_begin.png new file mode 100644 index 00000000..159ba1b1 Binary files /dev/null and b/doc/images/pivector_begin.png differ diff --git a/doc/images/pivector_rbegin.png b/doc/images/pivector_rbegin.png new file mode 100644 index 00000000..8e6be62d Binary files /dev/null and b/doc/images/pivector_rbegin.png differ diff --git a/libs/main/containers/pivector.h b/libs/main/containers/pivector.h index 383158fa..440f5504 100644 --- a/libs/main/containers/pivector.h +++ b/libs/main/containers/pivector.h @@ -1,17 +1,17 @@ -/*! \addtogroup Containers - * \{ - * \file pivector.h - * \brief - * \~english Declares \a PIVector - * \~russian Объявление \a PIVector - * \~\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 pivector.h +//! \brief +//! \~english Declares \a PIVector +//! \~russian Объявление \a PIVector +//! \~\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 Sequence linear container aka dynamic size array of any type @@ -36,69 +36,68 @@ #include "picontainers.h" -/*! \addtogroup Containers - * \{ - * \class PIVector pivector.h - * \brief - * \~english Sequence linear container - dynamic size array of any type - * \~russian Последовательный контейнер с линейной памятью - динамический массив любого типа - * \~\} - * \details - * \~english - * The elements are stored contiguously, - * which means that elements can be accessed not only through iterators, - * but also using offsets to regular pointers to elements. - * This means that a pointer to an element of a vector may be passed to any function - * that expects a pointer to an element of an array. - * - * The storage of the vector is handled automatically, - * being expanded and contracted as needed. - * Vectors usually occupy more space than static arrays, - * because more memory is allocated to handle future growth. - * This way a vector does not need to reallocate each time an element is inserted, - * but only when the additional memory is exhausted. - * The total amount of allocated memory can be queried using \a capacity() function. - * Reallocations are usually costly operations in terms of performance. - * The \a reserve() function can be used to eliminate reallocations - * if the number of elements is known beforehand. - * - * The complexity (efficiency) of common operations on vectors is as follows: - * - Random access - constant 𝓞(1) - * - Insertion or removal of elements at the end - amortized constant 𝓞(1) - * - Insertion or removal of elements - linear in the distance to the end of the vector 𝓞(n) - * - * \~russian - * Элементы хранятся непрерывно, а значит доступны не только через итераторы, - * но и с помощью смещений для обычных указателей на элементы. - * Это означает, что указатель на элемент вектора может передаваться в любую функцию, - * ожидающую указатель на элемент массива. - * - * Память вектора обрабатывается автоматически, - * расширяясь и сжимаясь по мере необходимости. - * Векторы обычно занимают больше места, чем статические массивы, - * поскольку больше памяти выделяется для обработки будущего роста. - * Таким образом, память для вектора требуется выделять - * не при каждой вставке элемента, - * а только после исчерпания дополнительной памяти. - * Общий объём выделенной памяти можно получить с помощью функции \a capacity(). - * - * Выделение памяти обычно является дорогостоящей операцией - * с точки зрения производительности. - * Функцию \a reserve() можно использовать для исключения выделения памяти, - * если количество элементов известно заранее. - * - * Сложность (эффективность) обычных операций над векторами следующая: - * - Произвольный доступ — постоянная 𝓞(1) - * - Вставка и удаление элементов в конце — амортизированная постоянная 𝓞(1) - * - Вставка и удаление элементов — линейная по расстоянию до конца вектора 𝓞(n) - */ +//! \addtogroup Containers +//! \{ +//! \class PIVector pivector.h +//! \brief +//! \~english Sequence linear container - dynamic size array of any type. +//! \~russian Последовательный контейнер с линейной памятью - динамический массив любого типа. +//! \~\} +//! \details +//! \~english +//! The elements are stored contiguously, +//! which means that elements can be accessed not only through iterators, +//! but also using offsets to regular pointers to elements. +//! This means that a pointer to an element of a vector may be passed to any function +//! that expects a pointer to an element of an array. +//! +//! The storage of the vector is handled automatically, +//! being expanded and contracted as needed. +//! Vectors usually occupy more space than static arrays, +//! because more memory is allocated to handle future growth. +//! This way a vector does not need to reallocate each time an element is inserted, +//! but only when the additional memory is exhausted. +//! The total amount of allocated memory can be queried using \a capacity() function. +//! Reallocations are usually costly operations in terms of performance. +//! The \a reserve() function can be used to eliminate reallocations +//! if the number of elements is known beforehand. +//! +//! The complexity (efficiency) of common operations on vectors is as follows: +//! - Random access - constant 𝓞(1) +//! - Insertion or removal of elements at the end - amortized constant 𝓞(1) +//! - Insertion or removal of elements - linear in the distance to the end of the vector 𝓞(n) +//! +//! \~russian +//! Элементы хранятся непрерывно, а значит доступны не только через итераторы, +//! но и с помощью смещений для обычных указателей на элементы. +//! Это означает, что указатель на элемент вектора может передаваться в любую функцию, +//! ожидающую указатель на элемент массива. +//! +//! Память вектора обрабатывается автоматически, +//! расширяясь и сжимаясь по мере необходимости. +//! Векторы обычно занимают больше места, чем статические массивы, +//! поскольку больше памяти выделяется для обработки будущего роста. +//! Таким образом, память для вектора требуется выделять +//! не при каждой вставке элемента, +//! а только после исчерпания дополнительной памяти. +//! Общий объём выделенной памяти можно получить с помощью функции \a capacity(). +//! +//! Выделение памяти обычно является дорогостоящей операцией +//! с точки зрения производительности. +//! Функцию \a reserve() можно использовать для исключения выделения памяти, +//! если количество элементов известно заранее. +//! +//! Сложность (эффективность) обычных операций над векторами следующая: +//! - Произвольный доступ — постоянная 𝓞(1) +//! - Вставка и удаление элементов в конце — амортизированная постоянная 𝓞(1) +//! - Вставка и удаление элементов — линейная по расстоянию до конца вектора 𝓞(n) template class PIVector { public: //! \~\brief - //! \~english Constructs an empty vector - //! \~russian Создает пустой массив + //! \~english Constructs an empty vector. + //! \~russian Создает пустой массив. inline PIVector(): piv_data(0), piv_size(0), piv_rsize(0) { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) } @@ -115,8 +114,8 @@ public: } //! \~\brief - //! \~english Copy constructor - //! \~russian Копирующий конструктор + //! \~english Copy constructor. + //! \~russian Копирующий конструктор. inline PIVector(const PIVector & v): piv_data(0), piv_size(0), piv_rsize(0) { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) alloc(v.piv_size); @@ -124,15 +123,11 @@ public: } //! \~\brief - //! \~english Contructs vector from C++11 initializer list. - //! \~russian Создает массив из списка инициализации C++11. + //! \~english Contructs vector from [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list). + //! \~russian Создает массив из [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list). //! \~\details - //! \~english - //! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list). - //! \~russian - //! [Список инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list). //! \~\code - //! PIVector v{1,2,3}; + //! PIVector v{1,2,3}; //! piCout << v; //! // {1, 2, 3} //! \endcode @@ -157,7 +152,7 @@ public: //! \~english Can use [Lambda expressions](https://en.cppreference.com/w/cpp/language/lambda) as constructor argument. //! \~russian Позволяет передавать [Лямбда-выражения](https://ru.cppreference.com/w/cpp/language/lambda) для создания элементов в конструкторе. //! \~\code - //! PIVector v(5, [](size_t i){return i*2;}); + //! PIVector v(5, [](size_t i){return i*2;}); //! piCout << v; //! // {0, 2, 4, 6, 8} //! \endcode @@ -167,16 +162,13 @@ public: } //! \~\brief - //! \~english Move constructor - //! \~russian Перемещающий конструктор + //! \~english Move constructor. + //! \~russian Перемещающий конструктор. inline PIVector(PIVector && v): piv_data(v.piv_data), piv_size(v.piv_size), piv_rsize(v.piv_rsize) { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) v._reset(); } - //! \~\brief - //! \~english Destructor - //! \~russian Деструктор inline virtual ~PIVector() { PIINTROSPECTION_CONTAINER_DELETE(T) PIINTROSPECTION_CONTAINER_FREE(T, (piv_rsize)) @@ -186,8 +178,8 @@ public: } //! \~\brief - //! \~english Assign operator - //! \~russian Оператор присваивания + //! \~english Assign operator. + //! \~russian Оператор присваивания. inline PIVector & operator =(const PIVector & v) { if (this == &v) return *this; clear(); @@ -198,8 +190,8 @@ public: } //! \~\brief - //! \~english Assign move operator - //! \~russian Оператор перемещающего присваивания + //! \~english Assign move operator. + //! \~russian Оператор перемещающего присваивания. inline PIVector & operator =(PIVector && v) { swap(v); return *this; @@ -283,21 +275,102 @@ public: inline bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);} }; + //! \~\brief + //! \~english Iterator to the first element. + //! \~russian Итератор на первый элемент. + //! \~\details ![begin, end](doc/images/pivector_begin.png) + //! + //! \~english If the vector is empty, the returned iterator is equal to \a end. + //! \~russian Если массив - пуст, возвращаемый итератор будет равен \a end. + //! \~\sa \a end, \a rbegin, \a rend inline iterator begin() {return iterator(this, 0);} + + //! \~\brief + //! \~english Iterator to the element following the last element. + //! \~russian Итератор на элемент, следующий за последним элементом. + //! \~\details ![begin, end](doc/images/pivector_begin.png) + //! + //! \~english This element acts as a placeholder; attempting to access it results in undefined behavior. + //! \~russian Этот элемент существует лишь условно, + //! попытка доступа к нему приведёт к выходу за разрешенную память. + //! \~\sa \a begin, \a rbegin, \a rend inline iterator end() {return iterator(this, piv_size);} + inline const_iterator begin() const {return const_iterator(this, 0);} inline const_iterator end() const {return const_iterator(this, piv_size);} + + //! \~\brief + //! \~english Returns a reverse iterator to the first element of the reversed vector. + //! \~russian Обратный итератор на первый элемент. + //! \~\details ![rbegin, rend](doc/images/pivector_rbegin.png) + //! + //! \~english It corresponds to the last element of the non-reversed vector. + //! If the vector is empty, the returned iterator is equal to \a rend. + //! \~russian Итератор для прохода массива в обратном порядке. + //! Указывает на последний элемент. + //! Если массив пустой, то совпадает с итератором \a rend. + //! \~\sa \a rend, \a begin, \a end inline reverse_iterator rbegin() {return reverse_iterator(this, piv_size - 1);} + + //! \~\brief + //! \~english Returns a reverse iterator to the element following the last element of the reversed vector. + //! \~russian Обратный итератор на элемент, следующий за последним элементом. + //! \~\details ![rbegin, rend](doc/images/pivector_rbegin.png) + //! + //! \~english It corresponds to the element preceding the first element of the non-reversed vector. + //! This element acts as a placeholder, attempting to access it results in undefined behavior. + //! \~russian Итератор для прохода массива в обратном порядке. + //! Указывает на элемент, предшествующий первому элементу. + //! Этот элемент существует лишь условно, + //! попытка доступа к нему приведёт к выходу за разрешенную память. + //! \~\sa \a rbegin, \a begin, \a end inline reverse_iterator rend() {return reverse_iterator(this, -1);} + inline const_reverse_iterator rbegin() const {return const_reverse_iterator(this, piv_size - 1);} inline const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);} + //! \~\brief + //! \~english Number of elements in the container. + //! \~russian Количество элементов массива. + //! \~\sa \a size_s, \a capacity, \a isEmpty, \a isNotEmpty, \a resize, \a reserve inline size_t size() const {return piv_size;} + + //! \~\brief + //! \~english Number of elements in the container as signed value. + //! \~russian Количество элементов массива в виде знакового числа. + //! \~\sa \a size, \a capacity, \a isEmpty, \a isNotEmpty, \a resize, \a reserve inline ssize_t size_s() const {return piv_size;} + + //! \~\brief + //! \~english Same as \a size. + //! \~russian Синоним \a size. + //! \~\sa \a size \a size_s, \a capacity, \a isEmpty, \a isNotEmpty, \a resize, \a reserve inline size_t length() const {return piv_size;} + + //! \~\brief + //! \~english Number of elements that the container has currently allocated space for. + //! \~russian Количество элементов, для которого сейчас выделена память контейнером. + //! \~\sa \a size \a size_s, \a isEmpty, \a isNotEmpty, \a resize, \a reserve inline size_t capacity() const {return piv_rsize;} + + //! \~\brief + //! \~english Checks if the container has no elements. + //! \~russian Проверяет пуст ли контейнер. + //! \~\return + //! \~english **true** if the container is empty, **false** otherwise + //! \~russian **true** если контейнер пуст, **false** иначе. + //! \~\sa \a size \a size_s, \a isEmpty, \a isNotEmpty, \a resize, \a reserve inline bool isEmpty() const {return (piv_size == 0);} + + //! \~\brief + //! \~english Checks if the container has elements. + //! \~russian Проверяет пуст ли контейнер. + //! \~\return + //! \~english **true** if the container is empty, **false** otherwise + //! \~russian **true** если контейнер пуст, **false** иначе. + //! \~\sa \a size \a size_s, \a isEmpty, \a isNotEmpty, \a resize, \a reserve inline bool isNotEmpty() const {return (piv_size > 0);} + inline bool any(std::function test) const { for (size_t i = 0; i < piv_size; ++i) { if (test(piv_data[i])) return true; diff --git a/main.cpp b/main.cpp index a94d025f..7525baea 100644 --- a/main.cpp +++ b/main.cpp @@ -2,30 +2,12 @@ int main(int argc, char * argv[]) { - PIThreadNotifier n; - int cnt1 = 0; - int cnt2 = 0; - int cnt3 = 0; - PIThread t1([&n, &cnt1](){n.wait(); cnt1++; piMSleep(1);}, true); - PIThread t2([&n, &cnt2](){n.wait(); cnt2++; piMSleep(2);}, true); - piCout << "created"; - piMSleep(10); - piCout << "unlock" << cnt1 << cnt2 << cnt3; - n.notifyOnce(); cnt3++; - piMSleep(10); - piCout << "unlock" << cnt1 << cnt2 << cnt3; - n.notifyOnce(); cnt3++; - piMSleep(10); - piCout << "run" << cnt1 << cnt2 << cnt3; - PIThread t3([&n, &cnt3](){n.notifyOnce(); cnt3++; piMSleep(1);}, true); - piMSleep(20); - t3.stop(); - piMSleep(100); - piCout << "exit" << cnt1 << cnt2 << cnt3; - PIByteArray ba = PIByteArray::fromHex("00aabbcc"); - PIByteArray ba2 = ba.getRange(1, 2); - piCout << ba2.toHex(); -// m.unlock(); -// piMSleep(10); + PIVector v(5, [](size_t i){return i*2;}); + v.prepend({1, 2, 3}); + piCout << v; + piCout << v.reduce([](int v, int s){return v+s;}); + piCout << v.reduce([](int v, PIString s){return s+PIString::fromNumber(v);}); + PIStringList sl = v.map([](int v){return PIString::fromNumber(v);}); + piCout << sl; return 0; }