PIMap new functions

PIByteArray checksum crc
some doc fixes
This commit is contained in:
Бычков Андрей
2022-08-04 20:20:08 +03:00
parent 54cc6c55b2
commit 170a713357
8 changed files with 436 additions and 81 deletions

View File

@@ -19,6 +19,9 @@
* \fn PIMap::PIMap(const PIMap & other);
* \brief Contructs a copy of "other"
*
*
*
* \fn PIMapIterator PIMap::makeIterator() const
* \brief Returns PIMapIterator for this map

View File

@@ -42,25 +42,81 @@
template <typename Key, typename T>
class PIMapIterator;
template <typename Key, typename T>
class PIMapReverseIterator;
//! \addtogroup Containers
//! \{
//! \class PIMap
//! \brief
//! \~english Associative array.
//! \~russian Словарь.
//! \~\}
//! \details
//! \~english
//! A collection of key/value pairs, from which you retrieve a value using its associated key.
//! There is a finite number of keys in the map, and each key has exactly one value associated with it.
//! \a value() returns value for key and leave map
//! unchaged in any case. \a operator [] create entry in map if
//! there is no entry for given key. You can retrieve all
//! keys by method \a keys() and all values by methos \a values().
//! To iterate all entries use class PIMapIterator, or methods
//! \a makeIterator() and \a makeReverseIterator().
//! A key in the Map may only occur once.
//! \~russian
//! Словари, в принципе, похожи на обычные, используемые в повседневной жизни.
//! Они хранят элементы одного и того же типа, индексируемые ключевыми значениями.
//! Достоинство словаря в том, что он позволяет быстро получать значение,
//! ассоциированное с заданным ключом.
//! Ключи должны быть уникальными.
//! Элемент
//! В контейнеры этого типа заносятся элементы вместе с ключами,
//! по которым их можно найти, которыми могут выступать значения любого типа.
//! \a operator [] позволяет получить доступ к элементу по ключу,
//! и если такого эелемента небыло, то он будет создан.
template <typename Key, typename T>
class PIMap {
template <typename Key1, typename T1> friend class PIMapIterator;
template <typename Key1, typename T1> friend class PIMapReverseIterator;
template <typename P, typename Key1, typename T1>
friend PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIMap<Key1, T1> & v);
template <typename P, typename Key1, typename T1>
friend PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIMap<Key1, T1> & v);
public:
PIMap() {;}
typedef T mapped_type;
typedef Key key_type;
typedef PIPair<Key, T> value_type;
//! \~english Constructs an empty map.
//! \~russian Создает пустой словарь.
PIMap() {}
//! \~english Copy constructor.
//! \~russian Копирующий конструктор.
PIMap(const PIMap<Key, T> & other) {*this = other;}
//! \~english Move constructor.
//! \~russian Перемещающий конструктор.
PIMap(PIMap<Key, T> && other) : pim_content(std::move(other.pim_content)), pim_index(std::move(other.pim_index)) {}
//! \~english Contructs map 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
//! \~\code
//! PIMap <int, PIString> m{{1, "a"}, {2, "b"}};
//! piCout << m; // {1, 2, 3}
//! \endcode
PIMap(std::initializer_list<std::pair<Key, T>> init_list) {
for (auto i: init_list) {
insert(std::get<0>(i), std::get<1>(i));
}
}
virtual ~PIMap() {;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIMap<Key, T> & operator =(const PIMap<Key, T> & other) {
if (this == &other) return *this;
clear();
@@ -69,15 +125,13 @@ public:
return *this;
}
//! \~english Assign move operator.
//! \~russian Оператор перемещающего присваивания.
PIMap<Key, T> & operator =(PIMap<Key, T> && other) {
swap(other);
return *this;
}
typedef T mapped_type;
typedef Key key_type;
typedef PIPair<Key, T> value_type;
class iterator {
friend class PIMap<Key, T>;
private:
@@ -88,7 +142,9 @@ public:
iterator(): parent(nullptr), pos(0) {}
const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);}
T & value() {return const_cast<PIMap<Key, T> * >(parent)->_value(pos);}
inline PIPair<Key, T> operator *() const {return PIPair<Key, T>(const_cast<PIMap<Key, T> * >(parent)->_key(pos), const_cast<PIMap<Key, T> * >(parent)->_value(pos));}
inline PIPair<Key, T> operator *() const {
return PIPair<Key, T>(const_cast<PIMap<Key, T> * >(parent)->_key(pos), const_cast<PIMap<Key, T> * >(parent)->_value(pos));
}
void operator ++() {++pos;}
void operator ++(int) {++pos;}
void operator --() {--pos;}
@@ -107,7 +163,9 @@ public:
reverse_iterator(): parent(nullptr), pos(0) {}
const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);}
T & value() const {return const_cast<PIMap<Key, T> * >(parent)->_value(pos);}
inline PIPair<Key, T> operator *() const {return PIPair<Key, T>(const_cast<PIMap<Key, T> * >(parent)->_key(pos), const_cast<PIMap<Key, T> * >(parent)->_value(pos));}
inline PIPair<Key, T> operator *() const {
return PIPair<Key, T>(const_cast<PIMap<Key, T> * >(parent)->_key(pos), const_cast<PIMap<Key, T> * >(parent)->_value(pos));
}
void operator ++() {--pos;}
void operator ++(int) {--pos;}
void operator --() {++pos;}
@@ -152,26 +210,45 @@ public:
bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);}
};
iterator begin() {return iterator(this, 0);}
iterator end() {return iterator(this, size());}
const_iterator begin() const {return const_iterator(this, 0);}
const_iterator end() const {return const_iterator(this, size());}
const_iterator constBegin() const {return const_iterator(this, 0);}
const_iterator constEnd() const {return const_iterator(this, size());}
reverse_iterator rbegin() {return reverse_iterator(this, size() - 1);}
reverse_iterator rend() {return reverse_iterator(this, -1);}
const_reverse_iterator rbegin() const {return const_reverse_iterator(this, size() - 1);}
const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);}
const_reverse_iterator constRbegin() const {return const_reverse_iterator(this, size() - 1);}
const_reverse_iterator constRend() const {return const_reverse_iterator(this, -1);}
//! \relatesalso PIMapIterator
PIMapIterator<Key, T> makeIterator() const {return PIMapIterator<Key, T>(*this);}
PIMapIterator<Key, T> makeReverseIterator() const {return PIMapIterator<Key, T>(*this, true);}
//! \relatesalso PIMapReverseIterator
PIMapReverseIterator<Key, T> makeReverseIterator() const {return PIMapReverseIterator<Key, T>(*this);}
size_t size() const {return pim_content.size();}
int size_s() const {return pim_content.size_s();}
size_t length() const {return pim_content.size();}
bool isEmpty() const {return (pim_content.size() == 0);}
bool isNotEmpty() const {return (pim_content.size() > 0);}
T & operator [](const Key & key) {
@@ -184,6 +261,15 @@ public:
}
T at(const Key & key) const {return value(key);}
T take(const Key & key) const {
bool f(false);
ssize_t i = _find(key, f);
if (!f) return T();
T ret(pim_content[pim_index[i].index]);
_remove(i);
return ret;
}
PIMap<Key, T> & operator <<(const PIMap<Key, T> & other) {
#ifndef NDEBUG
if (&other == this) {
@@ -192,24 +278,66 @@ public:
#endif
assert(&other != this);
if (other.isEmpty()) return *this;
if (other.size() == 1) {insert(other.pim_index[0].key, other.pim_content[0]); return *this;}
if (other.size() == 2) {insert(other.pim_index[0].key, other.pim_content[0]); insert(other.pim_index[1].key, other.pim_content[1]); return *this;}
if (other.size() == 1) {
insert(other.pim_index[0].key, other.pim_content[0]);
return *this;
}
if (other.size() == 2) {
insert(other.pim_index[0].key, other.pim_content[0]);
insert(other.pim_index[1].key, other.pim_content[1]);
return *this;
}
for (int i = 0; i < other.pim_index.size_s(); ++i) {
insert(other.pim_index[i].key, other.pim_content[other.pim_index[i].index]);
}
return *this;
}
bool operator ==(const PIMap<Key, T> & t) const {return (pim_content == t.pim_content && pim_index == t.pim_index);}
bool operator !=(const PIMap<Key, T> & t) const {return (pim_content != t.pim_content || pim_index != t.pim_index);}
bool contains(const Key & key) const {bool f(false); _find(key, f); return f;}
bool operator ==(const PIMap<Key, T> & t) const {
return (pim_content == t.pim_content && pim_index == t.pim_index);
}
bool operator !=(const PIMap<Key, T> & t) const {
return (pim_content != t.pim_content || pim_index != t.pim_index);
}
bool contains(const Key & key) const {
bool f(false); _find(key, f);
return f;
}
PIMap<Key, T> & reserve(size_t new_size) {pim_content.reserve(new_size); pim_index.reserve(new_size); return *this;}
bool containsValue(const T & value) const {
return pim_content.contains(value);
}
PIMap<Key, T> & removeOne(const Key & key) {bool f(false); ssize_t i = _find(key, f); if (f) _remove(i); return *this;}
PIMap<Key, T> & remove(const Key & key) {return removeOne(key);}
PIMap<Key, T> & erase(const Key & key) {return removeOne(key);}
PIMap<Key, T> & clear() {pim_content.clear(); pim_index.clear(); return *this;}
PIMap<Key, T> & reserve(size_t new_size) {
pim_content.reserve(new_size);
pim_index.reserve(new_size);
return *this;
}
PIMap<Key, T> & remove(const Key & key) {
bool f(false);
ssize_t i = _find(key, f);
if (f) _remove(i);
return *this;
}
PIMap<Key, T> & removeWhere(std::function<bool(const Key & key, const T & value)> test) {
for (int i = 0; i < pim_index.size_s(); ++i) {
if (pim_index[i].key, pim_content[pim_index[i].index]) {
_remove(i);
--i;
}
}
}
PIMap<Key, T> & erase(const Key & key) {return remove(key);}
PIMap<Key, T> & clear() {
pim_content.clear();
pim_index.clear();
return *this;
}
void swap(PIMap<Key, T> & other) {
pim_content.swap(other.pim_content);
@@ -219,7 +347,6 @@ public:
PIMap<Key, T> & insert(const Key & key, const T & value) {
bool f(false);
ssize_t i = _find(key, f);
//piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value;
if (f) {
pim_content[pim_index[i].index] = value;
} else {
@@ -231,7 +358,6 @@ public:
PIMap<Key, T> & insert(const Key & key, T && value) {
bool f(false);
ssize_t i = _find(key, f);
//piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value;
if (f) {
pim_content[pim_index[i].index] = std::move(value);
} else {
@@ -240,28 +366,85 @@ public:
}
return *this;
}
T value(const Key & key, const T & default_ = T()) const {bool f(false); ssize_t i = _find(key, f); if (!f) return default_; return pim_content[pim_index[i].index];}
PIMap<Key, T> & insert(const PIPair<Key, T> & pair) {
bool f(false);
ssize_t i = _find(pair.first, f);
if (f) {
pim_content[pim_index[i].index] = pair.second;
} else {
pim_content.push_back(pair.second);
pim_index.insert(i, MapIndex(pair.first, pim_content.size() - 1));
}
return *this;
}
PIMap<Key, T> & insert(PIPair<Key, T> && pair) {
bool f(false);
Key k(std::move(pair.first));
ssize_t i = _find(k, f);
if (f) {
pim_content[pim_index[i].index] = std::move(pair.second);
} else {
pim_content.push_back(std::move(pair.second));
pim_index.insert(i, MapIndex(k, pim_content.size() - 1));
}
return *this;
}
T value(const Key & key, const T & default_ = T()) const {
bool f(false);
ssize_t i = _find(key, f);
if (!f) return default_;
return pim_content[pim_index[i].index];
}
PIVector<T> values() const {return pim_content;}
Key key(const T & value_, const Key & default_ = Key()) const {for (int i = 0; i < pim_index.size_s(); ++i) if (pim_content[pim_index[i].index] == value_) return pim_index[i].key; return default_;}
Key key(const T & value_, const Key & default_ = Key()) const {
for (int i = 0; i < pim_index.size_s(); ++i) {
if (pim_content[pim_index[i].index] == value_) {
return pim_index[i].key;
}
}
return default_;
}
PIVector<Key> keys() const {
PIVector<Key> ret;
for (int i = 0; i < pim_index.size_s(); ++i)
ret.reserve(pim_index.size());
for (int i = 0; i < pim_index.size_s(); ++i) {
ret << pim_index[i].key;
}
return ret;
}
// void dump() {
// piCout << "PIMap" << size() << "entries" << PICoutManipulators::NewLine << "content:";
// for (size_t i = 0; i < pim_content.size(); ++i)
// piCout << PICoutManipulators::Tab << i << ":" << pim_content[i];
// piCout << "index:";
// for (size_t i = 0; i < pim_index.size(); ++i)
// piCout << PICoutManipulators::Tab << i << ":" << pim_index[i].key << "->" << pim_index[i].index;
// }
void forEach(std::function<void(const Key & key, const T & value)> f) const {
for (int i = 0; i < pim_index.size_s(); ++i) {
f(pim_index[i].key, pim_content[pim_index[i].index]);
}
}
template <typename Key2, typename T2>
inline PIMap<Key2, T2> map(std::function<PIPair<Key2, T2>(const Key & key, const T & value)> f) const {
PIMap<Key2, T2> ret; ret.reserve(size());
for (int i = 0; i < pim_index.size_s(); ++i) {
ret.insert(f(pim_index[i].key, pim_content[pim_index[i].index]));
}
return ret;
}
template <typename ST>
inline PIVector<ST> map(std::function<ST(const Key & key, const T & value)> f) const {
PIVector<ST> ret; ret.reserve(size());
for (int i = 0; i < pim_index.size_s(); ++i) {
ret << f(pim_index[i].key, pim_content[pim_index[i].index]);
}
return ret;
}
private:
struct MapIndex {
MapIndex(Key k = Key(), size_t i = 0): key(k), index(i) {;}
MapIndex(const Key & k = Key(), size_t i = 0): key(k), index(i) {}
MapIndex(Key && k, size_t i = 0): key(std::move(k)), index(i) {}
Key key;
size_t index;
bool operator ==(const MapIndex & s) const {return key == s.key;}
@@ -269,6 +452,7 @@ private:
bool operator <(const MapIndex & s) const {return key < s.key;}
bool operator >(const MapIndex & s) const {return key > s.key;}
};
template <typename P, typename Key1, typename T1>
friend PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIDeque<typename PIMap<Key1, T1>::MapIndex> & v);
template <typename P, typename Key1, typename T1>
@@ -285,6 +469,7 @@ private:
found = false;
return first;
}
ssize_t _find(const Key & k, bool & found) const {
if (pim_index.isEmpty()) {
found = false;
@@ -292,75 +477,213 @@ private:
}
return _binarySearch(0, pim_index.size_s() - 1, k, found);
}
void _remove(ssize_t index) {
//if (index >= pim_index.size()) return;
size_t ci = pim_index[index].index, bi = pim_index.size() - 1;
pim_index.remove(index);
for (size_t i = 0; i < pim_index.size(); ++i)
for (size_t i = 0; i < pim_index.size(); ++i) {
if (pim_index[i].index == bi) {
pim_index[i].index = ci;
break;
}
}
piSwap<T>(pim_content[ci], pim_content.back());
pim_content.resize(pim_index.size());
}
const value_type _pair(ssize_t index) const {
if (index < 0 || index >= pim_index.size_s())
return value_type();
//piCout << "_pair" << index << pim_index[index].index;
if (index < 0 || index >= pim_index.size_s()) return value_type();
return value_type(pim_index[index].key, pim_content[pim_index[index].index]);
}
Key & _key(ssize_t index) {return pim_index[index].key;}
const Key & _key(ssize_t index) const {return pim_index[index].key;}
T & _value(ssize_t index) {return pim_content[pim_index[index].index];}
const T & _value(ssize_t index) const {return pim_content[pim_index[index].index];}
PIVector<T> pim_content;
PIDeque<MapIndex> pim_index;
};
//! \addtogroup Containers
//! \{
//! \class PIMapIterator
//! \brief
//! \~english Java-style iterator for \a PIMap.
//! \~russian Итератор Java стиля для \a PIMap.
//! \~\}
//! \details
//! \~english
//! This class used to easy serial access keys and values in PIMap.
//! You can use constructor to create iterator, or use \a PIMap::makeIterator()
//! \~russian
//! Этот класс используется для удобного перебора ключей и значений всего словаря в обратном порядке.
//! Ты можешь использовать конструктор, в который передать словарь, или функцию словаря \a PIMap::makeReverseIterator().
//! \~
//! \code
//! PIMap<int, PIString> m;
//! m[1] = "one";
//! m[2] = "two";
//! m[4] = "four";
//! auto it = m.makeIterator();
//! while (it.next()) {
//! piCout << it.key() << it.value();
//! // 1 one
//! // 2 two
//! // 4 four
//! \endcode
template <typename Key, typename T>
class PIMapIterator {
typedef PIMap<Key, T> MapType;
public:
PIMapIterator(const PIMap<Key, T> & map, bool reverse = false): m(map), pos(-1), rev(reverse) {
if (rev) pos = m.size_s();
PIMapIterator(const PIMap<Key, T> & map, bool reverse = false): m(map), pos(-1) {}
//! \~english Returns current key.
//! \~russian Возвращает ключ текущего элемента.
//! \~\sa \a value(), \a valueRef()
const Key & key() const {
return m._key(pos);
}
const Key & key() const {return const_cast<MapType & >(m)._key(pos);}
const T & value() const {return const_cast<MapType & >(m)._value(pos);}
T & valueRef() const {return const_cast<MapType & >(m)._value(pos);}
//! \~english Returns current value.
//! \~russian Возвращает значение текущего элемента.
//! \~\sa \a key(), \a valueRef()
const T & value() const {
return m._value(pos);
}
//! \~english Returns current value reference.
//! \~russian Возвращает изменяемую ссылку на значение текущего элемента.
//! \~\sa \a key(), \a value()
T & valueRef() {
return const_cast<MapType & >(m)._value(pos);
}
//! \~english Returns true if iterator can jump to next entry
//! \~russian Возвращает true если итератор может перейти к следующему элементу.
inline bool hasNext() const {
if (rev) {
return pos > 0;
} else {
return pos < (m.size_s() - 1);
}
return false;
return pos < (m.size_s() - 1);
}
//! \~english Jump to next entry and return true if new position is valid.
//! \~russian Переходит к следующему элементу и возвращает true если он существует.
inline bool next() {
if (rev) {
--pos;
return pos >= 0;
} else {
++pos;
return pos < m.size_s();
}
return false;
++pos;
return pos < m.size_s();
}
//! \~english Reset iterator to initial position.
//! \~russian Переходит на начало.
inline void reset() {
if (rev) {
pos = m.size_s();
} else {
pos = -1;
}
pos = -1;
}
private:
const MapType & m;
ssize_t pos;
};
//! \addtogroup Containers
//! \{
//! \class PIMapReverseIterator
//! \brief
//! \~english Java-style reverse iterator for \a PIMap.
//! \~russian Итератор Java стиля для \a PIMap в обратном порядке.
//! \~\}
//! \details
//! \~english
//! This class used to easy serial reverse access keys and values in PIMap.
//! You can use constructor to create iterator, or use \a PIMap::makeReverseIterator().
//! \~russian
//! Этот класс используется для удобного перебора ключей и значений всего словаря в обратном порядке.
//! Ты можешь использовать конструктор, в который передать словарь, или функцию словаря \a PIMap::makeReverseIterator().
//! \~
//! \code
//! PIMap<int, PIString> m;
//! m[1] = "one";
//! m[2] = "two";
//! m[4] = "four";
//! auto it = m.makeReverseIterator();
//! while (it.next()) {
//! piCout << it.key() << it.value();
//! }
//! // 4 four
//! // 2 two
//! // 1 one
//! \endcode
//! \~english Write access:
//! \~russian Доступ на запись:
//! \~
//! \code
//! while (it.next()) {
//! it.valueRef().append("_!");
//! piCout << it.key() << it.value();
//! }
//! // 4 four_!
//! // 2 two_!
//! // 1 one_!
//! \endcode
template <typename Key, typename T>
class PIMapReverseIterator {
typedef PIMap<Key, T> MapType;
public:
PIMapReverseIterator(const PIMap<Key, T> & map): m(map), pos(m.size_s()) {}
//! \~english Returns current key.
//! \~russian Возвращает ключ текущего элемента.
//! \~\sa \a value(), \a valueRef()
const Key & key() const {
return m._key(pos);
}
//! \~english Returns current value.
//! \~russian Возвращает значение текущего элемента.
//! \~\sa \a key(), \a valueRef()
const T & value() const {
return m._value(pos);
}
//! \~english Returns current value reference.
//! \~russian Возвращает изменяемую ссылку на значение текущего элемента.
//! \~\sa \a key(), \a value()
T & valueRef() {
return const_cast<MapType & >(m)._value(pos);
}
//! \~english Returns true if iterator can jump to next entry
//! \~russian Возвращает true если итератор может перейти к следующему элементу.
inline bool hasNext() const {
return pos > 0;
}
//! \~english Jump to next entry and return true if new position is valid.
//! \~russian Переходит к следующему элементу и возвращает true если он существует.
inline bool next() {
--pos;
return pos >= 0;
}
//! \~english Reset iterator to initial position.
//! \~russian Переходит на начало.
inline void reset() {
pos = m.size_s();
}
private:
const MapType & m;
ssize_t pos;
bool rev;
};
#ifdef PIP_STD_IOSTREAM
//! \~english Output operator to [std::ostream](https://en.cppreference.com/w/cpp/io/basic_ostream).
//! \~russian Оператор вывода в [std::ostream](https://ru.cppreference.com/w/cpp/io/basic_ostream).
template<typename Key, typename Type>
inline std::ostream & operator <<(std::ostream & s, const PIMap<Key, Type> & v) {
s << "{";
@@ -376,6 +699,10 @@ inline std::ostream & operator <<(std::ostream & s, const PIMap<Key, Type> & v)
}
#endif
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
template<typename Key, typename Type>
inline PICout operator <<(PICout s, const PIMap<Key, Type> & v) {
s.space();
@@ -393,7 +720,8 @@ inline PICout operator <<(PICout s, const PIMap<Key, Type> & v) {
return s;
}
template<typename Key, typename Type> inline void piSwap(PIMap<Key, Type> & f, PIMap<Key, Type> & s) {f.swap(s);}
template<typename Key, typename Type>
inline void piSwap(PIMap<Key, Type> & f, PIMap<Key, Type> & s) {f.swap(s);}
#endif // PIMAP_H

View File

@@ -37,13 +37,7 @@ public:
T pop() {return PIVector<T>::take_back();}
T & top() {return PIVector<T>::back();}
const T & top() const {return PIVector<T>::back();}
PIVector<T> toVector() {
PIVector<T> v;
v.reserve(PIVector<T>::size());
for (uint i = 0; i < PIVector<T>::size(); ++i)
v.push_back(PIVector<T>::at(i));
return v;
}
PIVector<T> toVector() {return PIVector<T>(*this);}
};
#endif // PISTACK_H

View File

@@ -20,6 +20,7 @@
#include "pibytearray.h"
#include "pistringlist.h"
#include <iostream>
#include "picrc.h"
//! \class PIByteArray pibytearray.h
//! \~\details
@@ -292,6 +293,19 @@ uchar PIByteArray::checksumPlain8(bool inverse) const {
}
uchar PIByteArray::checksumCRC8() const {
return standardCRC_8().calculate(data(), size());
}
ushort PIByteArray::checksumCRC16() const {
return standardCRC_16().calculate(data(), size());
}
uint PIByteArray::checksumCRC32() const {
return standardCRC_32().calculate(data(), size());
}
//! \~\details
//! \~english
//! This is sum of all bytes multiplied by index+1, if inverse then add 1 and inverse.

View File

@@ -1111,6 +1111,18 @@ public:
//! \~russian Возвращает 32-битную контрольную сумму
uint checksumPlain32(bool inverse = true) const;
//! \~english Returns 8-bit checksum CRC-8
//! \~russian Возвращает 8-битную контрольную сумму CRC-8
uchar checksumCRC8() const;
//! \~english Returns 16-bit checksum CRC-16
//! \~russian Возвращает 16-битную контрольную сумму CRC-16
ushort checksumCRC16() const;
//! \~english Returns 32-bit checksum CRC-32
//! \~russian Возвращает 32-битную контрольную сумму CRC-32
uint checksumCRC32() const;
//! \~english Returns hash of content
//! \~russian Возвращает хэш содержимого
uint hash() const;

View File

@@ -376,7 +376,7 @@ bool PIConnection::removeDevice(const PIString & full_path) {
if (!dev) return false;
PIStringList dntd(deviceNames(dev));
for (const PIString & n : dntd) {
device_names.removeOne(n);
device_names.remove(n);
}
for (auto s = senders.constBegin(); s != senders.constEnd(); s++) {
if (!s.value()) continue;

View File

@@ -39,16 +39,20 @@
#pragma pack(push, 1)
//! \~english
//! \brief A class that works with square matrix operations, the input data of which are columns, rows and the data type of the matrix.
//! \brief A class for fixed size and type matrix.
//! \tparam `Rows` rows number of matrix.
//! \tparam `Сols` columns number of matrix.
//! \tparam `Type` is the data type of the matrix. There are can be basic C++ language data and different classes where the arithmetic operators(=, +=, -=, *=, /=, ==, !=, +, -, *, /)
//! of the C++ language are implemented
//! \~russian
//! \brief Класс, работающий с операциями над квадратными матрицами, входными данными которого являются столбцы, строки и матричный типа данных.
//! \brief Класс для работы с матрицами фиксированного размера и типа данных.
//! \details В отличие от \a PIMathMatrix не занимается динамическим выделением памяти и связанными с этим операциями.
//! То есть он тривиально копируемый.
//! Содержит проверки времени компиляции на несоответствие размера при различных математических операциях,
//! что позволяет заранее выявлять ошибки.
//! \tparam `Rows` количество строк матрицы.
//! \tparam `Сols` количество столбцов матрицы.
//! \tparam `Type`типа данных матрицы. Здесь можеть быть базовый тип данных C++ или различные классы,
//! \tparam `Type`тип данных матрицы. Здесь можеть быть базовый тип данных C++ или различные классы,
//! где реализованы арифметические операторы(=, +=, -=, *=, /=, ==, !=, +, -, *, /) языка C++.
template<uint Rows, uint Cols = Rows, typename Type = double>
class PIP_EXPORT PIMathMatrixT {
@@ -828,12 +832,12 @@ class PIMathMatrix;
#define PIMM_FOR_R for (uint i = 0; i < _V2D::rows_; ++i)
//! \~english
//! \brief A class that works with matrix operations, the input data of which is the data type of the matrix.
//! @tparam `Type` There are can be basic C++ language data and different classes where the arithmetic operators(=, +=, -=, *=, /=, ==, !=, +, -, *, /)
//! \brief A class for dynamic size and fixed type matrix.
//! \tparam `Type` There are can be basic C++ language data and different classes where the arithmetic operators(=, +=, -=, *=, /=, ==, !=, +, -, *, /)
//! of the C++ language are implemented.
//! \~russian
//! \brief Класс, работающий с матричными операциями, входными данными которого является тип данных матрицы.
//! @tparam `Type` Здесь можеть быть базовый тип данных C++ или различные классы,
//! \brief Класс для работы с матрицами динамического размера и фиксированного типа.
//! \tparam `Type` Здесь можеть быть базовый тип данных C++ или различные классы,
//! где реализованы арифметические операторы(=, +=, -=, *=, /=, ==, !=, +, -, *, /) языка C++.
template<typename Type>
class PIP_EXPORT PIMathMatrix : public PIVector2D<Type> {

View File

@@ -42,7 +42,7 @@ void CloudServer::addClient(DispatcherClient * c) {
void CloudServer::removeClient(DispatcherClient * c) {
last_ping.reset();
clients.removeOne(c);
index_clients.removeOne(c->clientId());
index_clients.remove(c->clientId());
server->sendDisconnected(c->clientId());
}