Files
TinyORM/include/orm/utils/container.hpp
T
2023-03-15 17:56:01 +01:00

107 lines
3.0 KiB
C++

#pragma once
#ifndef ORM_UTILS_CONTAINER_HPP
#define ORM_UTILS_CONTAINER_HPP
#include "orm/macros/systemheader.hpp"
TINY_SYSTEM_HEADER
#include "orm/constants.hpp"
#include "orm/ormconcepts.hpp" // IWYU pragma: keep
TINYORM_BEGIN_COMMON_NAMESPACE
namespace Orm::Utils
{
/*! Containers related library class. */
class Container
{
Q_DISABLE_COPY(Container)
public:
/*! Deleted default constructor, this is a pure library class. */
Container() = delete;
/*! Deleted destructor. */
~Container() = delete;
/*! Convert a string container into a (comma) delimited string. */
template<JoinContainer T, DelimiterConcept D = const QString &>
static QString
join(const T &container, D &&delimiter = Constants::COMMA);
/*! Count all string sizes in the given container and optionally add value to
every string. */
template<QStringContainer T, typename SizeType = typename T::size_type>
static SizeType
countStringSizes(const T &container, typename T::size_type addToElement = 0);
private:
/*! Get the delimiter size (returns 1 for the QChar). */
template<typename SizeType = QString::size_type, DelimiterConcept D>
static SizeType delimiterSize(D &&delimiter);
};
template<JoinContainer T, DelimiterConcept D>
QString Container::join(const T &container, D &&delimiter)
{
// Nothing to join
if (container.empty())
return {};
QString joined;
// +4 serves as a reserve (for the reserve() 😂)
const auto delimiterSize_ = delimiterSize<typename T::size_type>(delimiter);
joined.reserve(static_cast<QString::size_type>(
countStringSizes(container, delimiterSize_ + 4)));
auto end = container.cend();
--end;
auto it = container.cbegin();
for (; it != end; ++it)
// These append-s() are better for performance
joined.append(*it)
// No need for the if statement if it's empty or null
.append(std::forward<D>(delimiter));
Q_ASSERT(it == end);
joined.append(*it);
return joined;
}
template<QStringContainer T, typename SizeType>
SizeType
Container::countStringSizes(const T &container,
const typename T::size_type addToElement)
{
// Nothing to do
if (container.empty())
return 0;
SizeType size = 0;
for (const auto &string : container)
size += static_cast<SizeType>(string.size()) + addToElement;
return size;
}
/* private */
template<typename SizeType, DelimiterConcept D>
SizeType Container::delimiterSize(D &&delimiter)
{
if constexpr (std::is_constructible_v<QChar, D>)
return 1;
else
return static_cast<SizeType>(QString(delimiter).size());
}
} // namespace Orm::Utils
TINYORM_END_COMMON_NAMESPACE
#endif // ORM_UTILS_CONTAINER_HPP