378 lines
7.9 KiB
C++
378 lines
7.9 KiB
C++
/***
|
|
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
File: AuroraUtils.hpp
|
|
Date: 2021-6-9
|
|
Author: Reece
|
|
***/
|
|
#pragma once
|
|
|
|
template<typename T, int Z>
|
|
static constexpr int ArraySize(const T(&array)[Z])
|
|
{
|
|
return Z;
|
|
}
|
|
|
|
#if defined(DEBUG) || defined(INTERNAL)
|
|
|
|
template<typename Z, typename T>
|
|
static void inline SafeDelete(T *in)
|
|
{
|
|
static_assert(std::is_base_of<T, std::remove_pointer<Z>::type>::value);
|
|
auto cast = dynamic_cast<Z>(in);
|
|
if (cast == nullptr)
|
|
{
|
|
Z re;
|
|
SysPanic("Tried to free: 0x{:x}, type \"{}\" was not inherited from \"{}\"", AuUInt(in), typeid(in).name(), typeid(re).name());
|
|
}
|
|
delete cast;
|
|
}
|
|
|
|
#else
|
|
|
|
template<typename Z, typename T>
|
|
static void inline SafeDelete(T *in)
|
|
{
|
|
static_assert(std::is_base_of<T, std::remove_pointer<Z>::type>::value);
|
|
delete static_cast<Z>(in);
|
|
}
|
|
|
|
#endif
|
|
|
|
static inline AuUInt64 ConvertMagicTag64(const char buffer[8])
|
|
{
|
|
return *reinterpret_cast<const AuUInt64 *>(buffer);
|
|
}
|
|
|
|
static inline AuUInt32 ConvertMagicTag32(const char buffer[4])
|
|
{
|
|
return *reinterpret_cast<const AuUInt32 *>(buffer);
|
|
}
|
|
|
|
template<typename T, typename Z>
|
|
static inline std::optional<AuSPtr<T>> OptionalSharedDynamicCast(std::optional<AuSPtr<Z>> &in)
|
|
{
|
|
if (!in.has_value()) return {};
|
|
return std::dynamic_pointer_cast<T>(in.value());
|
|
}
|
|
|
|
template<typename T, typename Z>
|
|
static inline std::optional<AuSPtr<T>> OptionalSharedStaticCast(std::optional<AuSPtr<Z>> &in)
|
|
{
|
|
if (!in.has_value()) return {};
|
|
return std::static_pointer_cast<T>(in.value());
|
|
}
|
|
|
|
static inline bool EndsWith(std::string const &value, std::string const &ending)
|
|
{
|
|
if (ending.size() > value.size()) return false;
|
|
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
|
}
|
|
|
|
static inline bool StartsWith(std::string const &value, std::string const &starting)
|
|
{
|
|
return value.rfind(starting, 0) == 0;
|
|
}
|
|
|
|
template<typename T>
|
|
static inline AuString ToStringASCIIOp(T op, const AuString &in)
|
|
{
|
|
AuString ret;
|
|
ret.resize(in.size());
|
|
std::transform(in.begin(), in.end(), ret.begin(), [=](const char &c)
|
|
{
|
|
return op(c);
|
|
});
|
|
return ret;
|
|
}
|
|
|
|
static inline AuString ToLower(const AuString &in)
|
|
{
|
|
return ToStringASCIIOp<int(*)(int)>(std::tolower, in);
|
|
}
|
|
|
|
static inline AuString ToUpper(const AuString &in)
|
|
{
|
|
return ToStringASCIIOp<int(*)(int)>(std::toupper, in);
|
|
}
|
|
|
|
template<typename Map, class Key, typename Value>
|
|
static inline bool TryFind(Map &map, const Key &key, Value *&ptr)
|
|
{
|
|
auto itr = map.find(key);
|
|
if (itr != map.end())
|
|
{
|
|
ptr = &itr->second;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
ptr = nullptr;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
template<typename Map, class Key, typename Value>
|
|
static inline bool TryFind(Map *map, const Key &key, Value *&ptr)
|
|
{
|
|
auto itr = map->find(key);
|
|
if (itr != map->end())
|
|
{
|
|
ptr = &itr->second;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
ptr = nullptr;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
template<typename Map, class Key>
|
|
static inline bool TryFind(Map &map, const Key &key)
|
|
{
|
|
auto itr = map.find(key);
|
|
if (itr != map.end())
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
template<typename Map, class Key>
|
|
static inline bool TryFind(Map *map, const Key &key)
|
|
{
|
|
auto itr = map->find(key);
|
|
if (itr != map->end())
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
template<typename Map, class Key, typename Value>
|
|
static inline bool TryFindGeneric(Map &map, const Key &key, Value *&ptr)
|
|
{
|
|
auto itr = map.find(key);
|
|
if (itr != map.end())
|
|
{
|
|
ptr = &*itr;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
ptr = nullptr;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
template<typename Map, class Key>
|
|
static inline bool TryDelete(Map &map, const Key &key)
|
|
{
|
|
auto itr = map.find(key);
|
|
if (itr != map.end())
|
|
{
|
|
map.erase(itr);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
template<typename List, class Key>
|
|
static inline bool TryDeleteList(List &list, const Key &key)
|
|
{
|
|
auto itr = std::find(list.begin(), list.end(), key);
|
|
if (itr != list.end())
|
|
{
|
|
list.erase(itr);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
template<typename Container, typename Type>
|
|
static inline bool TryInsert(Container &container, const Type &value)
|
|
{
|
|
try
|
|
{
|
|
container.insert(container.end(), value);
|
|
|
|
return true;
|
|
}
|
|
catch (...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
template<typename Container, typename Type>
|
|
static inline bool TryInsert(Container &container, Type &&value)
|
|
{
|
|
try
|
|
{
|
|
container.insert(container.end(), value);
|
|
|
|
return true;
|
|
}
|
|
catch (...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
template<typename Container, typename Type>
|
|
static inline bool TryInsert(Container *container, const Type &value)
|
|
{
|
|
try
|
|
{
|
|
container->insert(container->end(), value);
|
|
|
|
return true;
|
|
}
|
|
catch (...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
template<typename Container, typename Type>
|
|
static inline bool TryInsert(Container *container, Type &&value)
|
|
{
|
|
try
|
|
{
|
|
container->insert(container->end(), value);
|
|
|
|
return true;
|
|
}
|
|
catch (...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
template<typename Container, typename Type>
|
|
static inline bool TryInsertNoEnd(Container &container, Type &&value) // move
|
|
{
|
|
try
|
|
{
|
|
container.insert(value);
|
|
|
|
return true;
|
|
}
|
|
catch (...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
template<typename Container, typename Type>
|
|
static inline bool TryInsertNoEnd(Container &container, const Type &value) // copy
|
|
{
|
|
try
|
|
{
|
|
container.insert(value);
|
|
|
|
return true;
|
|
}
|
|
catch (...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
template<typename Container, typename Type>
|
|
static inline bool TryInsertNoEnd(Container *container, Type &&value) // move
|
|
{
|
|
try
|
|
{
|
|
container->insert(value);
|
|
|
|
return true;
|
|
}
|
|
catch (...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
template<typename Container, typename Type>
|
|
static inline bool TryInsertNoEnd(Container *container, const Type &value) // copy
|
|
{
|
|
try
|
|
{
|
|
container->insert(value);
|
|
|
|
return true;
|
|
}
|
|
catch (...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
template<typename T>
|
|
static inline bool TryResize(T &list, AuUInt length)
|
|
{
|
|
try
|
|
{
|
|
list.resize(length);
|
|
return true;
|
|
}
|
|
catch (...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static inline std::string ReplaceAll(std::string &str, const std::string &from, const std::string &to)
|
|
{
|
|
size_t start_pos = 0;
|
|
while ((start_pos = str.find(from, start_pos)) != std::string::npos)
|
|
{
|
|
str.replace(start_pos, from.length(), to);
|
|
start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
|
|
}
|
|
return str;
|
|
}
|
|
|
|
// i told myself not to copy this, required a split function twice, now here we are :D
|
|
static inline AuList<AuString> SplitString(const AuString& str, const AuString& delim)
|
|
{
|
|
AuList<AuString> tokens;
|
|
AuUInt prev = 0, pos = 0;
|
|
do
|
|
{
|
|
pos = str.find(delim, prev);
|
|
if (pos == AuString::npos) pos = str.length();
|
|
auto token = str.substr(prev, pos-prev);
|
|
if (!token.empty()) tokens.push_back(token);
|
|
prev = pos + delim.length();
|
|
}
|
|
while (pos < str.length() && prev < str.length());
|
|
return tokens;
|
|
}
|
|
|
|
// more copy/pasta. work smart, not hard.
|
|
// i dont want to waste time working out template kinks between clang and msvc
|
|
template < template <typename...> class base,typename derived>
|
|
struct is_base_of_template_impl
|
|
{
|
|
template<typename... Ts>
|
|
static constexpr std::true_type test(const base<Ts...> *);
|
|
static constexpr std::false_type test(...);
|
|
using type = decltype(test(std::declval<derived*>()));
|
|
};
|
|
|
|
template < template <typename...> class base,typename derived>
|
|
using is_base_of_template = typename is_base_of_template_impl<base,derived>::type; |