Initial commit.
This commit is contained in:
1
src/ConstString.cpp
Normal file
1
src/ConstString.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "ConstString.hpp"
|
||||
33
src/ConstString.hpp
Normal file
33
src/ConstString.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef ARBUTILS_CONSTSTRING_HPP
|
||||
#define ARBUTILS_CONSTSTRING_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
namespace Arbutils {
|
||||
class ConstString {
|
||||
private:
|
||||
const char* _str;
|
||||
size_t _length;
|
||||
uint32_t _hash;
|
||||
|
||||
inline static uint32_t constexpr Hash(char const* input) {
|
||||
return (*input) ? static_cast<uint32_t>((*input)) + 33 * Hash(input + 1) : 5381;
|
||||
}
|
||||
inline static int constexpr Length(const char* str) { return *str ? 1 + Length(str + 1) : 0; }
|
||||
|
||||
public:
|
||||
constexpr explicit ConstString(const char* str) : _str(str), _length(Length(str)), _hash(Hash(str)){};
|
||||
|
||||
[[nodiscard]] constexpr const char* c_str() const noexcept { return _str; }
|
||||
[[nodiscard]] std::string std_str() const { return std::string(_str, _length); }
|
||||
|
||||
[[nodiscard]] constexpr size_t Length() const noexcept { return _length; }
|
||||
|
||||
[[nodiscard]] constexpr uint32_t GetHash() const noexcept { return _hash; }
|
||||
};
|
||||
constexpr ConstString operator"" _const(const char* c) { return ConstString(c); }
|
||||
}
|
||||
|
||||
#endif // ARBUTILS_CONSTSTRING_HPP
|
||||
79
src/Enum.hpp
Normal file
79
src/Enum.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include "MacroUtils.hpp"
|
||||
|
||||
#define ENUM_CASE(x, name) \
|
||||
case name::x: \
|
||||
return #x;
|
||||
#
|
||||
#define ENUM_PARSE_CASE(x, name) \
|
||||
case ConstHash(#x): \
|
||||
return name::x;
|
||||
#
|
||||
#define ENUM_TRY_PARSE_CASE(x, name) \
|
||||
case ConstHash(#x): \
|
||||
out = name::x; \
|
||||
return true;
|
||||
#
|
||||
#define ENUM_PARSE_CASE_INSENSITIVE(x, name) \
|
||||
case ConstHashCI(#x): \
|
||||
return name::x;
|
||||
#
|
||||
#define ENUM_TRY_PARSE_CASE_INSENSITIVE(x, name) \
|
||||
case ConstHashCI(#x): \
|
||||
out = name::x; \
|
||||
return true;
|
||||
#
|
||||
#define ARRAY_NAME(x, name) name::x,
|
||||
|
||||
/*!
|
||||
\def ENUM(name, type, values...)
|
||||
Generates an enum class inheriting from specified type with specified name. Also generates a useful helper class with
|
||||
static methods for use with the enum.
|
||||
*/
|
||||
|
||||
#define ENUM(name, type, values...) \
|
||||
enum class name : type { values }; \
|
||||
class name##Helper { \
|
||||
inline static uint32_t constexpr ConstHash(char const* input) { \
|
||||
return *input ? static_cast<uint32_t>(*input) + 33 * ConstHash(input + 1) : 5381; \
|
||||
} \
|
||||
inline static constexpr char charToLower(const char c) { \
|
||||
return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; \
|
||||
} \
|
||||
inline static uint32_t constexpr ConstHashCI(char const* input) { \
|
||||
return charToLower(*input) ? static_cast<uint32_t>(charToLower(*input)) + 33 * ConstHashCI(input + 1) \
|
||||
: 5381; \
|
||||
} \
|
||||
\
|
||||
public: \
|
||||
constexpr static const char* ToString(name value) { \
|
||||
switch (value) { FOR_EACH(ENUM_CASE, name, values) } \
|
||||
throw std::logic_error("Not reachable"); \
|
||||
} \
|
||||
constexpr static name Parse(const char* input, bool caseInsensitive = false) { \
|
||||
if (caseInsensitive) \
|
||||
return ParseCaseInsensitive(input); \
|
||||
switch (ConstHash(input)) { FOR_EACH(ENUM_PARSE_CASE, name, values) } \
|
||||
throw std::runtime_error("Invalid " #name " string."); \
|
||||
} \
|
||||
constexpr static bool TryParse(const char* input, name& out, bool caseInsensitive = false) { \
|
||||
if (caseInsensitive) \
|
||||
return TryParseCaseInsensitive(input, out); \
|
||||
switch (ConstHash(input)) { FOR_EACH(ENUM_TRY_PARSE_CASE, name, values) } \
|
||||
return false; \
|
||||
} \
|
||||
static std::vector<name> GetValues() { return {FOR_EACH(ARRAY_NAME, name, values)}; } \
|
||||
\
|
||||
private: \
|
||||
static name ParseCaseInsensitive(const char* input) { \
|
||||
switch (ConstHashCI(input)) { FOR_EACH(ENUM_PARSE_CASE_INSENSITIVE, name, values) } \
|
||||
throw std::runtime_error("Invalid " #name " string."); \
|
||||
} \
|
||||
static bool TryParseCaseInsensitive(const char* input, name& out) { \
|
||||
switch (ConstHashCI(input)) { FOR_EACH(ENUM_TRY_PARSE_CASE_INSENSITIVE, name, values) } \
|
||||
return false; \
|
||||
} \
|
||||
};
|
||||
45
src/MacroUtils.hpp
Normal file
45
src/MacroUtils.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
// Defines a for each macro utility, with up to 32 elements.
|
||||
|
||||
#define FE_0(FUNC, arg)
|
||||
#define FE_1(FUNC, arg, X) FUNC(X, arg)
|
||||
#define FE_2(FUNC, arg, X, ...) FUNC(X, arg) FE_1(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_3(FUNC, arg, X, ...) FUNC(X, arg) FE_2(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_4(FUNC, arg, X, ...) FUNC(X, arg) FE_3(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_5(FUNC, arg, X, ...) FUNC(X, arg) FE_4(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_6(FUNC, arg, X, ...) FUNC(X, arg) FE_5(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_7(FUNC, arg, X, ...) FUNC(X, arg) FE_6(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_8(FUNC, arg, X, ...) FUNC(X, arg) FE_7(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_9(FUNC, arg, X, ...) FUNC(X, arg) FE_8(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_10(FUNC, arg, X, ...) FUNC(X, arg) FE_9(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_11(FUNC, arg, X, ...) FUNC(X, arg) FE_10(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_12(FUNC, arg, X, ...) FUNC(X, arg) FE_11(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_13(FUNC, arg, X, ...) FUNC(X, arg) FE_12(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_14(FUNC, arg, X, ...) FUNC(X, arg) FE_13(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_15(FUNC, arg, X, ...) FUNC(X, arg) FE_14(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_16(FUNC, arg, X, ...) FUNC(X, arg) FE_15(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_17(FUNC, arg, X, ...) FUNC(X, arg) FE_16(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_18(FUNC, arg, X, ...) FUNC(X, arg) FE_17(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_19(FUNC, arg, X, ...) FUNC(X, arg) FE_18(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_20(FUNC, arg, X, ...) FUNC(X, arg) FE_19(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_21(FUNC, arg, X, ...) FUNC(X, arg) FE_20(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_22(FUNC, arg, X, ...) FUNC(X, arg) FE_21(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_23(FUNC, arg, X, ...) FUNC(X, arg) FE_22(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_24(FUNC, arg, X, ...) FUNC(X, arg) FE_23(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_25(FUNC, arg, X, ...) FUNC(X, arg) FE_24(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_26(FUNC, arg, X, ...) FUNC(X, arg) FE_25(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_27(FUNC, arg, X, ...) FUNC(X, arg) FE_26(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_28(FUNC, arg, X, ...) FUNC(X, arg) FE_27(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_29(FUNC, arg, X, ...) FUNC(X, arg) FE_28(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_30(FUNC, arg, X, ...) FUNC(X, arg) FE_29(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_31(FUNC, arg, X, ...) FUNC(X, arg) FE_30(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_32(FUNC, arg, X, ...) FUNC(X, arg) FE_31(FUNC, arg, __VA_ARGS__)
|
||||
#define FE_33(FUNC, arg, X, ...) THE_FOREACH_MACRO_CURRENTLY_ONLY_SUPPORTS_UP_TO_32_VALUES FE_32(FUNC, arg, __VA_ARGS__)
|
||||
|
||||
#define GET_MACRO(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, \
|
||||
_22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, NAME, ...) \
|
||||
NAME
|
||||
#define FOR_EACH(action, arg, ...) \
|
||||
GET_MACRO(_0, __VA_ARGS__, FE_33, FE_32, FE_31, FE_30, FE_29, FE_28, FE_27, FE_26, FE_25, FE_24, FE_23, FE_22, \
|
||||
FE_21, FE_20, FE_19, FE_18, FE_17, FE_16, FE_15, FE_14, FE_13, FE_12, FE_11, FE_10, FE_9, FE_8, FE_7, \
|
||||
FE_6, FE_5, FE_4, FE_3, FE_2, FE_1, FE_0) \
|
||||
(action, arg, __VA_ARGS__)
|
||||
9
src/Random.cpp
Normal file
9
src/Random.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "Random.hpp"
|
||||
#include <chrono>
|
||||
|
||||
// Seed parameterless constructor with current milliseconds since epoch.
|
||||
template <class RandomT>
|
||||
Arbutils::BaseRandom<RandomT>::BaseRandom()
|
||||
: _rng(RandomT(
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch())
|
||||
.count())) {}
|
||||
71
src/Random.hpp
Normal file
71
src/Random.hpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#ifndef ARBUTILS_RANDOM_HPP
|
||||
#define ARBUTILS_RANDOM_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <random>
|
||||
|
||||
namespace Arbutils {
|
||||
|
||||
template <class RandomT> class BaseRandom {
|
||||
private:
|
||||
RandomT _rng;
|
||||
|
||||
public:
|
||||
BaseRandom();
|
||||
explicit BaseRandom(int32_t seed) : _rng(seed){};
|
||||
|
||||
/// Gets a random float between 0.0 and 1.0.
|
||||
[[nodiscard]] inline float GetFloat() {
|
||||
return static_cast<float>(_rng()) / (static_cast<float>(std::mt19937::max() - std::mt19937::min()) - 0.5f);
|
||||
}
|
||||
|
||||
/// Gets a random double between 0.0 and 1.0.
|
||||
[[nodiscard]] inline double GetDouble() {
|
||||
return static_cast<double>(_rng()) /
|
||||
((static_cast<double>(std::mt19937::max()) - std::mt19937::min()) - 0.5);
|
||||
}
|
||||
|
||||
/// Gets a random 32 bit integer between 0 and max int.
|
||||
[[nodiscard]] inline int32_t Get() {
|
||||
return static_cast<int32_t>(GetDouble() * static_cast<float>(std::numeric_limits<int32_t>::max()));
|
||||
}
|
||||
|
||||
/// Gets a random 32 bit integer between 0, and given max parameter.
|
||||
/// \param max The exclusive max value the random value should be.
|
||||
[[nodiscard]] inline int32_t Get(int32_t max) {
|
||||
return static_cast<int32_t>(GetDouble() * static_cast<float>(max));
|
||||
}
|
||||
|
||||
/// Gets a random 32 bit integer between given min and max parameters.
|
||||
/// \param min The inclusive min value the random value should be.
|
||||
/// \param max The exclusive max value the random value should be.
|
||||
[[nodiscard]] inline int32_t Get(int32_t min, int32_t max) {
|
||||
return static_cast<int32_t>(GetDouble() * static_cast<float>(max - min) + min);
|
||||
}
|
||||
|
||||
/// Gets a random 32 bit unsigned integer between 0 and max unsigned int.
|
||||
[[nodiscard]] inline uint32_t GetUnsigned() {
|
||||
return static_cast<int32_t>(GetDouble() * static_cast<float>(std::numeric_limits<uint32_t>::max()));
|
||||
}
|
||||
|
||||
/// Gets a random 32 bit unsigned integer between 0, and given max parameter.
|
||||
/// \param max The exclusive max value the random value should be.
|
||||
[[nodiscard]] inline uint32_t GetUnsigned(uint32_t max) {
|
||||
return static_cast<int32_t>(GetDouble() * static_cast<float>(max));
|
||||
}
|
||||
|
||||
/// Gets a random 32 bit unsigned integer between given min and max parameters.
|
||||
/// \param min The inclusive min value the random value should be.
|
||||
/// \param max The exclusive max value the random value should be.
|
||||
[[nodiscard]] inline uint32_t GetUnsigned(uint32_t min, uint32_t max) {
|
||||
return static_cast<int32_t>(GetDouble() * static_cast<float>(max - min) + min);
|
||||
}
|
||||
};
|
||||
|
||||
class Random : public BaseRandom<std::mt19937> {
|
||||
public:
|
||||
Random() : BaseRandom() {}
|
||||
Random(int32_t seed) : BaseRandom(seed) {}
|
||||
};
|
||||
}
|
||||
#endif // ARBUTILS_RANDOM_HPP
|
||||
Reference in New Issue
Block a user