version 3.19.0

PIMathVectorT subvector methods
PISystemTime::isNull()
PISystemTime::Frequency::isNull()
PISystemTime::toString()
PISystemTime::fromString()
PIVariant can handle strings with PISystemTime
PIDateTime::toSystemTime() now returns null time from invalid strings
This commit is contained in:
2024-05-05 00:17:52 +03:00
parent a86e8f7b58
commit 491d89f117
9 changed files with 234 additions and 7 deletions

View File

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

View File

@@ -29,6 +29,51 @@
#include "pisystemtime.h" #include "pisystemtime.h"
//! \~\brief
//! \~english PISystemTime from days
//! \~russian PISystemTime из дней
inline PISystemTime operator""_d(long double v) {
return PISystemTime::fromSeconds(v * 60. * 60. * 24.);
}
//! \~\brief
//! \~english PISystemTime from days
//! \~russian PISystemTime из дней
inline PISystemTime operator""_d(unsigned long long v) {
return PISystemTime::fromSeconds(v * 60. * 60. * 24.);
}
//! \~\brief
//! \~english PISystemTime from hours
//! \~russian PISystemTime из часов
inline PISystemTime operator""_h(long double v) {
return PISystemTime::fromSeconds(v * 60. * 60.);
}
//! \~\brief
//! \~english PISystemTime from hours
//! \~russian PISystemTime из часов
inline PISystemTime operator""_h(unsigned long long v) {
return PISystemTime::fromSeconds(v * 60. * 60.);
}
//! \~\brief
//! \~english PISystemTime from minutes
//! \~russian PISystemTime из минут
inline PISystemTime operator""_m(long double v) {
return PISystemTime::fromSeconds(v * 60.);
}
//! \~\brief
//! \~english PISystemTime from minutes
//! \~russian PISystemTime из минут
inline PISystemTime operator""_m(unsigned long long v) {
return PISystemTime::fromSeconds(v * 60.);
}
//! \~\brief //! \~\brief
//! \~english PISystemTime from seconds //! \~english PISystemTime from seconds
//! \~russian PISystemTime из секунд //! \~russian PISystemTime из секунд

View File

@@ -127,6 +127,8 @@ public:
Type & operator[](uint index) { return c[index]; } Type & operator[](uint index) { return c[index]; }
const Type & operator[](uint index) const { return c[index]; } const Type & operator[](uint index) const { return c[index]; }
Type at(uint index) const { return c[index]; } Type at(uint index) const { return c[index]; }
inline Type & element(uint index) { return c[index]; }
inline const Type & element(uint index) const { return c[index]; }
_CVector & operator=(const Type & v) { _CVector & operator=(const Type & v) {
PIMV_FOR c[i] = v; PIMV_FOR c[i] = v;
@@ -225,6 +227,53 @@ public:
return tv; return tv;
} }
//! \~english
//! \brief Returns this vector with another element type.
//! \~russian
//! \brief Возвращает этот вектор с другим типом элементов.
template<typename T>
PIMathVectorT<Size, T> toType() const {
PIMathVectorT<Size, T> ret;
PIMV_FOR ret[i] = element(i);
return ret;
}
//! \~english
//! \brief Returns the subvector with size SubSize. Elements takes from coordinates "offset".
//! \details
//! \~russian
//! \brief Возвращает подвектор с размерами SubSize. Элементы берутся с координат "offset".
//! \details Координаты могут быть отрицательными. Возвращаемый подвектор может быть любого размера. Если исходные элементы выходят
//! за границы исходного подвектора, то в подвекторе будут нули.
template<uint SubSize>
PIMathVectorT<SubSize, Type> subvector(int offset = 0) const {
PIMathVectorT<SubSize, Type> ret;
for (int i = 0; i < (int)SubSize; ++i) {
int si = i + offset;
if (si < 0 || si >= (int)Size) continue;
ret[i] = element(si);
}
return ret;
}
//! \~english
//! \brief Set the subvector "v" in coordinates "index".
//! \details
//! \~russian
//! \brief Устанавливает подвектор "v" в координаты "index".
//! \details Присваивает значения из вектора "v" в область текущиего вектора, ограниченную
//! размерами "v", самого вектор и границами, исходя из координат установки. Координаты могут быть отрицательными.
//! Вектор "v" может быть любого размера. Возвращает ссылку на этот вектор.
template<uint SubSize>
PIMathVectorT<Size, Type> & setSubvector(int index, const PIMathVectorT<SubSize, Type> & v) {
for (int i = 0; i < (int)SubSize; ++i) {
int si = i + index;
if (si < 0 || si >= (int)Size) continue;
element(si) = v[i];
}
return *this;
}
static _CVector cross(const _CVector & v1, const _CVector & v2) { return v1.cross(v2); } static _CVector cross(const _CVector & v1, const _CVector & v2) { return v1.cross(v2); }
static _CVector dot(const _CVector & v1, const _CVector & v2) { return v1.dot(v2); } static _CVector dot(const _CVector & v1, const _CVector & v2) { return v1.dot(v2); }
static _CVector mul(const _CVector & v1, const _CVector & v2) { return v1.mul(v2); } static _CVector mul(const _CVector & v1, const _CVector & v2) { return v1.mul(v2); }

