/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: auContainerUtils.hpp Date: 2022-2-1 File: AuroraUtils.hpp File: auROXTLUtils.hpp Date: 2021-6-9 Author: Reece ***/ #pragma once #include namespace __audetail { template struct AuHascapacity { template static constexpr AuTrueType Test(decltype(&C::capacity)); template static constexpr AuFalseType Test(...); using type = decltype(Test(0)); }; template constexpr inline bool AuHascapacity_v = AuHascapacity::type::value; template struct AuHasreserve { template static constexpr AuTrueType Test(decltype(&C::reserve)); template static constexpr AuFalseType Test(...); using type = decltype(Test(0)); }; template constexpr inline bool AuHasreserve_v = AuHasreserve::type::value; template constexpr inline bool AuIsPreallocatable_v = AuHascapacity_v && AuHasreserve_v; template struct AuHastry_emplace { template static constexpr AuTrueType Test(decltype(&C::try_emplace)); template static constexpr AuFalseType Test(...); using type = decltype(Test(0)); }; template constexpr inline bool AuHastry_emplace_v = false;// ::type::value; template struct AuHasemplace { template static constexpr AuTrueType Test(decltype(&C::emplace)); template static constexpr AuFalseType Test(...); using type = decltype(Test(0)); }; template constexpr inline bool AuHasemplace_v = true;//AuHasemplace::type::value; template struct AuHasfind { template static constexpr AuTrueType Test(decltype(static_cast(&C::find))); template static constexpr AuTrueType Test(decltype(static_cast(&C::find))); template static constexpr AuFalseType Test(...); using type = decltype(Test(0)); }; template constexpr inline bool AuHasfind_v = AuHasfind::type::value; template struct AuHasend { template static constexpr AuTrueType Test(decltype(static_cast(&C::end))); template static constexpr AuFalseType Test(...); using type = decltype(Test(0)); }; template constexpr inline bool AuHasend_v = AuHasend::type::value; } template inline bool _AuRemoveIfBase(T &in, const AuPredicate &> &predicate); template inline bool AuRemoveAllIf(T &in, const AuPredicate &> &predicate) { return _AuRemoveIfBase(in, predicate); } template inline bool AuRemoveIf(T &in, const AuPredicate &> &predicate) { return _AuRemoveIfBase(in, predicate); } template inline void AuRemove(T &in, const Z &type) { auto itr = in.find(type); if (itr == in.end()) { return; } in.erase(itr); } template inline void AuRemoveRange(T &in, AuUInt index, AuUInt length) { if (index + length > in.size()) { return; } auto begin = in.begin(); auto end = begin; std::advance(begin, index); std::advance(end, index + length); while (begin != end) { in.erase(begin++); } } template inline bool AuTryRemoveRange(T &in, AuUInt index, AuUInt length) { AUROXTL_COMMODITY_TRY { if (index + length > in.size()) { return false; } auto begin = in.begin(); auto end = begin; std::advance(begin, index); std::advance(end, index + length); while (begin != end) { in.erase(begin++); } } AUROXTL_COMMODITY_CATCH { return false; } return true; } template && !AuIsPointer_v)> inline bool AuTryFind(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 inline bool AuTryFind(Map *map, const Key &key, Value *&ptr) { return AuTryFind(*map, key, ptr); } template inline auto AuTryFindByTupleN(List &list, const Key &key) { for (auto itr = list.begin(); itr != list.end(); ) { if (AuGet(*itr) == key) { return itr; } else { itr++; } } return list.end(); } template && !AuIsPointer_v)> inline bool AuExists(const Range &a, const Key &key) { return std::find(a.begin(), a.end(), key) != a.end(); } template && !AuIsPointer_v)> inline bool AuExists(const Map &map, const Key &key) { auto itr = map.find(key); if (itr != map.end()) { return true; } else { return false; } } template inline bool AuExists(const Map *map, const Key &key) { return AuExists(*map, key); } template inline bool AuTryClear(Container &container) { container.clear(); return true; } template && !AuIsPointer_v)> inline bool AuTryRemove(Range &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 && !AuIsPointer_v)> inline bool AuTryRemove(Map &map, const Key &key) { auto itr = map.find(key); if (itr != map.end()) { map.erase(itr); return true; } else { return false; } } template inline bool AuTryRemove(Map *map, const Key &key) { return AuTryRemove(*map, key); } template inline bool AuTryRemoveByTupleN(List &list, const Key &key) { for (auto itr = list.begin(); itr != list.end(); ) { if (AuGet(*itr) == key) { itr = list.erase(itr); return true; } else { itr++; } } return false; } template inline bool AuTryInsert(Container &container, Key_t &&key, Type_t &&value, bool overwriteMode = true) { AUROXTL_COMMODITY_TRY { auto itr = container.find(key); if (itr == container.end()) { #if defined(_AURORA_NULLEXPT_USE_TRY_EMPLACE_AFTER_FIND) if constexpr (__audetail::AuHastry_emplace_v) { auto [iterator, success] = container.try_emplace(AuMove(key), AuMove(value)); return success; } else #endif if constexpr (__audetail::AuHasemplace_v) { container.emplace(AuMove(key), AuMove(value)); return true; } else { container.insert(AuMakePair(AuMove(key), AuMove(value))); } } else { if (!overwriteMode) { return false; } itr->second = AuMove(value); } return true; } AUROXTL_COMMODITY_CATCH { return false; } } template inline bool AuTryInsert(Container &container, const Key_t &key, Type_t &&value, bool overwriteMode = true) { AUROXTL_COMMODITY_TRY { auto itr = container.find(key); if (itr == container.end()) { #if defined(_AURORA_NULLEXPT_USE_TRY_EMPLACE_AFTER_FIND) if constexpr (__audetail::AuHastry_emplace_v) { auto [iterator, success] = container.try_emplace(key, AuMove(value)); return success; } else #endif if constexpr (__audetail::AuHasemplace_v) { container.emplace(key, AuMove(value)); return true; } else { container.insert(AuMakePair(key, AuMove(value))); } } else { if (!overwriteMode) { return false; } itr->second = AuMove(value); } return true; } AUROXTL_COMMODITY_CATCH { return false; } } template inline bool AuTryReserve(Container &container, AuUInt uRequired) { if (container.capacity() >= uRequired) { return true; } AUROXTL_COMMODITY_TRY { container.reserve(uRequired); } AUROXTL_COMMODITY_CATCH { return false; } return container.capacity() >= uRequired; } template inline bool AuContainerReserveSpaceForOne(Container &container) { auto uCapacity = container.size(); if (container.capacity() >= (uCapacity + 1)) { return true; } return AuTryReserve(container, uCapacity > 512 ? 512 : uCapacity + 32); } template inline bool AuContainerReserveSpaceForOne(Container *container) { return AuContainerReserveSpaceForOne(*container); } template && !AuIsPointer_v)> inline bool AuTryInsert(Container &container, const Value &value) { AUROXTL_COMMODITY_TRY { if constexpr (__audetail::AuIsPreallocatable_v>) { if (!AuContainerReserveSpaceForOne(container)) { return false; } } container.insert(AuReference(value)); return true; } AUROXTL_COMMODITY_CATCH { return false; } } template && !AuIsPointer_v)> inline bool AuTryInsert(Container &container, Value &&value) { AUROXTL_COMMODITY_TRY { if constexpr (__audetail::AuIsPreallocatable_v>) { if (!AuContainerReserveSpaceForOne(container)) { return false; } } container.insert(AuMove(value)); return true; } AUROXTL_COMMODITY_CATCH { return false; } } template && !AuIsPointer_v)> inline bool AuTryInsert(Container &container, Value &&value) { AUROXTL_COMMODITY_TRY { if constexpr (__audetail::AuIsPreallocatable_v>) { if (!AuContainerReserveSpaceForOne(container)) { return false; } } container.insert(container.end(), AuMove(value)); return true; } AUROXTL_COMMODITY_CATCH { return false; } } template && !AuIsPointer_v)> inline bool AuTryInsert(Container &container, const Value &value) { AUROXTL_COMMODITY_TRY { if constexpr (__audetail::AuIsPreallocatable_v>) { if (!AuContainerReserveSpaceForOne(container)) { return false; } } container.insert(container.end(), value); return true; } AUROXTL_COMMODITY_CATCH { return false; } } template inline bool AuTryInsert(Map *map, Key &&key, Value &&value, bool overwriteMode = true) { return AuTryInsert(*map, AuMove(key), AuMove(value), overwriteMode); } template inline bool AuTryInsert(Map *map, const Key &key, Value &&value, bool overwriteMode = true) { return AuTryInsert(*map, AuReference(key), AuMove(value), overwriteMode); } template inline bool AuTryInsert(Map *map, Value &&value) { return AuTryInsert(*map, AuMove(value)); } template inline bool AuTryInsert(Map *map, const Value &value) { return AuTryInsert(*map, value); } namespace Aurora::Memory { struct ByteBuffer; } template inline bool AuTryResize(T &list, AuUInt length) { AUROXTL_COMMODITY_TRY { if constexpr (AuIsSame_v) { return list.Resize(length); } else { list.resize(length); return true; } } AUROXTL_COMMODITY_CATCH { return false; } } template inline bool AuTryDownsize(T &list, AuUInt length) { AUROXTL_COMMODITY_TRY { if constexpr (AuIsSame_v) { if (!list.Resize(length)) { return false; } list.GC(); return true; } else { list.resize(length); list.shrink_to_fit(); return true; } } AUROXTL_COMMODITY_CATCH { return false; } } template inline bool _AuRemoveIfBase(T &in, const AuPredicate &> &predicate) { bool retOne {}; for (auto itr = in.begin(); itr != in.end(); ) { if (predicate(*itr)) { itr = in.erase(itr); if constexpr (!all) { return true; } retOne = true; } else { itr++; } } // optimization hint if constexpr (all) return retOne; return {}; }