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" 31 #include <type_traits> 77 static QSet<T>
toSet(
const QList<T>& list) noexcept {
78 #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) 79 return QSet<T>(list.begin(), list.end());
86 static QList<T>
sortedQSet(
const QSet<T>&
set) noexcept {
87 QList<T> list =
set.values();
88 std::sort(list.begin(), list.end());
93 static T
sorted(
const T& container) noexcept {
95 std::sort(copy.begin(), copy.end());
109 template <
typename T,
typename Compare>
111 T& container, Compare compare,
112 Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive,
113 bool ignorePunctuation =
false) noexcept {
115 collator.setNumericMode(
true);
116 collator.setCaseSensitivity(caseSensitivity);
117 collator.setIgnorePunctuation(ignorePunctuation);
118 std::sort(container.begin(), container.end(),
119 [&collator, &compare](
const typename T::value_type& lhs,
120 const typename T::value_type& rhs) {
121 return compare(collator, lhs, rhs);
132 template <
typename T>
134 T& container, Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive,
135 bool ignorePunctuation =
false) noexcept {
138 [](
const QCollator& collator,
const typename T::value_type& lhs,
139 const typename T::value_type& rhs) {
return collator(lhs, rhs); },
140 caseSensitivity, ignorePunctuation);
158 return QRectF(-radius, -radius, 2 * radius, 2 * radius);
162 return QRectF(-rx, -ry, 2 * rx, 2 * ry);
166 qreal offset) noexcept {
167 return rect.adjusted(-offset, -offset, offset, offset);
171 const QPainterPath& path,
const QPen& pen,
const QBrush& brush,
175 const Angle& a) noexcept;
177 const Angle& a) noexcept;
216 const Point& l2) noexcept;
231 Point* nearest =
nullptr) noexcept;
283 const QRegularExpression& removeRegex,
284 bool trim =
true,
bool toLower =
false,
285 bool toUpper =
false,
286 const QString& spaceReplacement =
" ",
287 int maxLength = -1) noexcept;
310 template <
typename T>
312 const QLocale& locale) noexcept {
313 QString s = locale.toString(value,
'f', decimals);
314 for (
int i = 1; (i < decimals) && s.endsWith(locale.zeroDigit()); ++i) {
317 if (qAbs(value) >= 1000) {
318 s.remove(locale.groupSeparator());
329 template <
typename T>
331 using UnsignedT =
typename std::make_unsigned<T>::type;
340 valueAbs = -
static_cast<UnsignedT
>(value);
342 valueAbs =
static_cast<UnsignedT
>(value);
345 QString str = QString::number(valueAbs);
346 if (str.length() > pointPos) {
348 str.insert(str.length() - pointPos,
'.');
350 for (qint32 i = pointPos - str.length(); i != 0; i--) str.insert(0,
'0');
354 while (str.endsWith(
'0') && !str.endsWith(
".0")) str.chop(1);
356 if (value < 0) str.insert(0,
'-');
368 template <
typename T>
370 using UnsignedT =
typename std::make_unsigned<T>::type;
372 const T min = std::numeric_limits<T>::min();
373 const T max = std::numeric_limits<T>::max();
374 const UnsignedT max_u = std::numeric_limits<UnsignedT>::max();
387 State state = State::START;
388 UnsignedT valueAbs = 0;
390 qint32 expOffset = pointPos;
392 const quint32 maxExp = std::numeric_limits<quint32>::max();
394 bool expSign =
false;
396 for (QChar c : str) {
397 if (state == State::INVALID) {
409 state = State::AFTER_SIGN;
410 }
else if (c ==
'+') {
411 state = State::AFTER_SIGN;
412 }
else if (c ==
'.') {
413 state = State::LONELY_DOT;
414 }
else if (c.isDigit()) {
415 valueAbs =
static_cast<UnsignedT
>(c.digitValue());
416 state = State::INT_PART;
418 state = State::INVALID;
422 case State::AFTER_SIGN:
424 state = State::LONELY_DOT;
425 }
else if (c.isDigit()) {
426 valueAbs =
static_cast<UnsignedT
>(c.digitValue());
427 state = State::INT_PART;
429 state = State::INVALID;
433 case State::LONELY_DOT:
435 valueAbs =
static_cast<UnsignedT
>(c.digitValue());
437 state = State::FRAC_PART;
439 state = State::INVALID;
443 case State::INT_PART:
445 state = State::FRAC_PART;
446 }
else if (c ==
'e' || c ==
'E') {
448 }
else if (c.isDigit()) {
449 UnsignedT digit =
static_cast<UnsignedT
>(c.digitValue());
450 if (valueAbs > (max_u / 10)) {
452 state = State::INVALID;
456 if (valueAbs > (max_u - digit)) {
458 state = State::INVALID;
463 state = State::INVALID;
467 case State::FRAC_PART:
468 if (c ==
'e' || c ==
'E') {
470 }
else if (c.isDigit()) {
471 UnsignedT digit =
static_cast<UnsignedT
>(c.digitValue());
472 if (valueAbs > (max_u / 10)) {
474 state = State::INVALID;
478 if (valueAbs > (max_u - digit)) {
480 state = State::INVALID;
486 state = State::INVALID;
493 state = State::EXP_AFTER_SIGN;
494 }
else if (c ==
'+') {
495 state = State::EXP_AFTER_SIGN;
496 }
else if (c.isDigit()) {
497 exp =
static_cast<quint32
>(c.digitValue());
498 state = State::EXP_DIGITS;
500 state = State::INVALID;
504 case State::EXP_AFTER_SIGN:
506 exp =
static_cast<quint32
>(c.digitValue());
507 state = State::EXP_DIGITS;
509 state = State::INVALID;
513 case State::EXP_DIGITS:
515 quint32 digit =
static_cast<quint32
>(c.digitValue());
516 if (exp > (maxExp / 10)) {
518 state = State::INVALID;
522 if (exp > (maxExp - digit)) {
524 state = State::INVALID;
529 state = State::INVALID;
538 case State::AFTER_SIGN:
539 case State::LONELY_DOT:
541 case State::EXP_AFTER_SIGN:
545 case State::INT_PART:
546 case State::FRAC_PART:
547 case State::EXP_DIGITS:
552 quint32 expOffsetAbs;
554 expOffsetAbs = -
static_cast<quint32
>(expOffset);
556 expOffsetAbs =
static_cast<quint32
>(expOffset);
559 if (expSign == (expOffset < 0)) {
560 if (exp > (maxExp - expOffsetAbs)) {
567 if (exp < expOffsetAbs) {
581 for (quint32 i = 0; i < exp; i++) {
582 if ((valueAbs % 10) != 0) {
590 for (quint32 i = 0; i < exp; i++) {
591 if (valueAbs > (max_u / 10)) {
601 if (valueAbs > static_cast<UnsignedT>(min)) {
604 result =
static_cast<T
>(-valueAbs);
607 if (valueAbs > static_cast<UnsignedT>(max)) {
610 result =
static_cast<T
>(valueAbs);
620 tr(
"Invalid fixed point number string: \"%1\"").arg(str));
630 const QString& input,
631 const QVector<std::tuple<int, int, QStringList>>& replacements) noexcept;
Definition: occmodel.cpp:76
The Angle class is used to represent an angle (for example 12.75 degrees)
Definition: angle.h:76
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:216
The Length class is used to represent a length (for example 12.75 millimeters)
Definition: length.h:82
type_safe::constrained_type< Length, UnsignedLengthConstraint, UnsignedLengthVerifier > UnsignedLength
Definition: length.h:670