--- a/src/basics.h Sat Mar 24 11:05:40 2018 +0200 +++ b/src/basics.h Sat Mar 24 11:57:24 2018 +0200 @@ -17,68 +17,37 @@ */ #pragma once -#include <QString> -#include <QObject> -#include <QStringList> -#include <QMetaType> -#include <QSet> -#include <QVector3D> -#include <QVector> #include <QFile> #include <QMatrix4x4> -#include <functional> -#include <type_traits> -#include <math.h> -#include "macros.h" -#include "transform.h" +#include <QMetaType> +#include <QObject> +#include <QSet> +#include <QString> +#include <QStringList> +#include <QVector> +#include <QVector3D> +#include "generics/functions.h" -#if (QT_VERSION < QT_VERSION_CHECK(5, 7, 0)) -template <typename... Args> -struct QNonConstOverload -{ - template <typename R, typename T> - Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr) - { return ptr; } - template <typename R, typename T> - static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr) - { return ptr; } -}; -template <typename... Args> -struct QConstOverload -{ - template <typename R, typename T> - Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...) const) const Q_DECL_NOTHROW -> decltype(ptr) - { return ptr; } - template <typename R, typename T> - static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...) const) Q_DECL_NOTHROW -> decltype(ptr) - { return ptr; } -}; -template <typename... Args> -struct QOverload : QConstOverload<Args...>, QNonConstOverload<Args...> -{ - using QConstOverload<Args...>::of; - using QConstOverload<Args...>::operator(); - using QNonConstOverload<Args...>::of; - using QNonConstOverload<Args...>::operator(); - template <typename R> - Q_DECL_CONSTEXPR auto operator()(R (*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr) - { return ptr; } - template <typename R> - static Q_DECL_CONSTEXPR auto of(R (*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr) - { return ptr; } -}; -template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QOverload<Args...> qOverload = {}; -template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QConstOverload<Args...> qConstOverload = {}; -template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QNonConstOverload<Args...> qNonConstOverload = {}; +#ifndef __GNUC__ +# define __attribute__(X) #endif -class Matrix; -struct Vertex; +#define DEFINE_CLASS(SELF, SUPER) \ +public: \ + using Self = SELF; \ + using Super = SUPER; + +// TODO: get rid of this +#ifdef WIN32 +# define DIRSLASH "\\" +# define DIRSLASH_CHAR '\\' +#else // WIN32 +# define DIRSLASH "/" +# define DIRSLASH_CHAR '/' +#endif // WIN32 + using GLRotationMatrix = QMatrix4x4; -template<typename T, typename R> -using Pair = std::pair<T, R>; - enum Axis { X, @@ -93,346 +62,41 @@ Clockwise, }; -Winding operator^(Winding one, Winding other); -Winding& operator^=(Winding& one, Winding other); +/* + * Special operator definition that implements the XOR operator for windings. + * However, if either winding is NoWinding, then this function returns NoWinding. + */ +inline Winding operator^(Winding one, Winding other) +{ + if (one == NoWinding or other == NoWinding) + return NoWinding; + else + return static_cast<Winding>(static_cast<int>(one) ^ static_cast<int>(other)); +} +inline Winding& operator^=(Winding& one, Winding other) +{ + one = one ^ other; + return one; +} + +static const double pi = 3.14159265358979323846; + +/* + * Returns the norm of a vector. + */ static inline qreal abs(const QVector3D &vector) { return vector.length(); } -static const double pi = 3.14159265358979323846; - - -// ============================================================================= -// Plural expression -template<typename T> -static inline const char* plural (T n) -{ - return (n != 1) ? "s" : ""; -} - -template<typename T> -bool isZero (T a) -{ - return qFuzzyCompare (a + 1.0, 1.0); -} - -template<typename T> -bool isInteger (T a) -{ - return (qAbs (a - floor(a)) < 0.00001) or (qAbs (a - ceil(a)) < 0.00001); -} - -// -// Returns true if first arg is equal to any of the other args -// -template<typename T, typename Arg, typename... Args> -bool isOneOf (T const& a, Arg const& arg, Args const&... args) -{ - if (a == arg) - return true; - - return isOneOf (a, args...); -} - -template<typename T> -bool isOneOf (T const&) -{ - return false; -} - -inline void toggle (bool& a) -{ - a = not a; -} - -// -// Iterates an enum -// -template<typename Enum> -struct EnumIterShell -{ - struct Iterator - { - Iterator(typename std::underlying_type<Enum>::type i) : - i(i) {} - - Iterator& operator++() { ++i; return *this; } - bool operator==(Iterator other) { return i == other.i; } - bool operator!=(Iterator other) { return i != other.i; } - Enum operator*() const { return Enum(i); } - - typename std::underlying_type<Enum>::type i; - }; - - Iterator begin() - { - return Iterator(EnumLimits<Enum>::First); - }; - - Iterator end() - { - return Iterator(EnumLimits<Enum>::Last + 1); - } -}; - -template<typename Enum> -EnumIterShell<Enum> iterateEnum() -{ - return EnumIterShell<Enum>(); -} - -// Is a value inside an enum? -template<typename Enum> -bool valueInEnum(Enum enumerator) -{ - typename std::underlying_type<Enum>::type index = static_cast<typename std::underlying_type<Enum>::type>(enumerator); - return index >= EnumLimits<Enum>::First and index <= EnumLimits<Enum>::Last; -} - -double getRadialPoint(int segment, int divisions, double(*func)(double)); -QVector<QLineF> makeCircle(int segments, int divisions, double radius); -qreal distanceFromPointToRectangle(const QPointF& point, const QRectF& rectangle); - -/* - * Implements a ring adapter over T. This class corrects indices given to the element-operator so that they're within bounds. - * The maximum amount can be specified manually. - * - * Example: - * - * int A[] = {10,20,30,40}; - * ring(A)[0] == A[0 % 4] == A[0] - * ring(A)[5] == A[5 % 4] == A[1] - * ring(A)[-1] == ring(A)[-1 + 4] == A[3] - */ -template<typename T> -class RingAdapter -{ -private: - // The private section must come first because _collection is used in decltype() below. - T& _collection; - const int _count; - -public: - RingAdapter(T& collection, int count) : - _collection {collection}, - _count {count} {} - - template<typename IndexType> - decltype(_collection[IndexType()]) operator[](IndexType index) - { - if (_count == 0) - { - // Argh! ...let the collection deal with this case. - return _collection[0]; - } - else - { - index %= _count; - - // Fix negative modulus... - if (index < 0) - index += _count; - - return _collection[index]; - } - } - - int size() const - { - return _count; - } -}; - -/* - * Casts a reference to an enum into a reference to its underlying integer type. - */ -template<typename T> -typename std::underlying_type<T>::type& enum_cast(T& enu) -{ - return *reinterpret_cast<typename std::underlying_type<T>::type*>(&enu); -} - -/* - * Convenience function for RingAdapter so that the template parameter does not have to be provided. The ring amount is assumed - * to be the amount of elements in the collection. - */ -template<typename T> -RingAdapter<T> ring(T& collection) -{ - return RingAdapter<T> {collection, countof(collection)}; -} +using ApplyToMatrixFunction = std::function<void(int, double&)>; +using ApplyToMatrixConstFunction = std::function<void(int, double)>; -/* - * Version of ring() that allows manual specification of the count. - */ -template<typename T> -RingAdapter<T> ring(T& collection, int count) -{ - return RingAdapter<T> {collection, count}; -} - -struct Library -{ - QString path; - enum - { - ReadOnlyStorage, // for official files, etc - UnofficialFiles, // put downloaded files here - WorkingDirectory, // for editable documents - } role = ReadOnlyStorage; - - bool operator==(const Library& other) const - { - return (this->path == other.path) and (this->role == other.role); - } -}; - -Q_DECLARE_METATYPE(Library) -using Libraries = QVector<Library>; - -QDataStream& operator<<(QDataStream& out, const Library& library); -QDataStream& operator>>(QDataStream& in, Library& library); - -// -// Get the amount of elements in something. -// -template<typename T, size_t N> -int countof(T(&)[N]) -{ - return N; -} - -static inline int countof(const QString& string) -{ - return string.length(); -} - -template<typename T> -int countof(const QVector<T>& vector) -{ - return vector.size(); -} - -template<typename T> -int countof(const QList<T>& vector) -{ - return vector.size(); -} - -template<typename T> -int countof(const QSet<T>& set) -{ - return set.size(); -} - -template<typename T> -int countof(const std::initializer_list<T>& vector) -{ - return vector.size(); -} - -template<typename T> -int countof(const RingAdapter<T>& ring) -{ - return ring.size(); -} - -/* - * Extracts the sign of x. - */ -template<typename T> -T sign(T x) -{ - if (isZero(x)) - return {}; - else - return x / qAbs(x); -} - -template<> -inline int sign(int x) -{ - if (x == 0) - return 0; - else - return x / qAbs(x); -} - -/* - * Returns the maximum of a single parameter (the parameter itself). - */ -template <typename T> -T max(T a) -{ - return a; -} - -/* - * Returns the maximum of two parameters. - */ -template <typename T> -T max(T a, T b) -{ - return a > b ? a : b; -} - -/* - * Returns the maximum of n parameters. - */ -template <typename T, typename... Rest> -T max(T a, Rest&&... rest) -{ - return max(a, max(rest...)); -} - -/* - * Returns the minimum of a single parameter (the parameter itself). - */ -template <typename T> -T min(T a) -{ - return a; -} - -/* - * Returns the minimum of two parameters. - */ -template <typename T> -T min(T a, T b) -{ - return a < b ? a : b; -} - -/* - * Returns the minimum of n parameters. - */ -template <typename T, typename... Rest> -T min(T a, Rest&&... rest) -{ - return min(a, min(rest...)); -} - -/* - * Assigns the value of a single flag in a flagset - */ -template<int Flag, typename T> -void assignFlag(QFlags<T>& flagset, bool value) -{ - if (value) - flagset |= static_cast<T>(Flag); - else - flagset &= ~static_cast<T>(Flag); -} - -/* - * Returns a singleton of type T, useful for providing a valid but unused - * pointer. - */ -template<typename T> -inline T& sink() -{ - static T result; - return result; -} +void applyToMatrix(class Matrix& a, ApplyToMatrixFunction func); +void applyToMatrix(const class Matrix& a, ApplyToMatrixConstFunction func); +QString formatFileSize(qint64 size); +int gcd(int a, int b); +QString joinStrings(const QList<class StringFormatArg>& values, QString delimeter = " "); +void roundToDecimals(double& value, int decimals); +void simplify(int& numerator, int& denominator);