Files
qt5-legatus-legacy/Lts/Common/LtsUtils/LtsUtilsCore/pgarray.cpp
T
2026-08-13 18:33:10 +02:00

175 lines
4.6 KiB
C++
Executable File

/**
* Helper class for a vector of integer (stored as integer[] in the postgres database
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-05-03
*/
#include "pgarray.h"
#include <QVector>
#include <QDebug>
#include <functional>
#include <LtsUtilsCore/ltsutilscore_export.h>
namespace LtsUtils
{
template<typename T>
static inline QString convertToPgString(const std::vector<T> &data)
{
if (data.size() == 0)
return QLatin1String("{}");
QString ret(QLatin1Char('{'));
for (T i : data)
ret += QString::number(i) + QLatin1Char(',');
ret.chop(1);
ret += QLatin1Char('}');
return ret;
}
template<>
LTSUTILSCORE_EXPORT QString IntArray::toPgString() const
{
return convertToPgString(m_data);
}
template<>
LTSUTILSCORE_EXPORT QString BigintArray::toPgString() const
{
return convertToPgString(m_data);
}
template<typename T>
static inline T convertFromPgString(const QString &str, const std::function<typename T::Type(const QStringRef &val, bool *bOk)> &convertFunc)
{
typename T::ContainerType result;
int idxStart = str.indexOf(QLatin1Char('{'));
int idxEnd = str.lastIndexOf(QLatin1Char('}'));
if (idxEnd < idxStart)
return T(result);
if (idxStart < 0 && idxEnd < 0)
{
// no {} around - fake midRef call
idxStart = -1;
idxEnd = str.length() + 1;
}
const QStringRef strRef = str.midRef(idxStart + 1, idxEnd - idxStart - 1);
const QVector<QStringRef> vec = strRef.split(QLatin1Char(','), QString::SkipEmptyParts);
result.reserve(vec.size());
for (const QStringRef &s : vec)
{
bool ok = false;
const typename T::Type i = convertFunc(s, &ok);
if (ok)
result.push_back(i);
}
return T(result);
}
template<>
LTSUTILSCORE_EXPORT IntArray IntArray::fromPgString(const QString &str)
{
return convertFromPgString<IntArray>(str,
[](const QStringRef & val, bool * bOk) { return val.toInt(bOk);});
}
template<>
LTSUTILSCORE_EXPORT BigintArray BigintArray::fromPgString(const QString &str)
{
return convertFromPgString<BigintArray>(str,
[](const QStringRef & val, bool * bOk) { return val.toLongLong(bOk);});
}
//
// 2D
//
template<typename T>
static inline QString convertToPgString(const std::map<T, T> &data)
{
if (data.size() == 0)
return QLatin1String("{}");
QString ret(QLatin1Char('{'));
for (const auto &it : data)
{
ret += QLatin1Char('{') + QString::number(it.first) +
QLatin1Char(',') + QString::number(it.second) + QLatin1String("},");
}
ret.chop(1);
ret += QLatin1Char('}');
return ret;
}
template<>
LTSUTILSCORE_EXPORT QString IntArray2D::toPgString() const
{
return convertToPgString<IntArray2D::Type>(m_data);
}
template<>
LTSUTILSCORE_EXPORT QString BigintArray2D::toPgString() const
{
return convertToPgString<BigintArray2D::Type>(m_data);
}
template<typename T>
static inline T convertFromPgString2D(const QString &str, const std::function<typename T::Type(const QStringRef &val)> &convertFunc)
{
typename T::ContainerType ret;
int idxStart = str.indexOf(QLatin1Char('{'));
int idxEnd = str.lastIndexOf(QLatin1Char('}'));
if (idxEnd < idxStart)
return T(ret);
if (idxStart < 0 && idxEnd < 0)
{
// no {} around - fake midRef call
idxStart = -1;
idxEnd = str.length() + 1;
}
// remove first { and last } --> { 1, 2 }, { 4, 3 }, { 10, 1 }
const QStringRef strRef = str.midRef(idxStart + 1, idxEnd - idxStart - 1);
idxStart = strRef.indexOf(QLatin1Char('{'));
while (idxStart >= 0)
{
idxEnd = strRef.indexOf(QLatin1Char('}'), idxStart);
if (idxEnd < 0)
break;
// '{ 1, 2 }' -> ' 1, 2 '
const QStringRef keyValueStr = strRef.mid(idxStart + 1, idxEnd - idxStart - 1);
const QVector<QStringRef> keyValuePair = keyValueStr.split(QLatin1Char(','), QString::SkipEmptyParts);
if (keyValuePair.size() != 2)
break;
const typename T::Type key = convertFunc(keyValuePair.at(0).trimmed());
const typename T::Type value = convertFunc(keyValuePair.at(1).trimmed());
ret.insert(std::make_pair(key, value));
// search next
idxStart = strRef.indexOf(QLatin1Char('{'), idxEnd + 1);
}
return T(ret);
}
template<>
LTSUTILSCORE_EXPORT IntArray2D IntArray2D::fromPgString(const QString &str)
{
return convertFromPgString2D<IntArray2D>(str,
[](const QStringRef & val) { return val.toInt();});
}
template<>
LTSUTILSCORE_EXPORT BigintArray2D BigintArray2D::fromPgString(const QString &str)
{
return convertFromPgString2D<BigintArray2D>(str,
[](const QStringRef & val) { return val.toLongLong();});
}
} // namespace LtsUtils