View File

@@ -364,6 +364,11 @@ PIDateTime PIDateTime::fromString(PIString string, PIString format) {
} }
PISystemTime PIDateTime::toSystemTime() const {
return PISystemTime(piMaxi(0, int(toSecondSinceEpoch())), milliseconds * 1000000);
}
PIDateTime PIDateTime::fromSecondSinceEpoch(const time_t sec) { PIDateTime PIDateTime::fromSecondSinceEpoch(const time_t sec) {
tm * pt = localtime(&sec); tm * pt = localtime(&sec);
PIDateTime dt; PIDateTime dt;

View File

@@ -256,7 +256,7 @@ public:
//! \~english Returns time as %PISystemTime //! \~english Returns time as %PISystemTime
//! \~russian Возвращает время как %PISystemTime //! \~russian Возвращает время как %PISystemTime
PISystemTime toSystemTime() const { return PISystemTime(int(toSecondSinceEpoch()), milliseconds * 1000000); } PISystemTime toSystemTime() const;
//! \~english Returns date part //! \~english Returns date part
//! \~russian Возвращает дату //! \~russian Возвращает дату

View File

@@ -20,6 +20,8 @@
#include "pisystemtime.h" #include "pisystemtime.h"
#include "piincludes_p.h" #include "piincludes_p.h"
#include "piiostream.h"
#include "piliterals_time.h"
#include "pitime.h" #include "pitime.h"
#include <ctime> #include <ctime>
@@ -115,6 +117,41 @@ void PISystemTime::toTimespec(void * ts) {
} }
PIString PISystemTime::toString() const {
static const PISystemTime is_abs_thr = 3650._d; // 10 years
if ((*this) >= is_abs_thr) return PIDateTime::fromSystemTime((*this)).toString("yyyy-MM-dd hh:mm:ss.zzz");
auto extract = [](int & secs, int part) {
int p = secs / part;
secs -= p * part;
return p;
};
int s = seconds;
int d = extract(s, 60 * 60 * 24);
int h = extract(s, 60 * 60);
int m = extract(s, 60);
int ns = nanoseconds;
int ms = extract(ns, 1000000);
int us = extract(ns, 1000);
PIString ret;
PIIOTextStream ts(&ret, PIIODevice::WriteOnly);
auto print = [&ts, &ret](int part, const char * name) {
if (part > 0) {
if (ret.isNotEmpty()) ts << ' ';
ts << part << ' ' << name;
}
};
print(d, "d");
print(h, "h");
print(m, "m");
print(s, "s");
print(ms, "ms");
print(us, "us");
print(ns, "ns");
return ret;
}
PISystemTime PISystemTime::abs() const { PISystemTime PISystemTime::abs() const {
if (seconds < 0) if (seconds < 0)
return PISystemTime(piAbsl(seconds) - 1, 1000000000l - piAbsl(nanoseconds)); return PISystemTime(piAbsl(seconds) - 1, 1000000000l - piAbsl(nanoseconds));
@@ -123,6 +160,58 @@ PISystemTime PISystemTime::abs() const {
} }
PISystemTime PISystemTime::fromString(PIString s) {
if (s.findAny("-:") >= 0) {
return PIDateTime::fromString(s, "y-M-d h:m:s.z").toSystemTime();
}
// clang-format off
static const PIMap<PIString, PISystemTime> times({
{"d", 1_d}, {"day", 1_d}, {"days", 1_d},
{"h", 1_h}, {"hour", 1_h}, {"hours", 1_h},
{"m", 1_m}, {"min", 1_m}, {"mins", 1_m}, {"minute", 1_m}, {"minutes", 1_m},
{"s", 1_s}, {"sec", 1_s}, {"secs", 1_s}, {"second", 1_s}, {"seconds", 1_s},
{"ms", 1_ms}, {"msec", 1_ms}, {"msecs", 1_ms}, {"millisecond", 1_ms}, {"milliseconds", 1_ms}, {"milli", 1_ms}, {"millis", 1_ms},
{"us", 1_us}, {"usec", 1_us}, {"usecs", 1_us}, {"microsecond", 1_us}, {"microseconds", 1_us}, {"micro", 1_us}, {"micros", 1_us},
{"ns", 1_ns}, {"nsec", 1_ns}, {"nsecs", 1_ns}, {"nanosecond", 1_ns}, {"nanoseconds", 1_ns}, {"nano", 1_ns}, {"nanos", 1_ns}
});
static const PIMap<PIString, PISystemTime::Frequency> freqs({
{"hz", 1_Hz},
{"khz", 1_KHz},
{"mhz", 1_MHz},
{"ghz", 1_GHz}
});
static const PIString num_syms = PIStringAscii("0123456789.eE+-");
// clang-format on
s = s.toLowerCase();
PISystemTime sum_t;
PISystemTime::Frequency sum_f;
auto extract = [&sum_t, &sum_f](PIString & str) {
PIString vn, pn;
str.trim();
bool found = false;
for (int i = 0; i < str.size_s(); ++i)
if (!num_syms.contains(str[i])) {
vn = str.takeLeft(i);
found = true;
break;
}
if (!found) return false;
pn = str.takeWord();
if (pn.isEmpty()) return false;
if (times.contains(pn))
sum_t += times.value(pn) * vn.toDouble();
else if (freqs.contains(pn))
sum_f += freqs.value(pn) * vn.toDouble();
return true;
};
while (extract(s))
;
if (!sum_t.isNull() && !sum_f.isNull()) piCout << "[PISystemTime] fromString() warning: ambiguous string, time and frequency!";
if (sum_t.isNull() && !sum_f.isNull()) sum_t = sum_f.toSystemTime();
return sum_t;
}
PISystemTime PISystemTime::current(bool precise_but_not_system) { PISystemTime PISystemTime::current(bool precise_but_not_system) {
#ifdef WINDOWS #ifdef WINDOWS
if (precise_but_not_system) { if (precise_but_not_system) {

View File

@@ -67,6 +67,10 @@ public:
//! \~russian Создает нулевую частоту //! \~russian Создает нулевую частоту
Frequency() {} Frequency() {}
//! \~english Returns if frequency is null
//! \~russian Возвращает нулевая ли частота
bool isNull() const { return value_hz == 0.; }
//! \~english Returns frequency as hertz //! \~english Returns frequency as hertz
//! \~russian Возвращает частоту в герцах //! \~russian Возвращает частоту в герцах
double toHertz() const { return value_hz; } double toHertz() const { return value_hz; }
@@ -186,6 +190,10 @@ public:
}; };
//! \~english Returns if time is null
//! \~russian Возвращает нулевое ли время
bool isNull() const { return (seconds == 0) && (nanoseconds == 0); }
//! \~english Returns time value in seconds //! \~english Returns time value in seconds
//! \~russian Возвращает значение времени в секундах //! \~russian Возвращает значение времени в секундах
double toSeconds() const { return double(seconds) + nanoseconds / 1.e+9; } double toSeconds() const { return double(seconds) + nanoseconds / 1.e+9; }
@@ -240,6 +248,10 @@ public:
//! \~russian На *nix системах присваивает время к timespec структуре //! \~russian На *nix системах присваивает время к timespec структуре
void toTimespec(void * ts); void toTimespec(void * ts);
//! \~english Returns "yyyy-MM-dd hh:mm:ss.zzz" for absolute time and "<V> <d|h|m|s|ms|us|ns> ..." for relative
//! \~russian Возвращает "yyyy-MM-dd hh:mm:ss.zzz" для абсолютного времени и "<V> <d|h|m|s|ms|us|ns> ..." для относительного
PIString toString() const;
//! \~english Returns copy of this time with absolutely values of s and ns //! \~english Returns copy of this time with absolutely values of s and ns
//! \~russian Возвращает копию времени с модулем значения //! \~russian Возвращает копию времени с модулем значения
PISystemTime abs() const; PISystemTime abs() const;
@@ -370,6 +382,10 @@ public:
return PISystemTime(s, int((v / 1000000000. - s) * 1000000000.)); return PISystemTime(s, int((v / 1000000000. - s) * 1000000000.));
} }
//! \~english Contructs time from string "s" ("yyyy-MM-dd hh:mm:ss.zzz" or free form)
//! \~russian Создает время из строки "s" ("yyyy-MM-dd hh:mm:ss.zzz", либо произвольная форма)
static PISystemTime fromString(PIString s);
//! \~english Returns current system time //! \~english Returns current system time
//! \~russian Возвращает текущее системное время //! \~russian Возвращает текущее системное время
static PISystemTime current(bool precise_but_not_system = false); static PISystemTime current(bool precise_but_not_system = false);

View File

@@ -137,6 +137,9 @@ void PIVariant::setValueFromString(const PIString & v) {
case PIVariant::pivDateTime: { case PIVariant::pivDateTime: {
setValue(PIDateTime::fromString(v)); setValue(PIDateTime::fromString(v));
} break; } break;
case PIVariant::pivSystemTime: {
setValue(PISystemTime::fromString(v));
} break;
case PIVariant::pivString: { case PIVariant::pivString: {
setValue(v); setValue(v);
} break; } break;
@@ -1262,10 +1265,14 @@ PIDateTime PIVariant::toDateTime() const {
//! \~\details //! \~\details
//! \~english //! \~english
//! In case of SystemTime type returns system time. \n //! In case of SystemTime type returns system time. \n
//! In case of String type returns \a PISystemTime::fromString(). \n
//! In case of DateTime type returns \a PIDateTime::toSystemTime(). \n
//! In case of other types returns \a PISystemTime::fromSeconds() from \a toDouble(). //! In case of other types returns \a PISystemTime::fromSeconds() from \a toDouble().
//! //!
//! \~russian //! \~russian
//! Для типа SystemTime возвращает системное время. \n //! Для типа SystemTime возвращает системное время. \n
//! Для типа String возвращает \a PISystemTime::fromString(). \n
//! Для типа DateTime возвращает \a PIDateTime::toSystemTime(). \n
//! Для остальных типов возвращает \a PISystemTime::fromSeconds() от \a toDouble(). //! Для остальных типов возвращает \a PISystemTime::fromSeconds() от \a toDouble().
//! //!
PISystemTime PIVariant::toSystemTime() const { PISystemTime PIVariant::toSystemTime() const {
@@ -1275,6 +1282,16 @@ PISystemTime PIVariant::toSystemTime() const {
ba >> r; ba >> r;
return r; return r;
} }
if (_type == PIVariant::pivString) {
PIString r;
ba >> r;
return PISystemTime::fromString(r);
}
if (_type == PIVariant::pivDateTime) {
PIDateTime r;
ba >> r;
return r.toSystemTime();
}
if (_type == PIVariant::pivCustom) { if (_type == PIVariant::pivCustom) {
return getAsValue<PISystemTime>(*this); return getAsValue<PISystemTime>(*this);
} }
@@ -1293,8 +1310,8 @@ PISystemTime PIVariant::toSystemTime() const {
//! In case of StringList type returns joined string ("(" + PIStringList::join("; ") + ")"). \n //! In case of StringList type returns joined string ("(" + PIStringList::join("; ") + ")"). \n
//! In case of BitArray or ByteArray types returns number of bits/bytes. \n //! In case of BitArray or ByteArray types returns number of bits/bytes. \n
//! In case of Time, Date or DateTime types returns toString() of this values. \n //! In case of Time, Date or DateTime types returns toString() of this values. \n
//! In case of SystemTime types returns second and nanoseconds of time //! In case of SystemTime types returns \a PISystemTime::toString(). \n
//! In case of NetworkAddress types returns "i.i.i.i:p" //! In case of NetworkAddress types returns "i.i.i.i:p". \n
//! ("(PISystemTime::seconds s, PISystemTime::nanoseconds ns)"). \n //! ("(PISystemTime::seconds s, PISystemTime::nanoseconds ns)"). \n
//! In case of other types returns \b "". //! In case of other types returns \b "".
//! //!
@@ -1304,8 +1321,8 @@ PISystemTime PIVariant::toSystemTime() const {
//! Для типа StringList возвращает объединенную строку ("(" + PIStringList::join("; ") + ")"). \n //! Для типа StringList возвращает объединенную строку ("(" + PIStringList::join("; ") + ")"). \n
//! Для типов BitArray или ByteArray возвращает количество бит/байт. \n //! Для типов BitArray или ByteArray возвращает количество бит/байт. \n
//! Для типов Time, Date или DateTime возвращает toString(). \n //! Для типов Time, Date или DateTime возвращает toString(). \n
//! Для типов SystemTime возвращает секунды и наносекунды в формате "(s, ns)". //! Для типов SystemTime возвращает \a PISystemTime::toString(). \n
//! Для типов NetworkAddress возвращает "i.i.i.i:p" //! Для типов NetworkAddress возвращает "i.i.i.i:p". \n
//! Для остальных типов возвращает \b "". //! Для остальных типов возвращает \b "".
//! //!
PIString PIVariant::toString() const { PIString PIVariant::toString() const {
@@ -1386,6 +1403,11 @@ PIString PIVariant::toString() const {
ba >> r; ba >> r;
return r.toString(); return r.toString();
} }
case PIVariant::pivSystemTime: {
PISystemTime r;
ba >> r;
return r.toString();
}
case PIVariant::pivString: { case PIVariant::pivString: {
PIString r; PIString r;
ba >> r; ba >> r;

View File

@@ -999,6 +999,7 @@ template<> inline const char* PIVariant::value() const {return toString().data()
template<> inline PITime PIVariant::value() const {return toTime();} template<> inline PITime PIVariant::value() const {return toTime();}
template<> inline PIDate PIVariant::value() const {return toDate();} template<> inline PIDate PIVariant::value() const {return toDate();}
template<> inline PIDateTime PIVariant::value() const {return toDateTime();} template<> inline PIDateTime PIVariant::value() const {return toDateTime();}
template<> inline PISystemTime PIVariant::value() const {return toSystemTime();}
template<> inline PIString PIVariant::value() const {return toString();} template<> inline PIString PIVariant::value() const {return toString();}
template<> inline PIStringList PIVariant::value() const {return toStringList();} template<> inline PIStringList PIVariant::value() const {return toStringList();}
template<> inline PIBitArray PIVariant::value() const {return toBitArray();} template<> inline PIBitArray PIVariant::value() const {return toBitArray();}