20#ifndef LIBREPCB_CORE_TOOLBOX_H
21#define LIBREPCB_CORE_TOOLBOX_H
26#include "../exceptions.h"
27#include "../types/angle.h"
28#include "../types/length.h"
29#include "../types/point.h"
78 static inline QSet<T>
toSet(
const QList<T>& list)
noexcept {
79 return QSet<T>(list.begin(), list.end());
95 static inline QVector<T>
toVector(
const QSet<T>& set)
noexcept {
96 return QVector<T>(set.begin(), set.end());
111 template <
typename T>
112 static inline QList<T>
toList(
const QSet<T>& set)
noexcept {
113 return QList<T>(set.begin(), set.end());
116 template <
typename T>
118 QList<T> list = set.values();
119 std::sort(list.begin(), list.end());
123 template <
typename T,
typename Compare>
124 static QList<T>
sortedQSet(
const QSet<T>& set,
const Compare& cmp)
noexcept {
125 QList<T> list = set.values();
126 std::sort(list.begin(), list.end(), cmp);
130 template <
typename T>
131 static T
sorted(
const T& container)
noexcept {
133 std::sort(copy.begin(), copy.end());
147 template <
typename T,
typename Compare>
149 T& container, Compare compare,
150 Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive,
151 bool ignorePunctuation =
false) noexcept {
153 collator.setNumericMode(
true);
154 collator.setCaseSensitivity(caseSensitivity);
155 collator.setIgnorePunctuation(ignorePunctuation);
156 std::sort(container.begin(), container.end(),
157 [&collator, &compare](
const typename T::value_type& lhs,
158 const typename T::value_type& rhs) {
159 return compare(collator, lhs, rhs);
170 template <
typename T>
172 T& container, Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive,
173 bool ignorePunctuation =
false) noexcept {
176 [](
const QCollator& collator,
const typename T::value_type& lhs,
177 const typename T::value_type& rhs) {
return collator(lhs, rhs); },
178 caseSensitivity, ignorePunctuation);
196 return QRectF(-radius, -radius, 2 * radius, 2 * radius);
200 return QRectF(-rx, -ry, 2 * rx, 2 * ry);
204 qreal offset)
noexcept {
205 return rect.adjusted(-offset, -offset, offset, offset);
209 const QPainterPath& path,
const QPen& pen,
const QBrush& brush,
213 const
Angle& angle) noexcept;
215 const
Angle& angle) noexcept;
243 const
Point& end) noexcept;
270 const
Point& l2) noexcept;
285 Point* nearest =
nullptr) noexcept;
337 const QRegularExpression& removeRegex,
338 bool trim = true,
bool toLower = false,
339 bool toUpper = false,
340 const QString& spaceReplacement = " ",
341 int maxLength = -1) noexcept;
364 template <typename T>
366 const QLocale& locale) noexcept {
367 QString s = locale.toString(value,
'f', decimals);
368 for (
int i = 1; (i < decimals) && s.endsWith(locale.zeroDigit()); ++i) {
371 if (qAbs(value) >= 1000) {
372 s.remove(locale.groupSeparator());
383 template <
typename T>
385 using UnsignedT =
typename std::make_unsigned<T>::type;
394 valueAbs = -
static_cast<UnsignedT
>(value);
396 valueAbs =
static_cast<UnsignedT
>(value);
399 QString str = QString::number(valueAbs);
400 if (str.length() > pointPos) {
402 str.insert(str.length() - pointPos,
'.');
404 for (qint32 i = pointPos - str.length(); i != 0; i--) str.insert(0,
'0');
408 while (str.endsWith(
'0') && !str.endsWith(
".0")) str.chop(1);
410 if (value < 0) str.insert(0,
'-');
422 template <
typename T>
424 using UnsignedT =
typename std::make_unsigned<T>::type;
426 const T min = std::numeric_limits<T>::min();
427 const T max = std::numeric_limits<T>::max();
428 const UnsignedT max_u = std::numeric_limits<UnsignedT>::max();
441 State state = State::START;
442 UnsignedT valueAbs = 0;
444 qint32 expOffset = pointPos;
446 const quint32 maxExp = std::numeric_limits<quint32>::max();
448 bool expSign =
false;
450 for (QChar c : str) {
451 if (state == State::INVALID) {
463 state = State::AFTER_SIGN;
464 }
else if (c ==
'+') {
465 state = State::AFTER_SIGN;
466 }
else if (c ==
'.') {
467 state = State::LONELY_DOT;
468 }
else if (c.isDigit()) {
469 valueAbs =
static_cast<UnsignedT
>(c.digitValue());
470 state = State::INT_PART;
472 state = State::INVALID;
476 case State::AFTER_SIGN:
478 state = State::LONELY_DOT;
479 }
else if (c.isDigit()) {
480 valueAbs =
static_cast<UnsignedT
>(c.digitValue());
481 state = State::INT_PART;
483 state = State::INVALID;
487 case State::LONELY_DOT:
489 valueAbs =
static_cast<UnsignedT
>(c.digitValue());
491 state = State::FRAC_PART;
493 state = State::INVALID;
497 case State::INT_PART:
499 state = State::FRAC_PART;
500 }
else if (c ==
'e' || c ==
'E') {
502 }
else if (c.isDigit()) {
503 UnsignedT digit =
static_cast<UnsignedT
>(c.digitValue());
504 if (valueAbs > (max_u / 10)) {
506 state = State::INVALID;
510 if (valueAbs > (max_u - digit)) {
512 state = State::INVALID;
517 state = State::INVALID;
521 case State::FRAC_PART:
522 if (c ==
'e' || c ==
'E') {
524 }
else if (c.isDigit()) {
525 UnsignedT digit =
static_cast<UnsignedT
>(c.digitValue());
526 if (valueAbs > (max_u / 10)) {
528 state = State::INVALID;
532 if (valueAbs > (max_u - digit)) {
534 state = State::INVALID;
540 state = State::INVALID;
547 state = State::EXP_AFTER_SIGN;
548 }
else if (c ==
'+') {
549 state = State::EXP_AFTER_SIGN;
550 }
else if (c.isDigit()) {
551 exp =
static_cast<quint32
>(c.digitValue());
552 state = State::EXP_DIGITS;
554 state = State::INVALID;
558 case State::EXP_AFTER_SIGN:
560 exp =
static_cast<quint32
>(c.digitValue());
561 state = State::EXP_DIGITS;
563 state = State::INVALID;
567 case State::EXP_DIGITS:
569 quint32 digit =
static_cast<quint32
>(c.digitValue());
570 if (exp > (maxExp / 10)) {
572 state = State::INVALID;
576 if (exp > (maxExp - digit)) {
578 state = State::INVALID;
583 state = State::INVALID;
592 case State::AFTER_SIGN:
593 case State::LONELY_DOT:
595 case State::EXP_AFTER_SIGN:
599 case State::INT_PART:
600 case State::FRAC_PART:
601 case State::EXP_DIGITS:
606 quint32 expOffsetAbs;
608 expOffsetAbs = -
static_cast<quint32
>(expOffset);
610 expOffsetAbs =
static_cast<quint32
>(expOffset);
613 if (expSign == (expOffset < 0)) {
614 if (exp > (maxExp - expOffsetAbs)) {
621 if (exp < expOffsetAbs) {
635 for (quint32 i = 0; i < exp; i++) {
636 if ((valueAbs % 10) != 0) {
644 for (quint32 i = 0; i < exp; i++) {
645 if (valueAbs > (max_u / 10)) {
655 if (valueAbs >
static_cast<UnsignedT
>(min)) {
658 result =
static_cast<T
>(-valueAbs);
661 if (valueAbs >
static_cast<UnsignedT
>(max)) {
664 result =
static_cast<T
>(valueAbs);
674 tr(
"Invalid fixed point number string: \"%1\"").arg(str));
684 const QString& input,
685 const QVector<std::tuple<int, int, QStringList>>& replacements)
noexcept;
The Angle class is used to represent an angle (for example 12.75 degrees)
Definition angle.h:76
The Length class is used to represent a length (for example 12.75 millimeters)
Definition length.h:82
The Point class is used to represent a point/coordinate/vector, for example (1.2mm; 5....
Definition point.h:78
The RuntimeError class.
Definition exceptions.h:218
Definition occmodel.cpp:76
type_safe::constrained_type< Length, UnsignedLengthConstraint, UnsignedLengthVerifier > UnsignedLength
Definition length.h:694