version 3.14.0

PIBinaryStream::wasReadError() method, remove incomplete read asserts
This commit is contained in:
2023-08-30 12:18:04 +03:00
parent c86ec0ae82
commit 0907a3eb13
5 changed files with 118 additions and 48 deletions

View File

@@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.0)
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
project(PIP)
set(PIP_MAJOR 3)
set(PIP_MINOR 13)
set(PIP_REVISION 2)
set(PIP_MINOR 14)
set(PIP_REVISION 0)
set(PIP_SUFFIX )
set(PIP_COMPANY SHS)
set(PIP_DOMAIN org.SHS)

View File

@@ -2,6 +2,7 @@
\~russian \page iostream Поток ввода/вывода
\~english
\~russian
%PIBinaryStream представляет собой интерфейс бинарной сериализации.
Не может быть использован в чистом виде, только в виде миксина или
@@ -115,3 +116,10 @@ for (int i = 0; i < 10; ++i)
0.8
0.9
\endcode
\~english
\~russian
Если при чтении из потока не хватило данных (например, закончился массив или файл), то проверка
объекта потока на wasReadError() вернёт true. Рекомендуется делать эту проверку после чтения
данных для корректной обработки ошибки.

View File

@@ -44,7 +44,10 @@ public:
//! \~english Assign "device" device
//! \~russian Назначает устройство "device"
void setDevice(PIIODevice * device) { dev = device; }
void setDevice(PIIODevice * device) {
dev = device;
resetReadError();
}
bool binaryStreamAppendImp(const void * d, size_t s) {
if (!dev) return false;

View File

@@ -65,6 +65,7 @@
template<typename P>
class PIBinaryStream {
public:
//! \~english Write data
//! \~russian Записать данные
bool binaryStreamAppend(const void * d, size_t s) {
if (!static_cast<P *>(this)->binaryStreamAppendImp(d, s)) {
@@ -73,32 +74,50 @@ public:
}
return true;
}
//! \~english Read data
//! \~russian Прочитать данные
bool binaryStreamTake(void * d, size_t s) {
if (!static_cast<P *>(this)->binaryStreamTakeImp(d, s)) {
_was_read_error_ = true;
return false;
printf("[PIBinaryStream] binaryStreamTake() error\n");
}
return true;
}
//! \~russian Узнать оставшийся размер
//! \~english Returns remain size
//! \~russian Возвращает оставшийся размер
//! \~\details
//! \~english Returns -1 if no information about size
//! \~russian Возвращает -1 если нет информации о размере
ssize_t binaryStreamSize() const { return static_cast<const P *>(this)->binaryStreamSizeImp(); }
//! \~english Write data
//! \~russian Записать данные
template<typename T>
void binaryStreamAppend(T v) {
binaryStreamAppend(&v, sizeof(v));
}
//! \~english Read int
//! \~russian Прочитать int
int binaryStreamTakeInt() {
int r = 0;
binaryStreamTake(&r, sizeof(r));
return r;
}
//! \~english Returns whether there has been an incomplete read since last \a resetReadError() or after the stream was created
//! \~russian Возвращает было ли неполное чтение с момента последнего вызова \a resetReadError()
bool wasReadError() const { return _was_read_error_; }
//! \~english Reset incomplete read flag
//! \~russian Сбрасывает флаг неполного чтения
void resetReadError() { _was_read_error_ = false; }
private:
bool _was_read_error_ = false;
};
@@ -305,7 +324,6 @@ template<typename P,
inline PIBinaryStreamTrivialRef<P> operator>>(PIBinaryStream<P> & s, T & v) {
if (!s.binaryStreamTake(&v, sizeof(v))) {
printf("error with %s\n", __PIP_TYPENAME__(T));
assert(false);
}
return s;
}
@@ -322,10 +340,15 @@ template<typename P,
inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIVector<T> & v) {
// piCout << ">> vector trivial default";
int sz = s.binaryStreamTakeInt();
if (s.wasReadError()) {
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
v.clear();
return s;
}
v._resizeRaw(sz);
if (!s.binaryStreamTake(v.data(), sz * sizeof(T))) {
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
assert(false);
v.clear();
}
return s;
}
@@ -338,9 +361,20 @@ template<typename P,
inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIVector<T> & v) {
// piCout << ">> vector trivial custom";
int sz = s.binaryStreamTakeInt();
if (s.wasReadError()) {
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
v.clear();
return s;
}
v._resizeRaw(sz);
for (int i = 0; i < sz; ++i)
for (int i = 0; i < sz; ++i) {
s >> v[i];
if (s.wasReadError()) {
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
v.clear();
return s;
}
}
return s;
}
@@ -356,10 +390,15 @@ template<typename P,
inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIDeque<T> & v) {
// piCout << ">> deque trivial default";
int sz = s.binaryStreamTakeInt();
if (s.wasReadError()) {
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
v.clear();
return s;
}
v._resizeRaw(sz);
if (!s.binaryStreamTake(v.data(), sz * sizeof(T))) {
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
assert(false);
v.clear();
}
return s;
}
@@ -372,9 +411,20 @@ template<typename P,
inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIDeque<T> & v) {
// piCout << ">> deque trivial custom";
int sz = s.binaryStreamTakeInt();
if (s.wasReadError()) {
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
v.clear();
return s;
}
v._resizeRaw(sz);
for (int i = 0; i < sz; ++i)
for (int i = 0; i < sz; ++i) {
s >> v[i];
if (s.wasReadError()) {
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
v.clear();
return s;
}
}
return s;
}
@@ -392,10 +442,15 @@ inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIVector2D<T> & v)
int r, c;
r = s.binaryStreamTakeInt();
c = s.binaryStreamTakeInt();
if (s.wasReadError()) {
printf("error with PIVector2D<%s>\n", __PIP_TYPENAME__(T));
v.clear();
return s;
}
v._resizeRaw(r, c);
if (!s.binaryStreamTake(v.data(), v.size() * sizeof(T))) {
printf("error with PIVector2D<%s>\n", __PIP_TYPENAME__(T));
assert(false);
v.clear();
}
return s;
}
@@ -481,14 +536,15 @@ inline PIBinaryStream<P> & operator<<(PIBinaryStream<P> & s, const PIVector2D<T>
//! \~russian Оператор извлечения для PIVector сложных типов
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIVector<T> & v) {
// piCout << ">> vector complex";
/*if (s.size_s() < 4) {
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 4);
}*/
v.resize(s.binaryStreamTakeInt());
for (size_t i = 0; i < v.size(); ++i)
for (size_t i = 0; i < v.size(); ++i) {
s >> v[i];
if (s.wasReadError()) {
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
v.clear();
return s;
}
}
return s;
}
@@ -497,14 +553,15 @@ inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIVector<T> & v) {
//! \~russian Оператор извлечения для PIDeque сложных типов
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIDeque<T> & v) {
// piCout << ">> deque complex";
/*if (s.size_s() < 4) {
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 4);
}*/
v.resize(s.binaryStreamTakeInt());
for (size_t i = 0; i < v.size(); ++i)
for (size_t i = 0; i < v.size(); ++i) {
s >> v[i];
if (s.wasReadError()) {
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
v.clear();
return s;
}
}
return s;
}
@@ -513,11 +570,6 @@ inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIDeque<T> & v) {
//! \~russian Оператор извлечения для PIVector2D сложных типов
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIVector2D<T> & v) {
// piCout << ">> vector2d complex";
/*if (s.size_s() < 8) {
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 8);
}*/
int r, c;
PIVector<T> tmp;
r = s.binaryStreamTakeInt();
@@ -549,19 +601,25 @@ inline PIBinaryStream<P> & operator<<(PIBinaryStream<P> & s, const PIMap<Key, T>
//! \~russian Оператор извлечения
template<typename P, typename Key, typename T>
inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIMap<Key, T> & v) {
/*if (s.size_s() < 4) {
printf("error with PIMap<%s, %s>\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T));
assert(s.size_s() >= 4);
}*/
int sz = s.binaryStreamTakeInt();
v.pim_index.resize(sz);
int ind = 0;
for (int i = 0; i < sz; ++i) {
ind = s.binaryStreamTakeInt();
s >> v.pim_index[i].key;
if (s.wasReadError()) {
printf("error with PIMap<%s, %s>\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T));
v.clear();
return s;
}
v.pim_index[i].index = ind;
}
s >> v.pim_content;
if (s.wasReadError()) {
printf("error with PIMap<%s, %s>\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T));
v.clear();
return s;
}
if (v.pim_content.size_s() != v.pim_index.size_s()) {
piCout << "Warning: loaded invalid PIMap, clear";
v.clear();

View File

@@ -1820,6 +1820,7 @@ BINARY_STREAM_WRITE(PIString) {
//! \~russian Оператор извлечения.
BINARY_STREAM_READ(PIString) {
s >> v.d;
if (s.wasReadError()) v.clear();
return s;
}