sfizz/sources/Helpers.h

182 lines
4.6 KiB
C
Raw Normal View History

2019-07-29 02:13:03 +02:00
#pragma once
2019-08-24 15:32:06 +02:00
#include <random>
#include <signal.h>
#include <string_view>
2019-07-29 02:13:03 +02:00
2019-08-25 00:46:31 +02:00
inline void trimInPlace(std::string_view &s)
2019-07-29 02:13:03 +02:00
{
const auto leftPosition = s.find_first_not_of(" \r\t\n\f\v");
2019-08-25 00:46:31 +02:00
if (leftPosition != s.npos)
{
2019-07-29 02:13:03 +02:00
s.remove_prefix(leftPosition);
const auto rightPosition = s.find_last_not_of(" \r\t\n\f\v");
s.remove_suffix(s.size() - rightPosition - 1);
2019-08-25 00:46:31 +02:00
}
else
{
2019-07-29 02:13:03 +02:00
s.remove_suffix(s.size());
}
2019-07-29 02:13:03 +02:00
}
inline std::string_view trim(std::string_view s)
{
const auto leftPosition = s.find_first_not_of(" \r\t\n\f\v");
2019-08-25 00:46:31 +02:00
if (leftPosition != s.npos)
{
2019-07-29 02:13:03 +02:00
s.remove_prefix(leftPosition);
const auto rightPosition = s.find_last_not_of(" \r\t\n\f\v");
s.remove_suffix(s.size() - rightPosition - 1);
2019-08-25 00:46:31 +02:00
}
else
{
2019-07-29 02:13:03 +02:00
s.remove_suffix(s.size());
}
return s;
}
inline constexpr unsigned int Fnv1aBasis = 0x811C9DC5;
inline constexpr unsigned int Fnv1aPrime = 0x01000193;
2019-08-25 00:46:31 +02:00
inline constexpr unsigned int hash(const char *s, unsigned int h = Fnv1aBasis)
2019-07-29 02:13:03 +02:00
{
return !*s ? h : hash(s + 1, static_cast<unsigned int>((h ^ *s) * static_cast<unsigned long long>(Fnv1aPrime)));
}
inline unsigned int hash(std::string_view s, unsigned int h = Fnv1aBasis)
{
if (s.length() > 0)
return hash(std::string_view(s.data() + 1, s.length() - 1), static_cast<unsigned int>((h ^ s.front()) * static_cast<unsigned long long>(Fnv1aPrime)));
return h;
}
template <class T>
2019-08-22 01:54:43 +02:00
inline constexpr T min(T op1, T op2) { return std::min(op1, op2); }
template <class T>
2019-08-22 01:54:43 +02:00
inline constexpr T min(T op1, T op2, T op3) { return std::min(op1, std::min(op2, op3)); }
template <class T>
2019-08-22 01:54:43 +02:00
inline constexpr T min(T op1, T op2, T op3, T op4) { return std::min(op1, std::min(op2, std::min(op3, op4))); }
2019-07-29 02:13:03 +02:00
#ifndef NDEBUG
#if __linux__ || __unix__
// These trap into the signal library rather than your own sourcecode
// #define ASSERTFALSE { ::kill(0, SIGTRAP); }
// #define ASSERTFALSE { raise(SIGTRAP); }
#define ASSERTFALSE \
{ \
__asm__("int3"); \
}
2019-07-29 02:13:03 +02:00
#elif _WIN32 || _WIN64
#pragma intrinsic(__debugbreak)
#define ASSERTFALSE \
{ \
__debugbreak(); \
}
2019-07-29 02:13:03 +02:00
#else
#define ASSERTFALSE \
{ \
__asm int 3; \
}
2019-07-29 02:13:03 +02:00
#endif
#define ASSERT(expression) \
if (!(expression)) \
ASSERTFALSE
2019-07-29 02:13:03 +02:00
#include <iostream>
#define DBG(ostream) std::cerr << ostream << '\n'
#else
#define ASSERTFALSE
2019-07-29 02:13:03 +02:00
#define ASSERT(expression)
#define DBG(ostream)
2019-08-24 15:32:06 +02:00
#endif
template <class Type>
2019-08-24 15:32:06 +02:00
inline constexpr Type db2pow(Type in)
{
return std::pow(static_cast<Type>(10.0), in * static_cast<Type>(0.1));
}
template <class Type>
2019-08-24 15:32:06 +02:00
inline constexpr Type pow2db(Type in)
{
return static_cast<Type>(10.0) * std::log10(in);
}
template <class Type>
2019-08-24 15:32:06 +02:00
inline constexpr Type db2mag(Type in)
{
return std::pow(static_cast<Type>(10.0), in * static_cast<Type>(0.05));
}
template <class Type>
2019-08-24 15:32:06 +02:00
inline constexpr Type mag2db(Type in)
{
return static_cast<Type>(20.0) * std::log10(in);
}
2019-08-25 00:46:31 +02:00
namespace Random
{
static inline std::random_device randomDevice;
2019-08-25 00:46:31 +02:00
static inline std::mt19937 randomGenerator{randomDevice()};
} // namespace Random
2019-08-24 15:32:06 +02:00
inline float midiNoteFrequency(const int noteNumber)
2019-08-24 15:32:06 +02:00
{
return 440.0f * std::pow(2.0f, (noteNumber - 69) / 12.0f);
}
template <class Type>
2019-08-25 00:46:31 +02:00
constexpr Type pi{3.141592653589793238462643383279502884};
template <class Type>
2019-08-25 00:46:31 +02:00
constexpr Type twoPi{2 * pi<Type>};
template <class Type>
2019-08-25 00:46:31 +02:00
constexpr Type piTwo{pi<Type> / 2};
#include <atomic>
template <class Owner>
2019-08-25 00:46:31 +02:00
class LeakDetector
{
public:
LeakDetector()
{
objectCounter.count++;
}
2019-08-25 00:46:31 +02:00
LeakDetector(const LeakDetector &)
{
objectCounter.count++;
}
~LeakDetector()
{
objectCounter.count--;
2019-08-25 00:46:31 +02:00
if (objectCounter.count.load() < 0)
{
DBG("Deleted a dangling pointer for class " << Owner::getClassName());
// Deleted a dangling pointer!
2019-08-25 00:46:31 +02:00
ASSERTFALSE;
}
}
private:
2019-08-25 00:46:31 +02:00
struct ObjectCounter
{
ObjectCounter() = default;
~ObjectCounter()
{
2019-08-25 00:46:31 +02:00
if (auto residualCount = count.load() > 0)
{
DBG("Leaked " << residualCount << " instance(s) of class " << Owner::getClassName());
// Leaked ojects
2019-08-25 00:46:31 +02:00
ASSERTFALSE;
}
};
2019-08-25 00:46:31 +02:00
std::atomic<int> count{0};
};
static inline ObjectCounter objectCounter;
};
#ifndef NDEBUG
2019-08-25 00:46:31 +02:00
#define LEAK_DETECTOR(Class) \
friend class LeakDetector<Class>; \
static const char *getClassName() { return #Class; } \
LeakDetector<Class> leakDetector;
#else
#define LEAK_DETECTOR(Class)
#endif