Files
pip/libs/main/core/pibytearray.h
peri4 242abaaf59 version 2.95.0
get rid of PIByteArray subclassing from PIDeque<uchar>
2022-07-22 16:40:09 +03:00

912 lines
46 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.
/*! \file pibytearray.h
* \ingroup Core
* \~\brief
* \~english Byte array
* \~russian Байтовый массив
*/
/*
PIP - Platform Independent Primitives
Byte array
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@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 PIBYTEARRAY_H
#define PIBYTEARRAY_H
#include "pichar.h"
#include "pibinarystream.h"
#include <stdio.h>
class PIString;
class PIByteArray;
//! \ingroup Core
//! \~\brief
//! \~english The %PIByteArray class provides an array of bytes.
//! \~russian Класс %PIByteArray представляет собой массив байтов.
class PIP_EXPORT PIByteArray: public PIBinaryStream<PIByteArray>
{
public:
typedef ::PIMemoryBlock RawData DEPRECATEDM("use PIMemoryBlock instead");
//! \~english Constructs an empty byte array
//! \~russian Создает пустой байтовый массив
PIByteArray() {}
//! \~english Constructs copy of byte array "o"
//! \~russian Создает копию байтового массива "o"
PIByteArray(const PIByteArray & o): d(o.d) {}
//! \~english Constructs copy of byte array "o"
//! \~russian Создает копию байтового массива "o"
PIByteArray(const PIDeque<uchar> & o): d(o) {}
PIByteArray(PIByteArray && o): d(std::move(o.d)) {}
//! \~english Constructs 0-filled byte array with size "size"
//! \~russian Создает заполненный "0" байтовый массив размером "size"
PIByteArray(const uint size) {resize(size);}
//! \~english Constructs byte array from data "data" and size "size"
//! \~russian Создает байтовый массив из данных по указателю "data" размером "size"
PIByteArray(const void * data, const uint size): d((const uchar*)data, size_t(size)) {}
//! \~english Constructs byte array with size "size" filled by "t"
//! \~russian Создает заполненный "t" байтовый массив размером "size"
PIByteArray(const uint size, uchar t): d(size, t) {}
//! \~english Swaps array `v` other with this array.
//! \~russian Меняет местами массив `v` с этим массивом.
//! \~\details
//! \~english This operation is very fast and never fails.
//! \~russian Эта операция выполняется мгновенно без копирования памяти и никогда не дает сбоев.
inline void swap(PIByteArray & other) {
d.swap(other.d);
}
//! \~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 d.size();}
//! \~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 d.size_s();}
//! \~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 d.length();}
//! \~english Number of elements that the container has currently allocated space for.
//! \~russian Количество элементов, для которого сейчас выделена память контейнером.
//! \~\details
//! \~english To find out the actual number of items, use the function \a size().
//! \~russian Чтобы узнать фактическое количество элементов используйте функцию \a size().
//! \~\sa \a reserve(), \a size(), \a size_s()
inline size_t capacity() const {return d.capacity();}
//! \~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 d.isEmpty();}
//! \~english Checks if the container has elements.
//! \~russian Проверяет не пуст ли контейнер.
//! \~\return
//! \~english **true** if the container is not 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 d.isNotEmpty();}
//! \~english Tests whether at least one element in the array
//! passes the test implemented by the provided function `test`.
//! \~russian Проверяет, удовлетворяет ли какой-либо элемент массива условию,
//! заданному в передаваемой функции `test`.
//! \~\return
//! \~english **true** if, in the array,
//! it finds an element for which the provided function returns **true**;
//! otherwise it returns **false**. Always returns **false** if is empty.
//! \~russian **true** если хотя бы для одного элемента
//! передаваемая функция возвращает **true**, в остальных случаях **false**.
//! Метод возвращает **false** при любом условии для пустого массива.
//! \~\details
//! \~\sa \a every(), \a contains(), \a entries(), \a forEach()
inline bool any(std::function<bool(uchar e)> test) const {
return d.any(test);
}
//! \~english Tests whether all elements in the array passes the test
//! implemented by the provided function `test`.
//! \~russian Проверяет, удовлетворяют ли все элементы массива условию,
//! заданному в передаваемой функции `test`.
//! \~\return
//! \~english **true** if, in the array,
//! it finds an element for which the provided function returns **true**;
//! otherwise it returns **false**. Always returns **true** if is empty.
//! \~russian **true** если для всех элементов передаваемая функция возвращает **true**,
//! в остальных случаях **false**.
//! Метод возвращает **true** при любом условии для пустого массива.
//! \~\details
//! \~\sa \a any(), \a contains(), \a entries(), \a forEach()
inline bool every(std::function<bool(uchar e)> test) const {
return d.every(test);
}
//! \~english Full access to element by `index`.
//! \~russian Полный доступ к элементу по индексу `index`.
//! \~\details
//! \~english Element index starts from `0`.
//! Element index must be in range from `0` to `size()-1`.
//! Otherwise will be undefined behavior.
//! \~russian Индекс элемента считается от `0`.
//! Индекс элемента должен лежать в пределах от `0` до `size()-1`.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
//! \~\sa \a at()
inline uchar & operator [](size_t index) {return d[index];}
inline uchar operator [](size_t index) const {return d[index];}
//! \~english Read only access to element by `index`.
//! \~russian Доступ исключительно на чтение к элементу по индексу `index`.
//! \~\details
//! \~english Element index starts from `0`.
//! Element index must be in range from `0` to `size()-1`.
//! Otherwise will be undefined behavior.
//! \~russian Индекс элемента считается от `0`.
//! Индекс элемента должен лежать в пределах от `0` до `size()-1`.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline uchar at(size_t index) const {return d.at(index);}
//! \~english Last element.
//! \~russian Последний элемент массива.
//! \~\details
//! \~english Returns a reference to the last item in the array.
//! This function assumes that the array isn't empty.
//! Otherwise will be undefined behavior.
//! \~russian Возвращает ссылку на последний элемент в массиве.
//! Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline uchar & back() {return d.back();}
inline uchar back() const {return d.back();}
//! \~english Last element.
//! \~russian Первый элемент массива.
//! \~\details
//! \~english Returns a reference to the last item in the array.
//! This function assumes that the array isn't empty.
//! Otherwise will be undefined behavior.
//! \~russian Возвращает ссылку на пенрвый элемент в массиве.
//! Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline uchar & front() {return d.front();}
inline uchar front() const {return d.front();}
//! \~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
//! PIDeque<int> 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**.
//! \~\sa \a every(), \a any(), \a entries()
inline bool contains(uchar e, ssize_t start = 0) const {
return d.contains(e, start);
}
//! \~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, что означает, что просматривается весь массив.
//! \~\sa \a every(), \a any(), \a contains()
inline int entries(uchar e, ssize_t start = 0) const {
return d.entries(e, start);
}
//! \~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()
inline int entries(std::function<bool(uchar e)> test, ssize_t start = 0) const {
return d.entries(test, start);
}
//! \~english Pointer to array
//! \~russian Указатель на память массива
//! \~\details
//! \~english Optional argument `index` the position in this array,
//! where is pointer. Default: start of array.
//! \~russian Опциональный аргумент `index` указывает на индекс c которого брать указатель.
//! По умолчанию указывает на начало массива.
inline uchar * data(size_t index = 0) {return d.data(index);}
//! \~english Read only pointer to array
//! \~russian Указатель на память массива только для чтения.
//! \~\details
//! \~english The pointer can be used to access and modify the items in the array.
//! The pointer remains valid as long as the array isn't reallocated.
//! Optional argument `index` the position in this array,
//! where is pointer. Default: start of array.
//! \~russian Указатель можно использовать для доступа и изменения элементов в массиве.
//! Указатель остается действительным только до тех пор, пока массив не будет перераспределен.
//! Опциональный аргумент `index` указывает на индекс c которого брать указатель.
//! По умолчанию указывает на начало массива.
inline const uchar * data(size_t index = 0) const {return d.data(index);}
//! \~english Clear array, remove all elements.
//! \~russian Очищает массив, удаляет все элементы.
//! \~\details
//! \~\note
//! \~english Reserved memory will not be released.
//! \~russian Зарезервированная память не освободится.
//! \~\sa \a resize()
inline PIByteArray & clear() {
resize(0);
return *this;
}
//! \~english Assigns element 'e' to all items in the array.
//! \~russian Заполняет весь массив копиями элемента 'e'.
//! \~\details
//! \~\sa \a resize()
inline PIByteArray & fill(uchar e = 0) {
d.fill(e);
return *this;
}
//! \~english Assigns result of function 'f(size_t i)' to all items in the array.
//! \~russian Заполняет весь массив результатом вызова функции 'f(size_t i)'.
//! \~\details
//! \~\sa \a resize()
inline PIByteArray & fill(std::function<uchar(size_t i)> f) {
d.fill(f);
return *this;
}
//! \~english Same as \a fill().
//! \~russian Тоже самое что и \a fill().
//! \~\sa \a fill(), \a resize()
inline PIByteArray & assign(uchar e = 0) {return fill(e);}
//! \~english First does `resize(new_size)` then `fill(e)`.
//! \~russian Сначала делает `resize(new_size)`, затем `fill(e)`.
//! \~\sa \a fill(), \a resize()
inline PIByteArray & assign(size_t new_size, uchar e) {
resize(new_size);
return fill(e);
}
//! \~english Sets size of the array, new elements are copied from `e`.
//! \~russian Устанавливает размер массива, новые элементы копируются из `e`.
//! \~\details
//! \~english If `new_size` is greater than the current \a size(),
//! elements are added to the end; the new elements are initialized from `e`.
//! If `new_size` is less than the current \a size(), elements are removed from the end.
//! \~russian Если `new_size` больше чем текущий размер массива \a size(),
//! новые элементы добавляются в конец массива и создаются из `e`.
//! Если `new_size` меньше чем текущий размер массива \a size(),
//! лишние элементы удаляются с конца массива.
//! \~\sa \a size(), \a clear()
inline PIByteArray & resize(size_t new_size, uchar e = 0) {
d.resize(new_size, e);
return *this;
}
//! \~english Sets size of the array, new elements created by function `f(size_t i)`.
//! \~russian Устанавливает размер массива, новые элементы создаются функцией `f(size_t i)`.
//! \~\details
//! \~english If `new_size` is greater than the current \a size(),
//! elements are added to the end; the new elements created by function `f(size_t i)`.
//! If `new_size` is less than the current \a size(), elements are removed from the end.
//! \~russian Если `new_size` больше чем текущий размер массива \a size(),
//! новые элементы добавляются в конец массива и функцией `f(size_t i)`.
//! Если `new_size` меньше чем текущий размер массива \a size(),
//! лишние элементы удаляются с конца массива.
//! \~\sa \a size(), \a clear()
inline PIByteArray & resize(size_t new_size, std::function<uchar(size_t i)> f) {
d.resize(new_size, f);
return *this;
}
//! \~english Return resized byte array
//! \~russian Возвращает копию байтового массива с измененным размером
PIByteArray resized(uint new_size) const {PIByteArray ret(new_size); memcpy(ret.data(), data(), new_size); return ret;}
//! \~english Attempts to allocate memory for at least `new_size` elements.
//! \~russian Резервируется память под как минимум `new_size` элементов.
//! \~\details
//! \~english If you know in advance how large the array will be,
//! you should call this function to prevent reallocations and memory fragmentation.
//! If `new_size` is greater than the current \a capacity(),
//! new storage is allocated, otherwise the function does nothing.
//! This function does not change the \a size() of the array.
//! \~russian Если вы заранее знаете, насколько велик будет массив,
//! вы можете вызвать эту функцию, чтобы предотвратить перераспределение и фрагментацию памяти.
//! Если размер `new_size` больше чем выделенная память \a capacity(),
//! то произойдёт выделение новой памяти и перераспределение массива.
//! Эта функция не изменяет количество элементов в массиве \a size().
//! \~\sa \a size(), \a capacity(), \a resize()
inline PIByteArray & reserve(size_t new_size) {
d.reserve(new_size);
return *this;
}
//! \~english Inserts value `e` at `index` position in the array.
//! \~russian Вставляет значение `e` в позицию `index` в массиве.
//! \~\details
//! \~english The index must be greater than 0 and less than or equal to \a size().
//! \~russian Индекс должен быть больше 0 и меньше или равен \a size().
//! \~\sa \a append(), \a prepend(), \a remove()
inline PIByteArray & insert(size_t index, uchar e = 0) {
d.insert(index, e);
return *this;
}
//! \~english Inserts array `v` at `index` position in the array.
//! \~russian Вставляет массив `v` в позицию `index` в массиве.
//! \~\details
//! \~english The index must be greater than or equal to 0 and less than or equal to \a size().
//! \~russian Индекс должен быть больше или равен 0 и меньше или равен \a size().
//! \~\sa \a append(), \a prepend(), \a remove()
inline PIByteArray & insert(size_t index, const PIByteArray & v) {
d.insert(index, v.d);
return *this;
}
//! \~english Inserts the given elements at `index` position in the array.
//! \~russian Вставляет элементы в позицию `index` в массиве.
//! \~\details
//! \~english The index must be greater than or equal to 0 and less than or equal to \a size().
//! Inserts the given elements from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian Индекс должен быть больше или равен 0 и меньше или равен \a size().
//! Вставляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a append(), \a prepend(), \a remove()
inline PIByteArray & insert(size_t index, std::initializer_list<uchar> init_list) {
d.insert(index, init_list);
return *this;
}
//! \~english Removes `count` elements from the middle of the array, starting at `index` position.
//! \~russian Удаляет элементы из массива, начиная с позиции `index` в количестве `count`.
//! \~\details
//! \~\sa \a resize(), \a insert(), \a removeOne(), \a removeAll(), \a removeWhere()
inline PIByteArray & remove(size_t index, size_t count = 1) {
d.remove(index, count);
return *this;
}
//! \~english Return sub-array starts from "index" and has "count" or less bytes
//! \~russian Возвращает подмассив с данными от индекса "index" и размером не более "count"
PIByteArray getRange(size_t index, size_t count) const {
return d.getRange(index, count);
}
//! \~english Reverses this array.
//! \~russian Обращает порядок следования элементов этого массива.
//! \~\details
//! \~english This method reverses an array [in place](https://en.wikipedia.org/wiki/In-place_algorithm).
//! The first array element becomes the last, and the last array element becomes the first.
//! The reverse method transposes the elements of the calling array object in place,
//! mutating the array, and returning a reference to the array.
//! \~russian Метод reverse() на месте переставляет элементы массива,
//! на котором он был вызван, изменяет массив и возвращает ссылку на него.
//! Первый элемент массива становится последним, а последний — первым.
//! \~\sa \a reversed()
inline PIByteArray & reverse() {
d.reverse();
return *this;
}
//! \~english Returns reversed array.
//! \~russian Возвращает перевернутый массив.
//! \~\details
//! \~english Returns a copy of the array with elements in reverse order.
//! The first array element becomes the last, and the last array element becomes the first.
//! \~russian Возвращает копию массива с элементами в обратном порядке.
//! Первый элемент массива становится последним, а последний — первым.
//! \~\sa \a reverse()
inline PIByteArray reversed() const {
PIByteArray ret(*this);
return ret.reverse();
}
//! \~english Increases or decreases the size of the array by `add_size` elements.
//! \~russian Увеличивает или уменьшает размер массива на `add_size` элементов.
//! \~\details
//! \~english If `add_size > 0` then elements are added to the end of the array.
//! If `add_size < 0` then elements are removed from the end of the array.
//! If `add_size < 0` and there are fewer elements in the array than specified, then the array becomes empty.
//! \~russian Если `add_size > 0`, то в конец массива добавляются элементы.
//! Если `add_size < 0`, то с конца массива удаляются элементы.
//! Если `add_size < 0` и в массиве меньше элементов чем указано, то массив становится пустым.
//! \~\sa \a resize()
inline PIByteArray & enlarge(llong add_size) {
d.enlarge(add_size);
return *this;
}
//! \~english Remove no more than one element equal `e`.
//! \~russian Удаляет первый элемент, который равен элементу `e`.
//! \~\details
//! \~\sa \a remove(), \a removeAll(), \a removeWhere()
inline PIByteArray & removeOne(uchar e) {
d.removeOne(e);
return *this;
}
//! \~english Remove all elements equal `e`.
//! \~russian Удаляет все элементы, равные элементу `e`.
//! \~\details
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
inline PIByteArray & removeAll(uchar e) {
d.removeAll(e);
return *this;
}
//! \~english Remove all elements in the array
//! passes the test implemented by the provided function `test`.
//! \~russian Удаляет все элементы, удовлетворяющие условию,
//! заданному в передаваемой функции `test`.
//! \~\details
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
inline PIByteArray & removeWhere(std::function<bool(uchar e)> test) {
d.removeWhere(test);
return *this;
}
//! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива.
//! \~\details
//! \~english If size() is less than capacity(), which is most often
//! then the addition will be very fast.
//! In any case, the addition is fast and does not depend on the size of the array.
//! If the new size() is greater than capacity()
//! then all iterators and references
//! (including the past-the-end iterator) are invalidated.
//! Otherwise only the past-the-end iterator is invalidated.
//! \~russian Если size() меньше capacity(), что часто бывает,
//! то добавление будет очень быстрым.
//! В любом случае добавление быстрое и не зависит от размера массива.
//! Если новый size() больше, чем capacity(),
//! то все итераторы и указатели становятся нерабочими.
//! В противном случае все, кроме итераторов, указывающих на конец массива,
//! остаются в рабочем состоянии.
//! \~\sa \a push_front(), \a append(), \a prepend(), \a insert()
inline PIByteArray & push_back(uchar e) {
d.push_back(e);
return *this;
}
//! \~english Appends the given elements to the end of the array.
//! \~russian Добавляет элементы в конец массива.
//! \~\details
//! \~english Overloaded function.
//! Appends the given elements 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).
//! \~\sa \a push_back()
inline PIByteArray & push_back(std::initializer_list<uchar> init_list) {
d.push_back(init_list);
return *this;
}
//! \~english Appends the given array `v` to the end of the array.
//! \~russian Добавляет массив `v` в конец массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a push_back()
inline PIByteArray & push_back(const PIByteArray & v) {
d.push_back(v.d);
return *this;
}
//! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива.
//! \~\details
//! \~english If there is free space at the beginning of the array,
//! which is most often, then the addition will be very fast.
//! In any case, the addition is fast and does not depend on the size of the array.
//! If there is no free space at the beginning of the array
//! then all iterators and references
//! (including the past-the-begin iterator) are invalidated.
//! Otherwise only the past-the-begin iterator is invalidated.
//! \~russian Если в начале массива имеется свободное место,
//! что часто бывает, то добавление будет очень быстрым.
//! В любом случае добавление быстрое и не зависит от размера массива.
//! Если в начале массива нет свободного места,
//! то все итераторы и указатели становятся нерабочими.
//! В противном случае все, кроме итераторов указывающих, на начало массива,
//! остаются в рабочем состоянии.
//! \~\sa \a push_back(), \a append(), \a prepend(), \a insert()
inline PIByteArray & push_front(uchar e) {
d.push_front(e);
return *this;
}
//! \~english Appends the given array `v` to the begin of the array.
//! \~russian Добавляет массив `v` в начало массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a push_front()
inline PIByteArray & push_front(const PIByteArray & v) {
d.push_front(v.d);
return *this;
}
//! \~english Appends the given elements to the begin of the array.
//! \~russian Добавляет элементы в начало массива.
//! \~\details
//! \~english Overloaded function.
//! Appends the given elements 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).
//! \~\sa \a append()
inline PIByteArray & push_front(std::initializer_list<uchar> init_list) {
d.push_front(init_list);
return *this;
}
//! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива.
//! \~\details
//! \~english If there is free space at the beginning of the array,
//! which is most often, then the addition will be very fast.
//! In any case, the addition is fast and does not depend on the size of the array.
//! If there is no free space at the beginning of the array
//! then all iterators and references
//! (including the past-the-begin iterator) are invalidated.
//! Otherwise only the past-the-begin iterator is invalidated.
//! \~russian Если в начале массива имеется свободное место,
//! что часто бывает, то добавление будет очень быстрым.
//! В любом случае добавление быстрое и не зависит от размера массива.
//! Если в начале массива нет свободного места,
//! то все итераторы и указатели становятся нерабочими.
//! В противном случае все, кроме итераторов указывающих, на начало массива,
//! остаются в рабочем состоянии.
//! \~\sa \a push_back(), \a append(), \a prepend(), \a insert()
inline PIByteArray & prepend(uchar e) {
d.prepend(e);
return *this;
}
//! \~english Appends the given array `v` to the begin of the array.
//! \~russian Добавляет массив `v` в начало массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a prepend()
inline PIByteArray & prepend(const PIByteArray & v) {
d.prepend(v.d);
return *this;
}
//! \~english Appends the given elements to the begin of the array.
//! \~russian Добавляет элементы в начало массива.
//! \~\details
//! \~english Overloaded function.
//! Appends the given elements 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).
//! \~\sa \a append()
inline PIByteArray & prepend(std::initializer_list<uchar> init_list) {
d.prepend(init_list);
return *this;
}
//! \~english Remove one element from the end of the array.
//! \~russian Удаляет один элемент с конца массива.
//! \~\details
//! \~english Deleting an element from the end is very fast
//! and does not depend on the size of the array.
//! \~russian Удаление элемента с конца выполняется очень быстро
//! и не зависит от размера массива.
//! \~\sa \a pop_front(), \a take_back(), \a take_front()
inline PIByteArray & pop_back() {
d.pop_back();
return *this;
}
//! \~english Remove one element from the begining of the array.
//! \~russian Удаляет один элемент с начала массива.
//! \~\details
//! \~english Removing an element from the beginning takes longer than from the end.
//! This time is directly proportional to the size of the array.
//! All iterators and references are invalidated.
//! \~russian Удаление элемента с начала выполняется дольше, чем с конца.
//! Это время прямопропорционально размеру массива.
//! При удалении элемента все итераторы и указатели становятся нерабочими.
//! \~\sa \a pop_back(), \a take_back(), \a take_front()
inline PIByteArray & pop_front() {
d.pop_front();
return *this;
}
//! \~english Remove one element from the end of the array and return it.
//! \~russian Удаляет один элемент с начала массива и возвращает его.
//! \~\details
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
inline uchar take_back() {
return d.take_back();
}
//! \~english Remove one element from the begining of the array and return it.
//! \~russian Удаляет один элемент с конца массива и возвращает его.
//! \~\details
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
inline uchar take_front() {
return d.take_front();
}
//! \~english Convert data to Base 64 and return this byte array
//! \~russian Преобразует данные в Base 64 и возвращает текущий массив
PIByteArray & convertToBase64();
//! \~english Convert data from Base 64 and return this byte array
//! \~russian Преобразует данные из Base 64 и возвращает текущий массив
PIByteArray & convertFromBase64();
//! \~english Return converted to Base 64 data
//! \~russian Возвращает копию байтового массива, преобразованного в Base 64
PIByteArray toBase64() const;
PIByteArray & compressRLE(uchar threshold = 192);
PIByteArray & decompressRLE(uchar threshold = 192);
PIByteArray compressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.compressRLE(threshold); return ba;}
PIByteArray decompressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.decompressRLE(threshold); return ba;}
//! \~english Return string representation of data, each byte in "base" base, separated by spaces
//! \~russian Возвращает текстовое представление байтового массива, каждый байт в "base" системе, с пробелами
PIString toString(int base = 16) const;
//! \~english
//! Returns a hex encoded copy of the byte array, without spaces.
//! The hex encoding uses the numbers 0-9 and the letters a-f.
//! \~russian
//! Возвращает шестнадцатеричное представление массива, без пробелов.
//! Оно использует цифры 0-9 и буквы a-f.
PIString toHex() const;
//! \~english Add to the end data "data" with size "size"
//! \~russian Добавляет в конец массива данные по указателю "data" размером "size"
PIByteArray & append(const void * data_, int size_) {uint ps = size(); enlarge(size_); memcpy(data(ps), data_, size_); return *this;}
//! \~english Add to the end byte array "data"
//! \~russian Добавляет в конец массива содержимое массива "data"
PIByteArray & append(const PIByteArray & data_) {uint ps = size(); enlarge(data_.size_s()); memcpy(data(ps), data_.data(), data_.size()); return *this;}
//! \~english Add to the end "t"
//! \~russian Добавляет в конец массива байт "t"
PIByteArray & append(uchar t) {push_back(t); return *this;}
//! \~english Returns 8-bit checksum
//! \~russian Возвращает 8-битную контрольную сумму
uchar checksumPlain8(bool inverse = true) const;
//! \~english Returns 32-bit checksum
//! \~russian Возвращает 32-битную контрольную сумму
uint checksumPlain32(bool inverse = true) const;
//! \~english Returns hash of content
//! \~russian Возвращает хэш содержимого
uint hash() const;
void operator =(const PIDeque<uchar> & o) {resize(o.size()); memcpy(data(), o.data(), o.size());}
PIByteArray & operator =(const PIByteArray & o) {if (this == &o) return *this; clear(); append(o); return *this;}
PIByteArray & operator =(PIByteArray && o) {swap(o); return *this;}
static PIByteArray fromUserInput(PIString str);
static PIByteArray fromHex(PIString str);
//! \~english Return converted from Base 64 data
//! \~russian Возвращает массив из Base 64 представления
static PIByteArray fromBase64(const PIByteArray & base64);
static PIByteArray fromBase64(const PIString & base64);
bool binaryStreamAppendImp(const void * d_, size_t s) {
append(d_, s);
return true;
}
bool binaryStreamTakeImp(void * d_, size_t s) {
if (size() < s)
return false;
memcpy(d_, data(), s);
remove(0, s);
return true;
}
private:
PIDeque<uchar> d;
};
//! \relatesalso PIByteArray
//! \~english Byte arrays compare operator
//! \~russian Оператор сравнения
inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) {
if (v0.size() == v1.size()) {
if (v0.isEmpty()) return false;
return memcmp(v0.data(), v1.data(), v0.size()) < 0;
}
return v0.size() < v1.size();
}
//! \relatesalso PIByteArray
//! \~english Byte arrays compare operator
//! \~russian Оператор сравнения
inline bool operator >(const PIByteArray & v0, const PIByteArray & v1) {
if (v0.size() == v1.size()) {
if (v0.isEmpty()) return false;
return memcmp(v0.data(), v1.data(), v0.size()) > 0;
}
return v0.size() > v1.size();
}
//! \relatesalso PIByteArray
//! \~english Byte arrays compare operator
//! \~russian Оператор сравнения
inline bool operator ==(const PIByteArray & v0, const PIByteArray & v1) {
if (v0.size() == v1.size()) {
if (v0.isEmpty()) return true;
return memcmp(v0.data(), v1.data(), v0.size()) == 0;
}
return false;
}
//! \relatesalso PIByteArray
//! \~english Byte arrays compare operator
//! \~russian Оператор сравнения
inline bool operator !=(const PIByteArray & v0, const PIByteArray & v1) {
if (v0.size() == v1.size()) {
if (v0.isEmpty()) return false;
return memcmp(v0.data(), v1.data(), v0.size()) != 0;
}
return true;
}
#ifdef PIP_STD_IOSTREAM
//! \relatesalso PIByteArray \brief Output to std::ostream operator
inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba);
#endif
//! \relatesalso PIByteArray
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
PIP_EXPORT PICout operator <<(PICout s, const PIByteArray & ba);
BINARY_STREAM_WRITE(PIByteArray) {
s.binaryStreamAppend((int)v.size_s());
s.binaryStreamAppend(v.data(), v.size());
return s;
}
BINARY_STREAM_READ(PIByteArray) {
v.resize(s.binaryStreamTakeInt());
s.binaryStreamTake(v.data(), v.size());
return s;
}
//! \relatesalso PIByteArray
//! \~english Returns PIByteArray::hash() of "ba"
//! \~russian Возвращает PIByteArray::hash() от "ba"
template<> inline uint piHash(const PIByteArray & ba) {return ba.hash();}
//! \relatesalso PIByteArray
//! \~english Swap contents betwee "f" and "s"
//! \~russian Меняет содержимое массивов "f" и "s"
template<> inline void piSwap(PIByteArray & f, PIByteArray & s) {f.swap(s);}
//! \relatesalso PIByteArray
//! \~english Store "value" to bytearray and returns it
//! \~russian Сохраняет "value" в байтовый массив и возвращает его
template <typename T> PIByteArray piSerialize(const T & value) {
PIByteArray ret;
ret << value;
return ret;
}
//! \relatesalso PIByteArray
//! \~english Restore type "T" from bytearray "data" and returns it
//! \~russian Извлекает тип "T" из байтового массива "data" и возвращает его
template <typename T> T piDeserialize(const PIByteArray & data) {
T ret;
if (!data.isEmpty()) {
PIByteArray ba(data);
ba >> ret;
}
return ret;
}
#endif // PIBYTEARRAY_H