1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 08:47:17 +01:00
SqMod/module/Library/Utils/Map.hpp
Sandu Liviu Catalin 0670a8dadf Improve vector container.
Add basic map container.
2021-01-31 14:09:37 +02:00

271 lines
9.1 KiB
C++

#pragma once
// ------------------------------------------------------------------------------------------------
#include "Core/Utility.hpp"
// ------------------------------------------------------------------------------------------------
#include <map>
#include <random>
#include <iterator>
#include <algorithm>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Utility used to transform optimal argument type to stored type.
*/
template < class T > struct SqMapOpt
{
/* --------------------------------------------------------------------------------------------
* Optimal argument type.
*/
using Type = T;
/* --------------------------------------------------------------------------------------------
* Container type.
*/
using Container = std::map< T, LightObj >;
/* --------------------------------------------------------------------------------------------
* Convert the optimal type to the stored type. Does nothing special in this case.
*/
inline static Type & Get(Type & k) { return k; }
inline static const Type & Get(const Type & k) { return k; }
// --------------------------------------------------------------------------------------------
inline static void Put(Container & c, LightObj & v, Type & k)
{
c[k] = v;
}
inline static void Put(Container & c, LightObj & v, const Type & k)
{
c[k] = v;
}
// --------------------------------------------------------------------------------------------
inline static void Put(Container & c, LightObj && v, Type & k)
{
c[k] = std::move(v);
}
inline static void Put(Container & c, LightObj && v, const Type & k)
{
c[k] = std::move(v);
}
};
/* ------------------------------------------------------------------------------------------------
* Specialization of SqMapOpt for String type.
*/
template < > struct SqMapOpt< String >
{
/* --------------------------------------------------------------------------------------------
* Optimal argument type.
*/
using Type = StackStrF;
/* --------------------------------------------------------------------------------------------
* Container type.
*/
using Container = std::map< String, LightObj >;
/* --------------------------------------------------------------------------------------------
* Convert the optimal type to the stored type.
*/
inline static String Get(Type & k) { return k.ToStr(); }
inline static String Get(const Type & k) { return k.ToStr(); }
// --------------------------------------------------------------------------------------------
inline static void Put(Container & c, LightObj & v, Type & k)
{
c[k.ToStr()] = v;
}
inline static void Put(Container & c, LightObj & v, const Type & k)
{
c[k.ToStr()] = v;
}
// --------------------------------------------------------------------------------------------
inline static void Put(Container & c, LightObj && v, Type & k)
{
c[k.ToStr()] = std::move(v);
}
inline static void Put(Container & c, LightObj && v, const Type & k)
{
c[k.ToStr()] = std::move(v);
}
};
/* ------------------------------------------------------------------------------------------------
* Wrapper around a std::map of values. Space efficient table.
*/
template < class T > struct SqMap
{
/* --------------------------------------------------------------------------------------------
* Type given via the template parameter.
*/
using Type = T;
/* --------------------------------------------------------------------------------------------
* The typeof container that will be used.
*/
using Container = std::map< T, LightObj >;
/* --------------------------------------------------------------------------------------------
* Type stored in the container.
*/
using Element = typename Container::value_type;
/* --------------------------------------------------------------------------------------------
* Reference to the container.
*/
using Reference = std::shared_ptr< Container >;
/* --------------------------------------------------------------------------------------------
* Type given used to interact with specialized value cases.
*/
using Opt = SqMapOpt< T >;
/* --------------------------------------------------------------------------------------------
* Optimal type to receive a value of this type as function argument. Mainly for strings.
*/
using OptimalType = typename Opt::Type;
/* --------------------------------------------------------------------------------------------
* Same as OptimalType but preferably with a reference qualifier to avoid copies.
*/
using OptimalArg = typename std::conditional< std::is_same< T, OptimalType >::value, T, OptimalType & >::type;
/* --------------------------------------------------------------------------------------------
* Reference to the container instance.
*/
Reference mC;
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
SqMap()
: mC(std::make_shared< Container >())
{
}
/* --------------------------------------------------------------------------------------------
* Copy constructor from reference.
*/
explicit SqMap(const Reference & v)
: mC(v)
{
}
/* --------------------------------------------------------------------------------------------
* Move constructor from reference.
*/
explicit SqMap(Reference && v) noexcept
: mC(std::move(v))
{
}
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
SqMap(SqMap &&) noexcept = default;
/* --------------------------------------------------------------------------------------------
* Destroys the Statement.
*/
~SqMap() = default;
/* --------------------------------------------------------------------------------------------
* Assignment operator.
*/
SqMap & operator = (const SqMap &) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment.
*/
SqMap & operator = (SqMap &&) noexcept = default;
/* --------------------------------------------------------------------------------------------
* Make sure a container instance is referenced.
*/
void Validate() const
{
if (!mC)
{
STHROWF("Invalid map container instance");
}
}
/* --------------------------------------------------------------------------------------------
* Make sure a container instance is referenced and return it.
*/
Container & Valid() const { Validate(); return *mC; }
/* --------------------------------------------------------------------------------------------
* Make sure a container instance is referenced and is populated, then return it.
*/
Container & ValidPop() const
{
Validate();
if (mC->empty())
{
STHROWF("Vector container is empty");
}
return *mC;
}
/* --------------------------------------------------------------------------------------------
* Check if a container instance is referenced.
*/
SQMOD_NODISCARD bool IsNull() const
{
return static_cast< bool >(mC);
}
/* --------------------------------------------------------------------------------------------
* Retrieve a value from the container.
*/
SQMOD_NODISCARD const LightObj & Get(OptimalArg k) const
{
return Valid()[Opt::Get(k)];
}
/* --------------------------------------------------------------------------------------------
* Modify a value from the container.
*/
void Set(LightObj & v, OptimalArg k)
{
Opt::Put(Valid(), std::move(v), k);
}
/* --------------------------------------------------------------------------------------------
* Check if the container has no elements.
*/
SQMOD_NODISCARD bool Empty() const
{
return Valid().empty();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the number of elements in the container.
*/
SQMOD_NODISCARD SQInteger Size() const
{
return static_cast< SQInteger >(Valid().size());
}
/* --------------------------------------------------------------------------------------------
* Erase all elements from the container.
*/
void Clear()
{
return Valid().clear();
}
/* --------------------------------------------------------------------------------------------
* Erase the element with a certain key from the container.
*/
void Erase(OptimalArg k)
{
Valid().erase(Opt::Get(k));
}
};
} // Namespace:: SqMod