merging latest development
Signed-off-by: kberg-amzn <karlberg@amazon.com>
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/functional.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
//! Sets a variable upon construction and again when the object goes out of scope.
|
||||
template<typename T>
|
||||
class ScopedValue
|
||||
{
|
||||
private:
|
||||
T* m_ptr;
|
||||
T m_finalValue;
|
||||
|
||||
public:
|
||||
ScopedValue(T* ptr, T initialValue, T finalValue) :
|
||||
m_ptr(ptr), m_finalValue(finalValue)
|
||||
{
|
||||
AZ_Assert(m_ptr, "ScopedValue::m_ptr is null");
|
||||
*m_ptr = initialValue;
|
||||
}
|
||||
|
||||
~ScopedValue()
|
||||
{
|
||||
*m_ptr = m_finalValue;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace AZ
|
||||
@@ -19,4 +19,5 @@ set(FILES
|
||||
std/containers/vector_set.h
|
||||
std/containers/vector_set_base.h
|
||||
std/parallel/concurrency_checker.h
|
||||
Utils/ScopedValue.h
|
||||
)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AtomCore/Utils/ScopedValue.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
TEST(ScopedValueTest, TestBoolValue)
|
||||
{
|
||||
bool localValue = false;
|
||||
|
||||
{
|
||||
AZ::ScopedValue<bool> scopedValue(&localValue, true, false);
|
||||
EXPECT_EQ(true, localValue);
|
||||
}
|
||||
|
||||
EXPECT_EQ(false, localValue);
|
||||
}
|
||||
|
||||
TEST(ScopedValueTest, TestIntValue)
|
||||
{
|
||||
int localValue = 0;
|
||||
|
||||
{
|
||||
AZ::ScopedValue<int> scopedValue(&localValue, 1, 2);
|
||||
EXPECT_EQ(1, localValue);
|
||||
}
|
||||
|
||||
EXPECT_EQ(2, localValue);
|
||||
}
|
||||
}
|
||||
@@ -12,5 +12,6 @@ set(FILES
|
||||
InstanceDatabase.cpp
|
||||
lru_cache.cpp
|
||||
Main.cpp
|
||||
ScopedValueTest.cpp
|
||||
vector_set.cpp
|
||||
)
|
||||
|
||||
@@ -213,7 +213,7 @@ namespace AZ
|
||||
|
||||
void AssetData::Acquire()
|
||||
{
|
||||
AZ_Assert(m_useCount >= 0, "AssetData has been deleted")
|
||||
AZ_Assert(m_useCount >= 0, "AssetData has been deleted");
|
||||
|
||||
AcquireWeak();
|
||||
++m_useCount;
|
||||
|
||||
@@ -990,7 +990,7 @@ namespace AZ
|
||||
template<class T>
|
||||
u8 Asset<T>::GetFlags() const
|
||||
{
|
||||
AZ_Warning("Asset", false, "Deprecated - replaced by GetAutoLoadBehavior")
|
||||
AZ_Warning("Asset", false, "Deprecated - replaced by GetAutoLoadBehavior");
|
||||
return static_cast<u8>(m_loadBehavior);
|
||||
}
|
||||
|
||||
@@ -1012,7 +1012,7 @@ namespace AZ
|
||||
template<class T>
|
||||
bool Asset<T>::SetFlags(u8 flags)
|
||||
{
|
||||
AZ_Warning("Asset", false, "Deprecated - replaced by SetAutoLoadBehavior")
|
||||
AZ_Warning("Asset", false, "Deprecated - replaced by SetAutoLoadBehavior");
|
||||
if (!m_assetData)
|
||||
{
|
||||
AZ_Assert(flags < static_cast<u8>(AssetLoadBehavior::Count), "Flags value is out of range");
|
||||
|
||||
@@ -2132,7 +2132,7 @@ namespace AZ
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning("AssetManager", false, "Couldn't find handler for asset %s (%s)", asset.GetId().ToString<AZStd::string>().c_str(), asset.GetHint().c_str())
|
||||
AZ_Warning("AssetManager", false, "Couldn't find handler for asset %s (%s)", asset.GetId().ToString<AZStd::string>().c_str(), asset.GetHint().c_str());
|
||||
}
|
||||
|
||||
// Notify any dependent jobs.
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace AZ {
|
||||
struct Uuid;
|
||||
|
||||
@@ -8,14 +8,25 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// This is disabled by default because it puts in costly runtime checking of casted values.
|
||||
// You can either change it here to enable it across the engine, or use push/pop_macro to enable per file/feature.
|
||||
// Note that if using push/pop_macro, you may get some of the functions not inline and the definition coming from
|
||||
// another compilation unit, in such case, you will have to push/pop_macro on that compilation unit as well.
|
||||
// #define AZ_NUMERICCAST_ENABLED 1
|
||||
|
||||
#if !AZ_NUMERICCAST_ENABLED
|
||||
|
||||
#define aznumeric_cast static_cast
|
||||
|
||||
#else
|
||||
|
||||
#include <AzCore/Casting/numeric_cast_internal.h>
|
||||
#include <AzCore/std/typetraits/is_arithmetic.h>
|
||||
#include <AzCore/std/typetraits/is_class.h>
|
||||
#include <AzCore/std/typetraits/is_enum.h>
|
||||
#include <AzCore/std/typetraits/is_floating_point.h>
|
||||
#include <AzCore/std/typetraits/is_integral.h>
|
||||
#include <AzCore/std/typetraits/is_same.h>
|
||||
#include <AzCore/std/typetraits/is_signed.h>
|
||||
#include <AzCore/std/typetraits/is_unsigned.h>
|
||||
#include <AzCore/std/typetraits/remove_cvref.h>
|
||||
#include <AzCore/std/typetraits/underlying_type.h>
|
||||
#include <AzCore/std/utils.h>
|
||||
@@ -28,7 +39,7 @@
|
||||
// enabled.
|
||||
//
|
||||
// Because we can't do partial function specialization, I'm using enable_if to chop up the implementation into one of these
|
||||
// implementations. If none of these fit, then we will get a compile error because it is an unknown conversionr.
|
||||
// implementations. If none of these fit, then we will get a compile error because it is an unknown conversion.
|
||||
//
|
||||
//--------------------------------------------
|
||||
// TYPE <- TYPE DigitLoss
|
||||
@@ -51,85 +62,7 @@
|
||||
// (K) Floating Floating Y
|
||||
*/
|
||||
|
||||
// This is disabled by default because it puts in costly runtime checking of casted values.
|
||||
// You can either change it here to enable it across the engine, or use push/pop_macro to enable per file/feature.
|
||||
// Note that if using push/pop_macro, you may get some of the functions not inline and the definition coming from
|
||||
// another compilation unit, in such case, you will have to push/pop_macro on that compilation unit as well.
|
||||
// #define AZ_NUMERICCAST_ENABLED 1
|
||||
|
||||
#if AZ_NUMERICCAST_ENABLED
|
||||
#define AZ_NUMERIC_ASSERT(expr, ...) AZ_Assert(expr, __VA_ARGS__)
|
||||
#else
|
||||
#define AZ_NUMERIC_ASSERT(expr, ...) void(0)
|
||||
#endif
|
||||
|
||||
#pragma push_macro("max")
|
||||
#undef max
|
||||
|
||||
namespace NumericCastInternal
|
||||
{
|
||||
template <typename ToType, typename FromType>
|
||||
inline constexpr typename AZStd::enable_if<
|
||||
!AZStd::is_integral<FromType>::value || !AZStd::is_floating_point<ToType>::value
|
||||
, bool> ::type UnderflowsToType(const FromType& value)
|
||||
{
|
||||
return (value < static_cast<FromType>(std::numeric_limits<ToType>::lowest()));
|
||||
}
|
||||
|
||||
template <typename ToType, typename FromType>
|
||||
inline constexpr typename AZStd::enable_if<
|
||||
AZStd::is_integral<FromType>::value && AZStd::is_floating_point<ToType>::value
|
||||
, bool> ::type UnderflowsToType(const FromType& value)
|
||||
{
|
||||
return (static_cast<ToType>(value) < std::numeric_limits<ToType>::lowest());
|
||||
}
|
||||
|
||||
template <typename ToType, typename FromType>
|
||||
inline constexpr typename AZStd::enable_if<
|
||||
!AZStd::is_integral<FromType>::value || !AZStd::is_floating_point<ToType>::value
|
||||
, bool> ::type OverflowsToType(const FromType& value)
|
||||
{
|
||||
return (value > static_cast<FromType>(std::numeric_limits<ToType>::max()));
|
||||
}
|
||||
|
||||
template <typename ToType, typename FromType>
|
||||
inline constexpr typename AZStd::enable_if<
|
||||
AZStd::is_integral<FromType>::value && AZStd::is_floating_point<ToType>::value
|
||||
, bool> ::type OverflowsToType(const FromType& value)
|
||||
{
|
||||
return (static_cast<ToType>(value) > std::numeric_limits<ToType>::max());
|
||||
}
|
||||
|
||||
template <typename ToType, typename FromType>
|
||||
inline constexpr typename AZStd::enable_if<
|
||||
AZStd::is_integral<FromType>::value && AZStd::is_integral<ToType>::value
|
||||
&& std::numeric_limits<FromType>::digits <= std::numeric_limits<ToType>::digits
|
||||
&& AZStd::is_signed<FromType>::value && AZStd::is_unsigned<ToType>::value
|
||||
, bool> ::type FitsInToType(const FromType& value)
|
||||
{
|
||||
return !NumericCastInternal::UnderflowsToType<ToType>(value);
|
||||
}
|
||||
|
||||
template <typename ToType, typename FromType>
|
||||
inline constexpr typename AZStd::enable_if<
|
||||
AZStd::is_integral<FromType>::value && AZStd::is_integral<ToType>::value
|
||||
&& (std::numeric_limits<FromType>::digits > std::numeric_limits<ToType>::digits)
|
||||
&& AZStd::is_unsigned<FromType>::value
|
||||
, bool> ::type FitsInToType(const FromType& value)
|
||||
{
|
||||
return !NumericCastInternal::OverflowsToType<ToType>(value);
|
||||
}
|
||||
|
||||
template <typename ToType, typename FromType>
|
||||
inline constexpr typename AZStd::enable_if<
|
||||
(!AZStd::is_integral<FromType>::value || !AZStd::is_integral<ToType>::value)
|
||||
|| ((std::numeric_limits<FromType>::digits <= std::numeric_limits<ToType>::digits) && (AZStd::is_unsigned<FromType>::value || AZStd::is_signed<ToType>::value))
|
||||
|| ((std::numeric_limits<FromType>::digits > std::numeric_limits<ToType>::digits) && AZStd::is_signed<FromType>::value)
|
||||
, bool> ::type FitsInToType(const FromType& value)
|
||||
{
|
||||
return !NumericCastInternal::OverflowsToType<ToType>(value) && !NumericCastInternal::UnderflowsToType<ToType>(value);
|
||||
}
|
||||
} // namespace AZ
|
||||
|
||||
// INTEGER -> INTEGER
|
||||
// (A) Not losing digits or risking sign loss
|
||||
@@ -276,8 +209,10 @@ inline constexpr auto aznumeric_cast(FromType&& value) ->
|
||||
return static_cast<ToType>(value);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// This is a helper class that lets us induce the destination type of a numeric cast
|
||||
// It should never be directly used by anything other than azlossy_caster.
|
||||
// It should never be directly used by anything other than aznumeric_caster.
|
||||
namespace AZ
|
||||
{
|
||||
template <typename FromType>
|
||||
@@ -295,7 +230,7 @@ namespace AZ
|
||||
|
||||
FromType m_value;
|
||||
};
|
||||
}
|
||||
} // namespace AZ
|
||||
|
||||
// This is the primary function we should use when doing numeric casting, since it induces the
|
||||
// type we need to cast to from the code rather than requiring an explicit coupling in the source.
|
||||
@@ -305,4 +240,3 @@ inline constexpr AZ::NumericCasted<FromType> aznumeric_caster(FromType value)
|
||||
return AZ::NumericCasted<FromType>(value);
|
||||
}
|
||||
|
||||
#pragma pop_macro("max")
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/typetraits/conditional.h>
|
||||
#include <AzCore/std/typetraits/is_floating_point.h>
|
||||
#include <AzCore/std/typetraits/is_integral.h>
|
||||
#include <AzCore/std/typetraits/is_signed.h>
|
||||
#include <AzCore/std/typetraits/is_unsigned.h>
|
||||
#include <limits>
|
||||
|
||||
namespace NumericCastInternal
|
||||
{
|
||||
template<typename ToType, typename FromType>
|
||||
inline constexpr typename AZStd::enable_if<!AZStd::is_integral<FromType>::value || !AZStd::is_floating_point<ToType>::value, bool>::type
|
||||
UnderflowsToType(const FromType& value)
|
||||
{
|
||||
return (value < static_cast<FromType>(std::numeric_limits<ToType>::lowest()));
|
||||
}
|
||||
|
||||
template<typename ToType, typename FromType>
|
||||
inline constexpr typename AZStd::enable_if<AZStd::is_integral<FromType>::value && AZStd::is_floating_point<ToType>::value, bool>::type
|
||||
UnderflowsToType(const FromType& value)
|
||||
{
|
||||
return (static_cast<ToType>(value) < std::numeric_limits<ToType>::lowest());
|
||||
}
|
||||
|
||||
template<typename ToType, typename FromType>
|
||||
inline constexpr typename AZStd::enable_if<!AZStd::is_integral<FromType>::value || !AZStd::is_floating_point<ToType>::value, bool>::type
|
||||
OverflowsToType(const FromType& value)
|
||||
{
|
||||
return (value > static_cast<FromType>(std::numeric_limits<ToType>::max()));
|
||||
}
|
||||
|
||||
template<typename ToType, typename FromType>
|
||||
inline constexpr typename AZStd::enable_if<AZStd::is_integral<FromType>::value && AZStd::is_floating_point<ToType>::value, bool>::type
|
||||
OverflowsToType(const FromType& value)
|
||||
{
|
||||
return (static_cast<ToType>(value) > std::numeric_limits<ToType>::max());
|
||||
}
|
||||
|
||||
template<typename ToType, typename FromType>
|
||||
inline constexpr typename AZStd::enable_if<
|
||||
AZStd::is_integral<FromType>::value && AZStd::is_integral<ToType>::value &&
|
||||
std::numeric_limits<FromType>::digits <= std::numeric_limits<ToType>::digits && AZStd::is_signed<FromType>::value &&
|
||||
AZStd::is_unsigned<ToType>::value,
|
||||
bool>::type
|
||||
FitsInToType(const FromType& value)
|
||||
{
|
||||
return !NumericCastInternal::UnderflowsToType<ToType>(value);
|
||||
}
|
||||
|
||||
template<typename ToType, typename FromType>
|
||||
inline constexpr typename AZStd::enable_if<
|
||||
AZStd::is_integral<FromType>::value && AZStd::is_integral<ToType>::value &&
|
||||
(std::numeric_limits<FromType>::digits > std::numeric_limits<ToType>::digits) && AZStd::is_unsigned<FromType>::value,
|
||||
bool>::type
|
||||
FitsInToType(const FromType& value)
|
||||
{
|
||||
return !NumericCastInternal::OverflowsToType<ToType>(value);
|
||||
}
|
||||
|
||||
template<typename ToType, typename FromType>
|
||||
inline constexpr typename AZStd::enable_if<
|
||||
(!AZStd::is_integral<FromType>::value || !AZStd::is_integral<ToType>::value) ||
|
||||
((std::numeric_limits<FromType>::digits <= std::numeric_limits<ToType>::digits) &&
|
||||
(AZStd::is_unsigned<FromType>::value || AZStd::is_signed<ToType>::value)) ||
|
||||
((std::numeric_limits<FromType>::digits > std::numeric_limits<ToType>::digits) && AZStd::is_signed<FromType>::value),
|
||||
bool>::type
|
||||
FitsInToType(const FromType& value)
|
||||
{
|
||||
return !NumericCastInternal::OverflowsToType<ToType>(value) && !NumericCastInternal::UnderflowsToType<ToType>(value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -266,7 +266,7 @@ namespace AZ
|
||||
_ComponentClass::RTTI_Type().ToString<AZStd::string>().c_str(), descriptor->GetName(), _ComponentClass::RTTI_TypeName()); \
|
||||
return nullptr; \
|
||||
} \
|
||||
else if (descriptor->GetName() != _ComponentClass::RTTI_TypeName()) \
|
||||
if (descriptor->GetName() != _ComponentClass::RTTI_TypeName()) \
|
||||
{ \
|
||||
AZ_Error("Component", false, "The same component UUID (%s) / name (%s) was registered twice. This isn't allowed, " \
|
||||
"it can cause lifetime management issues / crashes.\nThis situation can happen by declaring a component " \
|
||||
|
||||
@@ -74,6 +74,8 @@
|
||||
#include <AzCore/Module/Environment.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
|
||||
AZ_CVAR(float, g_simulation_tick_rate, 0, nullptr, AZ::ConsoleFunctorFlags::Null, "The rate at which the game simulation tick loop runs, or 0 for as fast as possible");
|
||||
|
||||
static void PrintEntityName(const AZ::ConsoleCommandContainer& arguments)
|
||||
{
|
||||
if (arguments.empty())
|
||||
@@ -653,6 +655,7 @@ namespace AZ
|
||||
|
||||
ComponentApplicationBus::Handler::BusConnect();
|
||||
|
||||
m_currentTime = AZStd::chrono::system_clock::now();
|
||||
TickRequestBus::Handler::BusConnect();
|
||||
|
||||
#if defined(AZ_ENABLE_DEBUG_TOOLS)
|
||||
@@ -1249,6 +1252,8 @@ namespace AZ
|
||||
|
||||
return AZ::SettingsRegistryInterface::VisitResponse::Continue;
|
||||
}
|
||||
|
||||
using SettingsRegistryInterface::Visitor::Visit;
|
||||
void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, bool value) override
|
||||
{
|
||||
// By default the auto load option is true
|
||||
@@ -1365,45 +1370,44 @@ namespace AZ
|
||||
#endif
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Tick
|
||||
//=========================================================================
|
||||
void ComponentApplication::Tick(float deltaOverride /*= -1.f*/)
|
||||
{
|
||||
AZ_PROFILE_SCOPE(System, "Component application simulation tick");
|
||||
AZStd::chrono::system_clock::time_point now = AZStd::chrono::system_clock::now();
|
||||
m_deltaTime = 0.0f;
|
||||
if (now >= m_currentTime)
|
||||
{
|
||||
AZ_PROFILE_SCOPE(System, "Component application simulation tick");
|
||||
AZStd::chrono::duration<float> delta = now - m_currentTime;
|
||||
m_deltaTime = deltaOverride >= 0.f ? deltaOverride : delta.count();
|
||||
}
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzCore, "ComponentApplication::Tick:ExecuteQueuedEvents");
|
||||
TickBus::ExecuteQueuedEvents();
|
||||
}
|
||||
m_currentTime = now;
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzCore, "ComponentApplication::Tick:OnTick");
|
||||
EBUS_EVENT(TickBus, OnTick, m_deltaTime, ScriptTimePoint(now));
|
||||
}
|
||||
|
||||
TimeUs now = GetElapsedTimeUs();
|
||||
if (m_currentTime == TimeUs{ 0 })
|
||||
{
|
||||
m_currentTime = now;
|
||||
}
|
||||
// If tick rate limiting is on, ensure (1 / g_simulation_tick_rate) ms has elapsed since the last frame,
|
||||
// sleeping if there's still time remaining.
|
||||
if (g_simulation_tick_rate > 0.f)
|
||||
{
|
||||
now = AZStd::chrono::system_clock::now();
|
||||
|
||||
m_deltaTime = 0.0f;
|
||||
// Work in microsecond durations here as that's the native measurement time for time_point
|
||||
constexpr float microsecondsPerSecond = 1000.f * 1000.f;
|
||||
const AZStd::chrono::microseconds timeBudgetPerTick(static_cast<int>(microsecondsPerSecond / g_simulation_tick_rate));
|
||||
AZStd::chrono::microseconds timeUntilNextTick = m_currentTime + timeBudgetPerTick - now;
|
||||
|
||||
if (now >= m_currentTime)
|
||||
if (timeUntilNextTick.count() > 0)
|
||||
{
|
||||
float delta = TimeUsToSeconds(now - m_currentTime);
|
||||
m_deltaTime = deltaOverride >= 0.f ? deltaOverride : delta;
|
||||
}
|
||||
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzCore, "ComponentApplication::Tick:ExecuteQueuedEvents");
|
||||
TickBus::ExecuteQueuedEvents();
|
||||
}
|
||||
m_currentTime = now;
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzCore, "ComponentApplication::Tick:OnTick");
|
||||
auto epoch = AZStd::chrono::time_point<AZStd::chrono::high_resolution_clock>();
|
||||
auto chronoNow = AZStd::chrono::microseconds(aznumeric_cast<int64_t>(now));
|
||||
EBUS_EVENT(TickBus, OnTick, m_deltaTime, ScriptTimePoint(epoch + chronoNow));
|
||||
AZStd::this_thread::sleep_for(timeUntilNextTick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Tick
|
||||
//=========================================================================
|
||||
void ComponentApplication::TickSystem()
|
||||
{
|
||||
AZ_PROFILE_SCOPE(System, "Component application tick");
|
||||
@@ -1519,9 +1523,7 @@ namespace AZ
|
||||
//=========================================================================
|
||||
ScriptTimePoint ComponentApplication::GetTimeAtCurrentTick()
|
||||
{
|
||||
auto epoch = AZStd::chrono::time_point<AZStd::chrono::high_resolution_clock>();
|
||||
auto chronoCurrent = AZStd::chrono::microseconds(aznumeric_cast<int64_t>(m_currentTime));
|
||||
return ScriptTimePoint(epoch + chronoCurrent);
|
||||
return ScriptTimePoint(m_currentTime);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
|
||||
@@ -197,14 +197,14 @@ namespace AZ
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ComponentApplicationRequests
|
||||
void RegisterComponentDescriptor(const ComponentDescriptor* descriptor) override final;
|
||||
void UnregisterComponentDescriptor(const ComponentDescriptor* descriptor) override final;
|
||||
void RegisterEntityAddedEventHandler(EntityAddedEvent::Handler& handler) override final;
|
||||
void RegisterEntityRemovedEventHandler(EntityRemovedEvent::Handler& handler) override final;
|
||||
void RegisterEntityActivatedEventHandler(EntityActivatedEvent::Handler& handler) override final;
|
||||
void RegisterEntityDeactivatedEventHandler(EntityDeactivatedEvent::Handler& handler) override final;
|
||||
void SignalEntityActivated(Entity* entity) override final;
|
||||
void SignalEntityDeactivated(Entity* entity) override final;
|
||||
void RegisterComponentDescriptor(const ComponentDescriptor* descriptor) final;
|
||||
void UnregisterComponentDescriptor(const ComponentDescriptor* descriptor) final;
|
||||
void RegisterEntityAddedEventHandler(EntityAddedEvent::Handler& handler) final;
|
||||
void RegisterEntityRemovedEventHandler(EntityRemovedEvent::Handler& handler) final;
|
||||
void RegisterEntityActivatedEventHandler(EntityActivatedEvent::Handler& handler) final;
|
||||
void RegisterEntityDeactivatedEventHandler(EntityDeactivatedEvent::Handler& handler) final;
|
||||
void SignalEntityActivated(Entity* entity) final;
|
||||
void SignalEntityDeactivated(Entity* entity) final;
|
||||
bool AddEntity(Entity* entity) override;
|
||||
bool RemoveEntity(Entity* entity) override;
|
||||
bool DeleteEntity(const EntityId& id) override;
|
||||
@@ -369,7 +369,7 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
AZ::TimeUs m_currentTime{ 0 };
|
||||
AZStd::chrono::system_clock::time_point m_currentTime{ AZStd::chrono::system_clock::time_point::max() };
|
||||
float m_deltaTime{ 0.0f };
|
||||
AZStd::unique_ptr<ModuleManager> m_moduleManager;
|
||||
AZStd::unique_ptr<SettingsRegistryInterface> m_settingsRegistry;
|
||||
|
||||
@@ -84,8 +84,9 @@ namespace AZ
|
||||
static TypeId genericComponentWrapperTypeId("{68D358CA-89B9-4730-8BA6-E181DEA28FDE}");
|
||||
for (auto& [componentKey, component] : componentMap)
|
||||
{
|
||||
// if underlying type is genericComponentWrapperTypeId, the template is null and the component should not be addded
|
||||
if (component->GetUnderlyingComponentType() != genericComponentWrapperTypeId)
|
||||
// if the component didn't serialize (i.e. is null) or the underlying type is genericComponentWrapperTypeId, the
|
||||
// template is null and the component should not be addded
|
||||
if (component && (component->GetUnderlyingComponentType() != genericComponentWrapperTypeId))
|
||||
{
|
||||
entityInstance->m_components.emplace_back(component);
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ namespace AZ
|
||||
|
||||
TICK_PRE_RENDER = 750, ///< Suggested tick handler position to update render-related data.
|
||||
|
||||
TICK_RENDER = 800, ///< Suggested tick handler position for rendering.
|
||||
|
||||
TICK_DEFAULT = 1000, ///< Default tick handler position when the handler is constructed.
|
||||
|
||||
TICK_UI = 2000, ///< Suggested tick handler position for UI components.
|
||||
|
||||
@@ -86,6 +86,7 @@ namespace AZ
|
||||
class AssetTreeNodeBase
|
||||
{
|
||||
public:
|
||||
virtual ~AssetTreeNodeBase() = default;
|
||||
virtual const AssetPrimaryInfo* GetAssetPrimaryInfo() const = 0;
|
||||
virtual AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetPrimaryInfo* info) = 0;
|
||||
};
|
||||
@@ -94,6 +95,7 @@ namespace AZ
|
||||
class AssetTreeBase
|
||||
{
|
||||
public:
|
||||
virtual ~AssetTreeBase() = default;
|
||||
virtual AssetTreeNodeBase& GetRoot() = 0;
|
||||
};
|
||||
|
||||
@@ -101,6 +103,7 @@ namespace AZ
|
||||
class AssetAllocationTableBase
|
||||
{
|
||||
public:
|
||||
virtual ~AssetAllocationTableBase() = default;
|
||||
virtual AssetTreeNodeBase* FindAllocation(void* ptr) const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ namespace AZ
|
||||
{
|
||||
}
|
||||
|
||||
~AssetTreeNode() override = default;
|
||||
|
||||
const AssetPrimaryInfo* GetAssetPrimaryInfo() const override
|
||||
{
|
||||
return m_primaryinfo;
|
||||
@@ -67,6 +69,8 @@ namespace AZ
|
||||
class AssetTree : public AssetTreeBase
|
||||
{
|
||||
public:
|
||||
~AssetTree() override = default;
|
||||
|
||||
AssetTreeNodeBase& GetRoot() override
|
||||
{
|
||||
return m_rootAssets;
|
||||
@@ -99,6 +103,7 @@ namespace AZ
|
||||
AllocationTable(mutex_type& mutex) : m_mutex(mutex)
|
||||
{
|
||||
}
|
||||
~AllocationTable() override = default;
|
||||
|
||||
AssetTreeNodeBase* FindAllocation(void* ptr) const override
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace AZ::Debug
|
||||
class BudgetTracker
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(BudgetTracker, "{E14A746D-BFFE-4C02-90FB-4699B79864A5}");
|
||||
AZ_TYPE_INFO(BudgetTracker, "{E14A746D-BFFE-4C02-90FB-4699B79864A5}");
|
||||
static Budget* GetBudgetFromEnvironment(const char* budgetName, uint32_t crc);
|
||||
|
||||
~BudgetTracker();
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/PlatformDef.h>
|
||||
#define AZ_VA_HAS_ARGS(...) ""#__VA_ARGS__[0] != 0
|
||||
|
||||
#include <AzCore/base.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -262,17 +261,18 @@ namespace AZ
|
||||
#define AZ_VerifyWarning(window, expression, ...) AZ_Warning(window, 0 != (expression), __VA_ARGS__)
|
||||
|
||||
#else // !AZ_ENABLE_TRACING
|
||||
#define AZ_Assert(expression, ...)
|
||||
#define AZ_Error(window, expression, ...)
|
||||
#define AZ_ErrorOnce(window, expression, ...)
|
||||
#define AZ_Warning(window, expression, ...)
|
||||
#define AZ_WarningOnce(window, expression, ...)
|
||||
#define AZ_TracePrintf(window, ...)
|
||||
#define AZ_TracePrintfOnce(window, ...)
|
||||
|
||||
#define AZ_Verify(expression, ...) (void)(expression)
|
||||
#define AZ_VerifyError(window, expression, ...) (void)(expression)
|
||||
#define AZ_VerifyWarning(window, expression, ...) (void)(expression)
|
||||
#define AZ_Assert(...) AZ_UNUSED(__VA_ARGS__);
|
||||
#define AZ_Error(...) AZ_UNUSED(__VA_ARGS__);
|
||||
#define AZ_ErrorOnce(...) AZ_UNUSED(__VA_ARGS__);
|
||||
#define AZ_Warning(...) AZ_UNUSED(__VA_ARGS__);
|
||||
#define AZ_WarningOnce(...) AZ_UNUSED(__VA_ARGS__);
|
||||
#define AZ_TracePrintf(...) AZ_UNUSED(__VA_ARGS__);
|
||||
#define AZ_TracePrintfOnce(...) AZ_UNUSED(__VA_ARGS__);
|
||||
|
||||
#define AZ_Verify(...) AZ_UNUSED(__VA_ARGS__);
|
||||
#define AZ_VerifyError(...) AZ_UNUSED(__VA_ARGS__);
|
||||
#define AZ_VerifyWarning(...) AZ_UNUSED(__VA_ARGS__);
|
||||
|
||||
#endif // AZ_ENABLE_TRACING
|
||||
|
||||
|
||||
@@ -28,21 +28,21 @@ namespace AZ
|
||||
protected:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Driller
|
||||
virtual const char* GroupName() const { return "SystemDrillers"; }
|
||||
virtual const char* GetName() const { return "TraceMessagesDriller"; }
|
||||
virtual const char* GetDescription() const { return "Handles all system messages like Assert, Exception, Error, Warning, Printf, etc."; }
|
||||
virtual void Start(const Param* params = NULL, int numParams = 0);
|
||||
virtual void Stop();
|
||||
const char* GroupName() const override { return "SystemDrillers"; }
|
||||
const char* GetName() const override { return "TraceMessagesDriller"; }
|
||||
const char* GetDescription() const override { return "Handles all system messages like Assert, Exception, Error, Warning, Printf, etc."; }
|
||||
void Start(const Param* params = NULL, int numParams = 0) override;
|
||||
void Stop() override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// TraceMessagesDrillerBus
|
||||
/// Triggered when a AZ_Assert failed. This is terminating event! (the code will break, crash).
|
||||
virtual void OnAssert(const char* message);
|
||||
virtual void OnException(const char* message);
|
||||
virtual void OnError(const char* window, const char* message);
|
||||
virtual void OnWarning(const char* window, const char* message);
|
||||
virtual void OnPrintf(const char* window, const char* message);
|
||||
void OnAssert(const char* message) override;
|
||||
void OnException(const char* message) override;
|
||||
void OnError(const char* window, const char* message) override;
|
||||
void OnWarning(const char* window, const char* message) override;
|
||||
void OnPrintf(const char* window, const char* message) override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
} // namespace Debug
|
||||
|
||||
@@ -693,7 +693,7 @@ namespace AZ
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(m_isPooledString == false && m_isPooledStringCrc32 == false, "This stream requires using of a string pool as the string is send only once and afterwards only the Crc32 is used!")
|
||||
AZ_Assert(m_isPooledString == false && m_isPooledStringCrc32 == false, "This stream requires using of a string pool as the string is send only once and afterwards only the Crc32 is used!");
|
||||
}
|
||||
return srcData;
|
||||
}
|
||||
|
||||
@@ -443,7 +443,7 @@ namespace AZ
|
||||
const unsigned char* GetData() const { return m_data.data(); }
|
||||
unsigned int GetDataSize() const { return static_cast<unsigned int>(m_data.size()); }
|
||||
inline void Reset() { m_data.clear(); }
|
||||
virtual void WriteBinary(const void* data, unsigned int dataSize)
|
||||
void WriteBinary(const void* data, unsigned int dataSize) override
|
||||
{
|
||||
m_data.insert(m_data.end(), reinterpret_cast<const unsigned char*>(data), reinterpret_cast<const unsigned char*>(data) + dataSize);
|
||||
}
|
||||
@@ -489,7 +489,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
unsigned int GetDataLeft() const { return static_cast<unsigned int>(m_dataEnd - m_data); }
|
||||
virtual unsigned int ReadBinary(void* data, unsigned int maxDataSize)
|
||||
unsigned int ReadBinary(void* data, unsigned int maxDataSize) override
|
||||
{
|
||||
AZ_Assert(m_data != nullptr, "You must call SetData function, before you can read data!");
|
||||
AZ_Assert(data != nullptr && maxDataSize > 0, "We must have a valid pointer and max data size!");
|
||||
@@ -523,7 +523,7 @@ namespace AZ
|
||||
bool Open(const char* fileName, int mode, int platformFlags = 0);
|
||||
void Close();
|
||||
|
||||
virtual void WriteBinary(const void* data, unsigned int dataSize);
|
||||
void WriteBinary(const void* data, unsigned int dataSize) override;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -540,7 +540,7 @@ namespace AZ
|
||||
DrillerInputFileStream();
|
||||
~DrillerInputFileStream();
|
||||
bool Open(const char* fileName, int mode, int platformFlags = 0);
|
||||
virtual unsigned int ReadBinary(void* data, unsigned int maxDataSize);
|
||||
unsigned int ReadBinary(void* data, unsigned int maxDataSize) override;
|
||||
void Close();
|
||||
};
|
||||
|
||||
|
||||
@@ -1717,6 +1717,7 @@ AZ_POP_DISABLE_WARNING
|
||||
{
|
||||
EBusRouterNode<typename EBus::InterfaceType> m_routerNode;
|
||||
public:
|
||||
virtual ~EBusNestedVersionRouter() = default;
|
||||
template<class Container>
|
||||
void BusRouterConnect(Container& container, int order = 0);
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace AZ
|
||||
|
||||
const char* get_name() const { return m_name; }
|
||||
void set_name(const char* name) { m_name = name; }
|
||||
size_type get_max_size() const { return AZ_CORE_MAX_ALLOCATOR_SIZE; }
|
||||
constexpr size_type max_size() const { return AZ_CORE_MAX_ALLOCATOR_SIZE; }
|
||||
size_type get_allocated_size() const { return 0; }
|
||||
|
||||
bool is_lock_free() { return false; }
|
||||
|
||||
@@ -98,21 +98,21 @@ namespace AZ
|
||||
|
||||
/// Return compressor type id.
|
||||
static AZ::u32 TypeId();
|
||||
virtual AZ::u32 GetTypeId() const { return TypeId(); }
|
||||
AZ::u32 GetTypeId() const override { return TypeId(); }
|
||||
/// Called when we open a stream to Read for the first time. Data contains the first. dataSize <= m_maxHeaderSize.
|
||||
virtual bool ReadHeaderAndData(CompressorStream* stream, AZ::u8* data, unsigned int dataSize);
|
||||
bool ReadHeaderAndData(CompressorStream* stream, AZ::u8* data, unsigned int dataSize) override;
|
||||
/// Called when we are about to start writing to a compressed stream.
|
||||
virtual bool WriteHeaderAndData(CompressorStream* stream);
|
||||
bool WriteHeaderAndData(CompressorStream* stream) override;
|
||||
/// Forwarded function from the Device when we from a compressed stream.
|
||||
virtual SizeType Read(CompressorStream* stream, SizeType byteSize, SizeType offset, void* buffer);
|
||||
SizeType Read(CompressorStream* stream, SizeType byteSize, SizeType offset, void* buffer) override;
|
||||
/// Forwarded function from the Device when we write to a compressed stream.
|
||||
virtual SizeType Write(CompressorStream* stream, SizeType byteSize, const void* data, SizeType offset = SizeType(-1));
|
||||
SizeType Write(CompressorStream* stream, SizeType byteSize, const void* data, SizeType offset = SizeType(-1)) override;
|
||||
/// Write a seek point.
|
||||
virtual bool WriteSeekPoint(CompressorStream* stream);
|
||||
bool WriteSeekPoint(CompressorStream* stream) override;
|
||||
/// Set auto seek point even dataSize bytes.
|
||||
virtual bool StartCompressor(CompressorStream* stream, int compressionLevel, SizeType autoSeekDataSize);
|
||||
bool StartCompressor(CompressorStream* stream, int compressionLevel, SizeType autoSeekDataSize) override;
|
||||
/// Called just before we close the stream. All compression data will be flushed and finalized. (You can't add data afterwards).
|
||||
virtual bool Close(CompressorStream* stream);
|
||||
bool Close(CompressorStream* stream) override;
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -150,9 +150,7 @@ namespace AZ::IO::IStreamerTypes
|
||||
|
||||
private:
|
||||
AZStd::atomic_int m_lockCounter{ 0 };
|
||||
#ifdef AZ_ENABLE_TRACING
|
||||
AZStd::atomic_int m_allocationCounter{ 0 };
|
||||
#endif
|
||||
AZ::IAllocatorAllocate& m_allocator;
|
||||
};
|
||||
|
||||
|
||||
@@ -256,10 +256,24 @@ namespace AZ::IO
|
||||
|
||||
template <typename PathResultType>
|
||||
static constexpr void MakeRelativeTo(PathResultType& pathResult, const AZ::IO::PathView& path, const AZ::IO::PathView& base);
|
||||
template <typename PathResultType>
|
||||
static constexpr void LexicallyNormalInplace(PathResultType& pathResult, const AZ::IO::PathView& path);
|
||||
|
||||
constexpr int compare_string_view(AZStd::string_view other) const;
|
||||
struct PathIterable;
|
||||
//! Returns a structure that provides a view of the path parts which can be used for iteration
|
||||
//! Only the path parts that correspond to creating an normalized path is returned
|
||||
//! This function is useful for returning a "view" into a normalized path without the need
|
||||
//! to allocate memory for the heap
|
||||
static constexpr PathIterable GetNormalPathParts(const AZ::IO::PathView& path) noexcept;
|
||||
// joins the input path to the Path Iterable structure using similiar logic to Path::Append
|
||||
// If the input path is absolute it will replace the current PathIterable otherwise
|
||||
// the input path will be appended to the Path Iterable structure
|
||||
// For example a PathIterable with parts = ['C:', '/', 'foo']
|
||||
// If the path input = 'bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar']
|
||||
// If the path input = 'C:/bar', then the new PathIterable parts = [C:', '/', 'bar']
|
||||
// If the path input = 'C:bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar' ]
|
||||
// If the path input = 'D:bar', then the new PathIterable parts = [D:, 'bar' ]
|
||||
static constexpr void AppendNormalPathParts(PathIterable& pathIterableResult, const AZ::IO::PathView& path) noexcept;
|
||||
|
||||
constexpr int ComparePathView(const PathView& other) const;
|
||||
constexpr AZStd::string_view root_name_view() const;
|
||||
constexpr AZStd::string_view root_directory_view() const;
|
||||
constexpr AZStd::string_view root_path_raw_view() const;
|
||||
@@ -442,14 +456,15 @@ namespace AZ::IO
|
||||
constexpr void swap(BasicPath& rhs) noexcept;
|
||||
|
||||
// native format observers
|
||||
constexpr const string_type& Native() const noexcept;
|
||||
constexpr const string_type& Native() const& noexcept;
|
||||
constexpr const string_type&& Native() const&& noexcept;
|
||||
constexpr const value_type* c_str() const noexcept;
|
||||
constexpr explicit operator string_type() const;
|
||||
|
||||
// Adds support for retrieving a modifiable copy of the underlying string
|
||||
// Any modifications to the string invalidates existing PathIterators
|
||||
constexpr string_type& Native() noexcept;
|
||||
constexpr explicit operator string_type&() noexcept;
|
||||
constexpr string_type& Native() & noexcept;
|
||||
constexpr string_type&& Native() && noexcept;
|
||||
|
||||
//! The string and wstring functions cannot be constexpr until AZStd::basic_string is made constexpr.
|
||||
//! This cannot occur until C++20 as operator new/delete cannot be used within constexpr functions
|
||||
@@ -465,6 +480,8 @@ namespace AZ::IO
|
||||
// compare
|
||||
//! Performs a compare of each of the path parts for equivalence
|
||||
//! Each part of the path is compare using string comparison
|
||||
//! If both *this path and the input path uses the WindowsPathSeparator
|
||||
//! then a non-case sensitive compare is performed
|
||||
//! Ex: Comparing "test/foo" against "test/fop" returns -1;
|
||||
//! Path separators of the contained path string aren't compared
|
||||
//! Ex. Comparing "C:/test\foo" against C:\test/foo" returns 0;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/containers/array.h>
|
||||
#include <AzCore/IO/Path/PathParser.inl>
|
||||
|
||||
namespace AZ::IO
|
||||
{
|
||||
struct PathView::PathIterable
|
||||
{
|
||||
inline static constexpr size_t MaxPathParts = 64;
|
||||
using PartKindPair = AZStd::pair<AZStd::string_view, AZ::IO::parser::PathPartKind>;
|
||||
using PartKindArray = AZStd::array<PartKindPair, MaxPathParts>;
|
||||
constexpr PathIterable() = default;
|
||||
|
||||
[[nodiscard]] constexpr bool empty() const noexcept;
|
||||
constexpr auto size() const noexcept-> size_t;
|
||||
constexpr auto begin() noexcept-> PartKindArray::iterator;
|
||||
constexpr auto begin() const noexcept -> PartKindArray::const_iterator;
|
||||
constexpr auto cbegin() const noexcept -> PartKindArray::const_iterator;
|
||||
constexpr auto end() noexcept -> PartKindArray::iterator;
|
||||
constexpr auto end() const noexcept -> PartKindArray::const_iterator;
|
||||
constexpr auto cend() const noexcept -> PartKindArray::const_iterator;
|
||||
constexpr auto rbegin() noexcept -> PartKindArray::reverse_iterator;
|
||||
constexpr auto rbegin() const noexcept -> PartKindArray::const_reverse_iterator;
|
||||
constexpr auto crbegin() const noexcept -> PartKindArray::const_reverse_iterator;
|
||||
constexpr auto rend() noexcept -> PartKindArray::reverse_iterator;
|
||||
constexpr auto rend() const noexcept -> PartKindArray::const_reverse_iterator;
|
||||
constexpr auto crend() const noexcept -> PartKindArray::const_reverse_iterator;
|
||||
|
||||
[[nodiscard]] constexpr bool IsAbsolute() const noexcept;
|
||||
|
||||
private:
|
||||
template <typename... Args>
|
||||
constexpr PartKindPair& emplace_back(Args&&... args) noexcept;
|
||||
constexpr void pop_back() noexcept;
|
||||
constexpr const PartKindPair& back() const noexcept;
|
||||
constexpr PartKindPair& back() noexcept;
|
||||
|
||||
constexpr const PartKindPair& front() const noexcept;
|
||||
constexpr PartKindPair& front() noexcept;
|
||||
|
||||
constexpr void clear() noexcept;
|
||||
|
||||
friend constexpr auto PathView::GetNormalPathParts(const AZ::IO::PathView&) noexcept -> PathIterable;
|
||||
friend constexpr auto PathView::AppendNormalPathParts(PathIterable& pathIterable, const AZ::IO::PathView&) noexcept -> void;
|
||||
PartKindArray m_parts{};
|
||||
size_t m_size{};
|
||||
};
|
||||
|
||||
// public
|
||||
[[nodiscard]] constexpr auto PathView::PathIterable::empty() const noexcept -> bool
|
||||
{
|
||||
return m_size == 0;
|
||||
}
|
||||
constexpr auto PathView::PathIterable::size() const noexcept -> size_t
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
constexpr auto PathView::PathIterable::begin() noexcept -> PartKindArray::iterator
|
||||
{
|
||||
return m_parts.begin();
|
||||
}
|
||||
constexpr auto PathView::PathIterable::begin() const noexcept -> PartKindArray::const_iterator
|
||||
{
|
||||
return m_parts.begin();
|
||||
}
|
||||
constexpr auto PathView::PathIterable::cbegin() const noexcept -> PartKindArray::const_iterator
|
||||
{
|
||||
return begin();
|
||||
}
|
||||
constexpr auto PathView::PathIterable::end() noexcept -> PartKindArray::iterator
|
||||
{
|
||||
return begin() + size();
|
||||
}
|
||||
constexpr auto PathView::PathIterable::end() const noexcept -> PartKindArray::const_iterator
|
||||
{
|
||||
return begin() + size();
|
||||
}
|
||||
constexpr auto PathView::PathIterable::cend() const noexcept -> PartKindArray::const_iterator
|
||||
{
|
||||
return end();
|
||||
}
|
||||
constexpr auto PathView::PathIterable::rbegin() noexcept -> PartKindArray::reverse_iterator
|
||||
{
|
||||
return PartKindArray::reverse_iterator(begin() + size());
|
||||
}
|
||||
constexpr auto PathView::PathIterable::rbegin() const noexcept -> PartKindArray::const_reverse_iterator
|
||||
{
|
||||
return PartKindArray::const_reverse_iterator(begin() + size());
|
||||
}
|
||||
constexpr auto PathView::PathIterable::crbegin() const noexcept -> PartKindArray::const_reverse_iterator
|
||||
{
|
||||
return rbegin();
|
||||
}
|
||||
constexpr auto PathView::PathIterable::rend() noexcept -> PartKindArray::reverse_iterator
|
||||
{
|
||||
return PartKindArray::reverse_iterator(begin());
|
||||
}
|
||||
constexpr auto PathView::PathIterable::rend() const noexcept -> PartKindArray::const_reverse_iterator
|
||||
{
|
||||
return PartKindArray::const_reverse_iterator(begin());
|
||||
}
|
||||
constexpr auto PathView::PathIterable::crend() const noexcept -> PartKindArray::const_reverse_iterator
|
||||
{
|
||||
return rend();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto PathView::PathIterable::IsAbsolute() const noexcept -> bool
|
||||
{
|
||||
return !empty() && (front().second == parser::PathPartKind::PK_RootSep
|
||||
|| (size() > 1 && front().second == parser::PathPartKind::PK_RootName && m_parts[1].second == parser::PathPartKind::PK_RootSep));
|
||||
}
|
||||
|
||||
// private
|
||||
template <typename... Args>
|
||||
constexpr auto PathView::PathIterable::emplace_back(Args&&... args) noexcept -> PartKindPair&
|
||||
{
|
||||
AZ_Assert(m_size < MaxPathParts, "PathIterable cannot be made out of a path with more than %zu parts", MaxPathParts);
|
||||
m_parts[m_size++] = PartKindPair{ AZStd::forward<Args>(args)... };
|
||||
return back();
|
||||
}
|
||||
constexpr auto PathView::PathIterable::pop_back() noexcept -> void
|
||||
{
|
||||
AZ_Assert(m_size > 0, "Cannot pop_back() from a PathIterable with 0 parts");
|
||||
--m_size;
|
||||
}
|
||||
constexpr auto PathView::PathIterable::back() const noexcept -> const PartKindPair&
|
||||
{
|
||||
AZ_Assert(!empty(), "back() was invoked on PathIterable with 0 parts");
|
||||
return m_parts[m_size - 1];
|
||||
}
|
||||
constexpr auto PathView::PathIterable::back() noexcept -> PartKindPair&
|
||||
{
|
||||
AZ_Assert(!empty(), "back() was invoked on PathIterable with 0 parts");
|
||||
return m_parts[m_size - 1];
|
||||
}
|
||||
|
||||
constexpr auto PathView::PathIterable::front() const noexcept -> const PartKindPair&
|
||||
{
|
||||
AZ_Assert(!empty(), "front() was invoked on PathIterable with 0 parts");
|
||||
return m_parts[0];
|
||||
}
|
||||
constexpr auto PathView::PathIterable::front() noexcept -> PartKindPair&
|
||||
{
|
||||
AZ_Assert(!empty(), "front() was invoked on PathIterable with 0 parts");
|
||||
return m_parts[0];
|
||||
}
|
||||
|
||||
constexpr auto PathView::PathIterable::clear() noexcept -> void
|
||||
{
|
||||
m_size = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,750 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/AzCore_Traits_Platform.h>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
|
||||
namespace AZ::IO::Internal
|
||||
{
|
||||
constexpr bool IsSeparator(const char elem)
|
||||
{
|
||||
return elem == '/' || elem == '\\';
|
||||
}
|
||||
template <typename InputIt, typename EndIt, typename = AZStd::enable_if_t<AZStd::Internal::is_input_iterator_v<InputIt>>>
|
||||
static constexpr bool HasDrivePrefix(InputIt first, EndIt last)
|
||||
{
|
||||
size_t prefixSize = AZStd::distance(first, last);
|
||||
if (prefixSize < 2 || *AZStd::next(first, 1) != ':')
|
||||
{
|
||||
// Drive prefix must be at least two characters and have a colon for the second character
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr size_t ValidDrivePrefixRange = 26;
|
||||
// Uppercase the drive letter by bitwise and'ing out the the 2^5 bit
|
||||
unsigned char driveLetter = static_cast<unsigned char>(*first);
|
||||
|
||||
driveLetter &= 0b1101'1111;
|
||||
// normalize the character value in the range of A-Z -> 0-25
|
||||
driveLetter -= 'A';
|
||||
return driveLetter < ValidDrivePrefixRange;
|
||||
}
|
||||
|
||||
static constexpr bool HasDrivePrefix(AZStd::string_view prefix)
|
||||
{
|
||||
return HasDrivePrefix(prefix.begin(), prefix.end());
|
||||
}
|
||||
|
||||
//! Returns an iterator past the end of the consumed root name
|
||||
//! Windows root names can have include drive letter within them
|
||||
template <typename InputIt>
|
||||
constexpr auto ConsumeRootName(InputIt entryBeginIter, InputIt entryEndIter, const char preferredSeparator)
|
||||
-> AZStd::enable_if_t<AZStd::Internal::is_forward_iterator_v<InputIt>, InputIt>
|
||||
{
|
||||
if (preferredSeparator == PosixPathSeparator)
|
||||
{
|
||||
// If the preferred separator is forward slash the parser is in posix path
|
||||
// parsing mode, which doesn't have a root name,
|
||||
// unless we're on a posix platform that uses a custom path root separator
|
||||
#if defined(AZ_TRAIT_CUSTOM_PATH_ROOT_SEPARATOR)
|
||||
const AZStd::string_view path{ entryBeginIter, entryEndIter };
|
||||
const auto positionOfPathSeparator = path.find(AZ_TRAIT_CUSTOM_PATH_ROOT_SEPARATOR);
|
||||
if (positionOfPathSeparator != AZStd::string_view::npos)
|
||||
{
|
||||
return AZStd::next(entryBeginIter, positionOfPathSeparator + 1);
|
||||
}
|
||||
#endif
|
||||
return entryBeginIter;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Information for GetRootName has been gathered from Microsoft <filesystem> header
|
||||
// Below are examples of paths and what there root-name will return
|
||||
// "/" - returns ""
|
||||
// "foo/" - returns ""
|
||||
// "C:DriveRelative" - returns "C:"
|
||||
// "C:\\DriveAbsolute" - returns "C:"
|
||||
// "C://DriveAbsolute" - returns "C:"
|
||||
// "\\server\share" - returns "\\server"
|
||||
// The following paths are based on the UNC specification to work with paths longer than the 260 character path limit
|
||||
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN#maximum-path-length-limitation
|
||||
// \\?\device - returns "\\?"
|
||||
// \??\device - returns "\??"
|
||||
// \\.\device - returns "\\."
|
||||
|
||||
|
||||
AZStd::string_view path{ entryBeginIter, entryEndIter };
|
||||
|
||||
if (path.size() < 2)
|
||||
{
|
||||
// A root name is either <drive letter><colon> or a network path
|
||||
// therefore it has a least two characters
|
||||
return entryBeginIter;
|
||||
}
|
||||
|
||||
if (HasDrivePrefix(path))
|
||||
{
|
||||
// If the path has a drive prefix, then it has a root name of <driver letter><colon>
|
||||
return AZStd::next(entryBeginIter, 2);
|
||||
}
|
||||
|
||||
if (!Internal::IsSeparator(path[0]))
|
||||
{
|
||||
// At this point all other root names start with a path separator
|
||||
return entryBeginIter;
|
||||
}
|
||||
|
||||
// Check if the path has the form of "\\?\, "\??\" or "\\.\"
|
||||
const bool pathInUncForm = path.size() >= 4 && Internal::IsSeparator(path[3])
|
||||
&& (path.size() == 4 || !Internal::IsSeparator(path[4]));
|
||||
if (pathInUncForm)
|
||||
{
|
||||
// \\?\<0 or more> or \\.\$<zero or more>
|
||||
const bool slashQuestionMark = Internal::IsSeparator(path[1]) && (path[2] == '?' || path[2] == '.');
|
||||
// \??\<0 or more>
|
||||
const bool questionMarkTwice = path[1] == '?' && path[2] == '?';
|
||||
if (slashQuestionMark || questionMarkTwice)
|
||||
{
|
||||
// Return the root value root slash - i.e "\\?"
|
||||
return AZStd::next(entryBeginIter, 3);
|
||||
}
|
||||
}
|
||||
|
||||
if (path.size() >= 3 && Internal::IsSeparator(path[1]) && !Internal::IsSeparator(path[2]))
|
||||
{
|
||||
// Find the next path separator for network paths that have the form of \\server\share
|
||||
constexpr AZStd::string_view PathSeparators = { "/\\" };
|
||||
size_t nextPathSeparatorOffset = path.find_first_of(PathSeparators, 3);
|
||||
return AZStd::next(entryBeginIter, nextPathSeparatorOffset != AZStd::string_view::npos ? nextPathSeparatorOffset : path.size());
|
||||
}
|
||||
|
||||
return entryBeginIter;
|
||||
}
|
||||
}
|
||||
|
||||
//! Returns an iterator past the end of the consumed path separator(s)
|
||||
template <typename InputIt>
|
||||
constexpr InputIt ConsumeSeparator(InputIt entryBeginIter, InputIt entryEndIter) noexcept
|
||||
{
|
||||
return AZStd::find_if_not(entryBeginIter, entryEndIter, [](const char elem) { return Internal::IsSeparator(elem); });
|
||||
}
|
||||
|
||||
//! Returns an iterator past the end of the consumed filename
|
||||
template <typename InputIt>
|
||||
constexpr InputIt ConsumeName(InputIt entryBeginIter, InputIt entryEndIter) noexcept
|
||||
{
|
||||
return AZStd::find_if(entryBeginIter, entryEndIter, [](const char elem) { return Internal::IsSeparator(elem); });
|
||||
}
|
||||
|
||||
//! Check if a path is absolute on a OS basis
|
||||
//! If the preferred separator is '/' just checks if the path starts with a '/
|
||||
//! Otherwise a check for a Windows absolute path occurs
|
||||
//! Windows absolute paths can include a RootName
|
||||
template <typename InputIt, typename EndIt, typename = AZStd::enable_if_t<AZStd::Internal::is_input_iterator_v<InputIt>>>
|
||||
static constexpr bool IsAbsolute(InputIt first, EndIt last, const char preferredSeparator)
|
||||
{
|
||||
size_t pathSize = AZStd::distance(first, last);
|
||||
|
||||
// If the preferred separator is a forward slash
|
||||
// than an absolute path is simply one that starts with a forward slash,
|
||||
// unless we're on a posix platform that uses a custom path root separator
|
||||
if (preferredSeparator == PosixPathSeparator)
|
||||
{
|
||||
#if defined(AZ_TRAIT_CUSTOM_PATH_ROOT_SEPARATOR)
|
||||
const AZStd::string_view path{ first, last };
|
||||
return path.find(AZ_TRAIT_CUSTOM_PATH_ROOT_SEPARATOR) != AZStd::string_view::npos;
|
||||
#else
|
||||
return pathSize > 0 && IsSeparator(*first);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Internal::HasDrivePrefix(first, last))
|
||||
{
|
||||
// If a windows path ends starts with C:foo it is a root relative path
|
||||
// A path is absolute root absolute on windows if it starts with <drive_letter><colon><path_separator>
|
||||
return pathSize > 2 && Internal::IsSeparator(*AZStd::next(first, 2));
|
||||
}
|
||||
|
||||
return first != ConsumeRootName(first, last, preferredSeparator);
|
||||
}
|
||||
}
|
||||
static constexpr bool IsAbsolute(AZStd::string_view pathView, const char preferredSeparator)
|
||||
{
|
||||
// Uses the template preferred to branch on the absolute path check
|
||||
// logic
|
||||
return IsAbsolute(pathView.begin(), pathView.end(), preferredSeparator);
|
||||
}
|
||||
|
||||
// Compares path segments using either Posix or Windows path rules based on the exactCaseCompare option
|
||||
static int ComparePathSegment(AZStd::string_view left, AZStd::string_view right, bool exactCaseCompare)
|
||||
{
|
||||
const size_t maxCharsToCompare = (AZStd::min)(left.size(), right.size());
|
||||
|
||||
int charCompareResult = exactCaseCompare
|
||||
? maxCharsToCompare ? strncmp(left.data(), right.data(), maxCharsToCompare) : 0
|
||||
: maxCharsToCompare ? azstrnicmp(left.data(), right.data(), maxCharsToCompare) : 0;
|
||||
return charCompareResult == 0
|
||||
? static_cast<int>(aznumeric_cast<ptrdiff_t>(left.size()) - aznumeric_cast<ptrdiff_t>(right.size()))
|
||||
: charCompareResult;
|
||||
}
|
||||
}
|
||||
|
||||
//! PathParser implementation
|
||||
//! For internal use only
|
||||
namespace AZ::IO::parser
|
||||
{
|
||||
using parser_path_type = PathView;
|
||||
using string_view_pair = AZStd::pair<AZStd::string_view, AZStd::string_view>;
|
||||
using PosPtr = const typename parser_path_type::value_type*;
|
||||
|
||||
enum ParserState : uint8_t
|
||||
{
|
||||
// Zero is a special sentinel value used by default constructed iterators.
|
||||
PS_BeforeBegin = PathIterator<PathView>::BeforeBegin,
|
||||
PS_InRootName = PathIterator<PathView>::InRootName,
|
||||
PS_InRootDir = PathIterator<PathView>::InRootDir,
|
||||
PS_InFilenames = PathIterator<PathView>::InFilenames,
|
||||
PS_AtEnd = PathIterator<PathView>::AtEnd
|
||||
};
|
||||
|
||||
struct PathParser
|
||||
{
|
||||
AZStd::string_view m_path_view;
|
||||
AZStd::string_view m_path_raw_entry;
|
||||
ParserState m_parser_state{};
|
||||
const char m_preferred_separator{ AZ_TRAIT_OS_PATH_SEPARATOR };
|
||||
|
||||
constexpr PathParser(AZStd::string_view path, ParserState state, const char preferredSeparator) noexcept
|
||||
: m_path_view(path)
|
||||
, m_parser_state(state)
|
||||
, m_preferred_separator(preferredSeparator)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr PathParser(AZStd::string_view path, AZStd::string_view entry, ParserState state, const char preferredSeparator) noexcept
|
||||
: m_path_view(path)
|
||||
, m_path_raw_entry(entry)
|
||||
, m_parser_state(static_cast<ParserState>(state))
|
||||
, m_preferred_separator(preferredSeparator)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr static PathParser CreateBegin(AZStd::string_view path, const char preferredSeparator) noexcept
|
||||
{
|
||||
PathParser pathParser(path, PS_BeforeBegin, preferredSeparator);
|
||||
pathParser.Increment();
|
||||
return pathParser;
|
||||
}
|
||||
|
||||
constexpr static PathParser CreateEnd(AZStd::string_view path, const char preferredSeparator) noexcept
|
||||
{
|
||||
PathParser pathParser(path, PS_AtEnd, preferredSeparator);
|
||||
return pathParser;
|
||||
}
|
||||
|
||||
constexpr PosPtr Peek() const noexcept
|
||||
{
|
||||
auto tokenEnd = getNextTokenStartPos();
|
||||
auto End = m_path_view.end();
|
||||
return tokenEnd == End ? nullptr : tokenEnd;
|
||||
}
|
||||
|
||||
constexpr void Increment() noexcept
|
||||
{
|
||||
const PosPtr pathEnd = m_path_view.end();
|
||||
const PosPtr currentPathEntry = getNextTokenStartPos();
|
||||
if (currentPathEntry == pathEnd)
|
||||
{
|
||||
return MakeState(PS_AtEnd);
|
||||
}
|
||||
|
||||
switch (m_parser_state)
|
||||
{
|
||||
case PS_BeforeBegin:
|
||||
{
|
||||
/*
|
||||
* First the determine if the path contains only a root-name such as "C:" or is a filename such as "foo"
|
||||
* root-relative path(Windows only) - C:foo
|
||||
* root-absolute path - C:\foo
|
||||
* root-absolute path - /foo
|
||||
* relative path - foo
|
||||
*
|
||||
* Try to consume the root-name then the root directory to determine if path entry
|
||||
* being parsed is a root-name or filename
|
||||
* The State transitions from BeforeBegin are
|
||||
* "C:", "\\server\", "\\?\", "\??\", "\\.\" -> Root Name
|
||||
* "/", "\" -> Root Directory
|
||||
* "path/foo", "foo" -> Filename
|
||||
*/
|
||||
auto rootNameEnd = Internal::ConsumeRootName(currentPathEntry, pathEnd, m_preferred_separator);
|
||||
if (currentPathEntry != rootNameEnd)
|
||||
{
|
||||
// Transition to the Root Name state
|
||||
return MakeState(PS_InRootName, currentPathEntry, rootNameEnd);
|
||||
}
|
||||
[[fallthrough]];
|
||||
}
|
||||
case PS_InRootName:
|
||||
{
|
||||
auto rootDirEnd = Internal::ConsumeSeparator(currentPathEntry, pathEnd);
|
||||
if (currentPathEntry != rootDirEnd)
|
||||
{
|
||||
// Transition to Root Directory state
|
||||
return MakeState(PS_InRootDir, currentPathEntry, rootDirEnd);
|
||||
}
|
||||
[[fallthrough]];
|
||||
}
|
||||
case PS_InRootDir:
|
||||
{
|
||||
auto filenameEnd = Internal::ConsumeName(currentPathEntry, pathEnd);
|
||||
if (currentPathEntry != filenameEnd)
|
||||
{
|
||||
return MakeState(PS_InFilenames, currentPathEntry, filenameEnd);
|
||||
}
|
||||
[[fallthrough]];
|
||||
}
|
||||
case PS_InFilenames:
|
||||
{
|
||||
auto separatorEnd = Internal::ConsumeSeparator(currentPathEntry, pathEnd);
|
||||
if (separatorEnd != pathEnd)
|
||||
{
|
||||
// find the end of the current filename entry
|
||||
auto filenameEnd = Internal::ConsumeName(separatorEnd, pathEnd);
|
||||
return MakeState(PS_InFilenames, separatorEnd, filenameEnd);
|
||||
}
|
||||
// If after consuming the separator that path entry is at the end iterator
|
||||
// move the path state to AtEnd
|
||||
return MakeState(PS_AtEnd);
|
||||
}
|
||||
case PS_AtEnd:
|
||||
AZ_Assert(false, "Path Parser cannot be incremented when it is in the AtEnd state");
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void Decrement() noexcept
|
||||
{
|
||||
auto pathStart = m_path_view.begin();
|
||||
auto currentPathEntry = getCurrentTokenStartPos();
|
||||
|
||||
if (currentPathEntry == pathStart)
|
||||
{
|
||||
// we're decrementing the begin
|
||||
return MakeState(PS_BeforeBegin);
|
||||
}
|
||||
switch (m_parser_state)
|
||||
{
|
||||
case PS_AtEnd:
|
||||
{
|
||||
/*
|
||||
* First the determine if the path contains only a root-name such as "C:" or is a filename such as "foo"
|
||||
* root-relative path(Windows only) - C:foo
|
||||
* root-absolute path - C:\foo
|
||||
* root-absolute path - /foo
|
||||
* relative path - foo
|
||||
* Try to consume the root-name then the root directory to determine if path entry
|
||||
* being parsed is a root-name or filename
|
||||
* The State transitions from AtEnd are
|
||||
* "/path/foo/", "foo/", "C:foo\", "C:\foo\" -> Trailing Separator
|
||||
* "/path/foo", "foo", "C:foo", "C:\foo" -> Filename
|
||||
* "/", "C:\" or "\\server\" -> Root Directory
|
||||
* "C:", "\\server", "\\?", "\??", "\\." -> Root Name
|
||||
*/
|
||||
auto rootNameEnd = Internal::ConsumeRootName(pathStart, currentPathEntry, m_preferred_separator);
|
||||
if (pathStart != rootNameEnd && currentPathEntry == rootNameEnd)
|
||||
{
|
||||
// Transition to the Root Name state
|
||||
return MakeState(PS_InRootName, pathStart, currentPathEntry);
|
||||
}
|
||||
|
||||
auto rootDirEnd = Internal::ConsumeSeparator(rootNameEnd, currentPathEntry);
|
||||
if (rootNameEnd != rootDirEnd && currentPathEntry == rootDirEnd)
|
||||
{
|
||||
// Transition to Root Directory state
|
||||
return MakeState(PS_InRootDir, rootNameEnd, currentPathEntry);
|
||||
}
|
||||
|
||||
auto filenameEnd = currentPathEntry;
|
||||
if (Internal::IsSeparator(*(filenameEnd - 1)))
|
||||
{
|
||||
// The last character a path separator that isn't root directory
|
||||
// consume all the preceding path separators
|
||||
filenameEnd = Internal::ConsumeSeparator(AZStd::make_reverse_iterator(filenameEnd),
|
||||
AZStd::make_reverse_iterator(rootDirEnd)).base();
|
||||
}
|
||||
|
||||
// The previous state will be Filename, so the beginning of the filename is searched found
|
||||
auto filenameBegin = Internal::ConsumeName(AZStd::make_reverse_iterator(filenameEnd),
|
||||
AZStd::make_reverse_iterator(rootDirEnd)).base();
|
||||
return MakeState(PS_InFilenames, filenameBegin, filenameEnd);
|
||||
}
|
||||
case PS_InFilenames:
|
||||
{
|
||||
/* The State transitions from Filename are
|
||||
* "/path/foo" -> Filename
|
||||
* ^
|
||||
* "C:\foo" -> Root Directory
|
||||
* ^
|
||||
* "C:foo" -> Root Name
|
||||
* ^
|
||||
* "foo" -> This case has been taken care of by the current path entry != path start check
|
||||
* ^
|
||||
*/
|
||||
auto rootNameEnd = Internal::ConsumeRootName(pathStart, currentPathEntry, m_preferred_separator);
|
||||
if (pathStart != rootNameEnd && currentPathEntry == rootNameEnd)
|
||||
{
|
||||
// Transition to the Root Name state
|
||||
return MakeState(PS_InRootName, pathStart, rootNameEnd);
|
||||
}
|
||||
|
||||
auto rootDirEnd = Internal::ConsumeSeparator(rootNameEnd, currentPathEntry);
|
||||
if (rootNameEnd != rootDirEnd && currentPathEntry == rootDirEnd)
|
||||
{
|
||||
// Transition to Root Directory state
|
||||
return MakeState(PS_InRootDir, rootNameEnd, rootDirEnd);
|
||||
}
|
||||
// The previous state will be Filename again, so first the end of that filename is found
|
||||
// proceeded by finding the beginning of that filename
|
||||
auto filenameEnd = Internal::ConsumeSeparator(AZStd::make_reverse_iterator(currentPathEntry),
|
||||
AZStd::make_reverse_iterator(rootDirEnd)).base();
|
||||
auto filenameBegin = Internal::ConsumeName(AZStd::make_reverse_iterator(filenameEnd),
|
||||
AZStd::make_reverse_iterator(rootDirEnd)).base();
|
||||
return MakeState(PS_InFilenames, filenameBegin, filenameEnd);
|
||||
}
|
||||
case PS_InRootDir:
|
||||
{
|
||||
/* The State transitions from Root Directory are
|
||||
* "C:\" "\\server\", "\\?\", "\??\", "\\.\" -> Root Name
|
||||
* ^ ^ ^ ^ ^
|
||||
* "/" -> This case has been taken care of by the current path entry != path start check
|
||||
* ^
|
||||
*/
|
||||
return MakeState(PS_InRootName, pathStart, currentPathEntry);
|
||||
}
|
||||
case PS_InRootName:
|
||||
// The only valid state transition from Root Name is BeforeBegin
|
||||
return MakeState(PS_BeforeBegin);
|
||||
case PS_BeforeBegin:
|
||||
AZ_Assert(false, "Path Parser cannot be decremented when it is in the BeforeBegin State");
|
||||
}
|
||||
}
|
||||
|
||||
//! Return a view of the current element in the path processor state
|
||||
constexpr AZStd::string_view operator*() const noexcept
|
||||
{
|
||||
switch (m_parser_state)
|
||||
{
|
||||
case PS_BeforeBegin:
|
||||
[[fallthrough]];
|
||||
case PS_AtEnd:
|
||||
[[fallthrough]];
|
||||
case PS_InRootDir:
|
||||
return m_preferred_separator == '/' ? "/" : "\\";
|
||||
case PS_InRootName:
|
||||
case PS_InFilenames:
|
||||
return m_path_raw_entry;
|
||||
default:
|
||||
AZ_Assert(false, "Path Parser is in an invalid state");
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr explicit operator bool() const noexcept
|
||||
{
|
||||
return m_parser_state != PS_BeforeBegin && m_parser_state != PS_AtEnd;
|
||||
}
|
||||
|
||||
constexpr PathParser& operator++() noexcept
|
||||
{
|
||||
Increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr PathParser& operator--() noexcept
|
||||
{
|
||||
Decrement();
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr bool AtEnd() const noexcept
|
||||
{
|
||||
return m_parser_state == PS_AtEnd;
|
||||
}
|
||||
|
||||
constexpr bool InRootDir() const noexcept
|
||||
{
|
||||
return m_parser_state == PS_InRootDir;
|
||||
}
|
||||
|
||||
constexpr bool InRootName() const noexcept
|
||||
{
|
||||
return m_parser_state == PS_InRootName;
|
||||
}
|
||||
|
||||
constexpr bool InRootPath() const noexcept
|
||||
{
|
||||
return InRootName() || InRootDir();
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr void MakeState(ParserState newState, typename AZStd::string_view::iterator start, typename AZStd::string_view::iterator end) noexcept
|
||||
{
|
||||
m_parser_state = newState;
|
||||
m_path_raw_entry = AZStd::string_view(start, end);
|
||||
}
|
||||
constexpr void MakeState(ParserState newState) noexcept
|
||||
{
|
||||
m_parser_state = newState;
|
||||
m_path_raw_entry = {};
|
||||
}
|
||||
|
||||
//! Return a pointer to the first character after the currently lexed element.
|
||||
constexpr typename AZStd::string_view::iterator getNextTokenStartPos() const noexcept
|
||||
{
|
||||
switch (m_parser_state)
|
||||
{
|
||||
case PS_BeforeBegin:
|
||||
return m_path_view.begin();
|
||||
case PS_InRootName:
|
||||
case PS_InRootDir:
|
||||
case PS_InFilenames:
|
||||
return m_path_raw_entry.end();
|
||||
case PS_AtEnd:
|
||||
return m_path_view.end();
|
||||
default:
|
||||
AZ_Assert(false, "Path Parser is in an invalid state");
|
||||
}
|
||||
return m_path_view.end();
|
||||
}
|
||||
|
||||
//! Return a pointer to the first character in the currently lexed element.
|
||||
constexpr typename AZStd::string_view::iterator getCurrentTokenStartPos() const noexcept
|
||||
{
|
||||
switch (m_parser_state)
|
||||
{
|
||||
case PS_BeforeBegin:
|
||||
case PS_InRootName:
|
||||
return m_path_view.begin();
|
||||
case PS_InRootDir:
|
||||
case PS_InFilenames:
|
||||
return m_path_raw_entry.begin();
|
||||
case PS_AtEnd:
|
||||
return m_path_view.end();
|
||||
default:
|
||||
AZ_Assert(false, "Path Parser is in an invalid state");
|
||||
}
|
||||
return m_path_view.end();
|
||||
}
|
||||
};
|
||||
|
||||
constexpr string_view_pair SeparateFilename(const AZStd::string_view& srcView)
|
||||
{
|
||||
if (srcView == "." || srcView == ".." || srcView.empty())
|
||||
{
|
||||
return string_view_pair{ srcView, "" };
|
||||
}
|
||||
auto pos = srcView.find_last_of('.');
|
||||
if (pos == AZStd::string_view::npos || pos == 0)
|
||||
{
|
||||
return string_view_pair{ srcView, AZStd::string_view{} };
|
||||
}
|
||||
return string_view_pair{ srcView.substr(0, pos), srcView.substr(pos) };
|
||||
}
|
||||
|
||||
|
||||
// path part consumption
|
||||
constexpr bool ConsumeRootName(PathParser* pathParser)
|
||||
{
|
||||
static_assert(PS_BeforeBegin == 1 && PS_InRootName == 2,
|
||||
"PathParser must be in state before begin or in the root name in order to consume the root name");
|
||||
while (pathParser->m_parser_state <= PS_InRootName)
|
||||
{
|
||||
++(*pathParser);
|
||||
}
|
||||
return pathParser->m_parser_state == PS_AtEnd;
|
||||
}
|
||||
constexpr bool ConsumeRootDir(PathParser* pathParser)
|
||||
{
|
||||
static_assert(PS_BeforeBegin == 1 && PS_InRootName == 2 && PS_InRootDir == 3,
|
||||
"PathParser must be in state before begin, in the root name or in the root directory in order to consume the root directory");
|
||||
while (pathParser->m_parser_state <= PS_InRootDir)
|
||||
{
|
||||
++(*pathParser);
|
||||
}
|
||||
return pathParser->m_parser_state == PS_AtEnd;
|
||||
}
|
||||
|
||||
// path.comparisons
|
||||
constexpr int CompareRootName(PathParser* lhsPathParser, PathParser* rhsPathParser)
|
||||
{
|
||||
if (!lhsPathParser->InRootName() && !rhsPathParser->InRootName())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto GetRootName = [](PathParser* pathParser) constexpr -> AZStd::string_view
|
||||
{
|
||||
return pathParser->InRootName() ? **pathParser : "";
|
||||
};
|
||||
|
||||
const bool exactCaseCompare = lhsPathParser->m_preferred_separator == PosixPathSeparator
|
||||
|| rhsPathParser->m_preferred_separator == PosixPathSeparator;
|
||||
int res = Internal::ComparePathSegment(GetRootName(lhsPathParser), GetRootName(rhsPathParser), exactCaseCompare);
|
||||
ConsumeRootName(lhsPathParser);
|
||||
ConsumeRootName(rhsPathParser);
|
||||
return res;
|
||||
}
|
||||
constexpr int CompareRootDir(PathParser* lhsPathParser, PathParser* rhsPathParser)
|
||||
{
|
||||
if (!lhsPathParser->InRootDir() && rhsPathParser->InRootDir())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (lhsPathParser->InRootDir() && !rhsPathParser->InRootDir())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsumeRootDir(lhsPathParser);
|
||||
ConsumeRootDir(rhsPathParser);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
constexpr int CompareRelative(PathParser* lhsPathParserPtr, PathParser* rhsPathParserPtr)
|
||||
{
|
||||
auto& lhsPathParser = *lhsPathParserPtr;
|
||||
auto& rhsPathParser = *rhsPathParserPtr;
|
||||
|
||||
const bool exactCaseCompare = lhsPathParser.m_preferred_separator == PosixPathSeparator
|
||||
|| rhsPathParser.m_preferred_separator == PosixPathSeparator;
|
||||
while (lhsPathParser && rhsPathParser)
|
||||
{
|
||||
if (int res = Internal::ComparePathSegment(*lhsPathParser, *rhsPathParser, exactCaseCompare);
|
||||
res != 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
++lhsPathParser;
|
||||
++rhsPathParser;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
constexpr int CompareEndState(PathParser* lhsPathParser, PathParser* rhsPathParser)
|
||||
{
|
||||
if (lhsPathParser->AtEnd() && !rhsPathParser->AtEnd())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (!lhsPathParser->AtEnd() && rhsPathParser->AtEnd())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//path.hash
|
||||
/// Path is using FNV-1a algorithm 64 bit version.
|
||||
inline size_t HashSegment(AZStd::string_view pathSegment, bool hashExactPath)
|
||||
{
|
||||
size_t hash = 14695981039346656037ULL;
|
||||
constexpr size_t fnvPrime = 1099511628211ULL;
|
||||
|
||||
for (const char first : pathSegment)
|
||||
{
|
||||
hash ^= static_cast<size_t>(hashExactPath ? first : tolower(first));
|
||||
hash *= fnvPrime;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
constexpr size_t HashPath(PathParser& pathParser)
|
||||
{
|
||||
size_t hash_value = 0;
|
||||
const bool hashExactPath = pathParser.m_preferred_separator == AZ::IO::PosixPathSeparator;
|
||||
while (pathParser)
|
||||
{
|
||||
switch (pathParser.m_parser_state)
|
||||
{
|
||||
case PS_InRootName:
|
||||
case PS_InFilenames:
|
||||
AZStd::hash_combine(hash_value, HashSegment(*pathParser, hashExactPath));
|
||||
break;
|
||||
case PS_InRootDir:
|
||||
// Only hash the PosixPathSeparator when a root directory is seen
|
||||
// This makes the hash consistent for root directories path of C:\ and C:/
|
||||
AZStd::hash_combine(hash_value, HashSegment("/", hashExactPath));
|
||||
break;
|
||||
default:
|
||||
// The BeforeBegin and AtEnd states contain no segments to hash
|
||||
break;
|
||||
}
|
||||
++pathParser;
|
||||
}
|
||||
return hash_value;
|
||||
}
|
||||
|
||||
constexpr int DetermineLexicalElementCount(PathParser pathParser)
|
||||
{
|
||||
int count = 0;
|
||||
for (; pathParser; ++pathParser)
|
||||
{
|
||||
auto pathElement = *pathParser;
|
||||
if (pathElement == "..")
|
||||
{
|
||||
--count;
|
||||
}
|
||||
else if (pathElement != "." && pathElement != "")
|
||||
{
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
enum class PathPartKind : uint8_t
|
||||
{
|
||||
PK_None,
|
||||
PK_RootName,
|
||||
PK_RootSep,
|
||||
PK_Filename,
|
||||
PK_Dot,
|
||||
PK_DotDot,
|
||||
};
|
||||
|
||||
constexpr PathPartKind ClassifyPathPart(const PathParser& parser)
|
||||
{
|
||||
// Check each parser state to determine the PathPartKind
|
||||
if (parser.m_parser_state == PS_InRootDir)
|
||||
{
|
||||
return PathPartKind::PK_RootSep;
|
||||
}
|
||||
if (parser.m_parser_state == PS_InRootName)
|
||||
{
|
||||
return PathPartKind::PK_RootName;
|
||||
}
|
||||
|
||||
// Fallback to checking parser pathEntry view value
|
||||
// to determine if the special "." or ".." values are being used
|
||||
AZStd::string_view pathPart = *parser;
|
||||
if (pathPart == ".")
|
||||
{
|
||||
return PathPartKind::PK_Dot;
|
||||
}
|
||||
if (pathPart == "..")
|
||||
{
|
||||
return PathPartKind::PK_DotDot;
|
||||
}
|
||||
|
||||
// Return PathPartKind of PK_ilename if the parser state doesn't match
|
||||
// the states of InRootDir or InRootName and the filename
|
||||
// isn't made up of the special directory values of "." and ".."
|
||||
return PathPartKind::PK_Filename;
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ namespace AZ
|
||||
{
|
||||
}
|
||||
protected:
|
||||
virtual void Process()
|
||||
void Process() override
|
||||
{
|
||||
m_notifyFlag->store(true, AZStd::memory_order_release);
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace AZ
|
||||
: public Sample<Vector3>
|
||||
{
|
||||
public:
|
||||
Vector3 GetInterpolatedValue(TimeType time) override final
|
||||
Vector3 GetInterpolatedValue(TimeType time) final
|
||||
{
|
||||
Vector3 interpolatedValue = m_previousValue;
|
||||
if (m_targetTimestamp != 0)
|
||||
@@ -108,7 +108,7 @@ namespace AZ
|
||||
: public Sample<Quaternion>
|
||||
{
|
||||
public:
|
||||
Quaternion GetInterpolatedValue(TimeType time) override final
|
||||
Quaternion GetInterpolatedValue(TimeType time) final
|
||||
{
|
||||
Quaternion interpolatedValue = m_previousValue;
|
||||
if (m_targetTimestamp != 0)
|
||||
@@ -144,7 +144,7 @@ namespace AZ
|
||||
: public Sample<Vector3>
|
||||
{
|
||||
public:
|
||||
Vector3 GetInterpolatedValue(TimeType /*time*/) override final
|
||||
Vector3 GetInterpolatedValue(TimeType /*time*/) final
|
||||
{
|
||||
return GetTargetValue();
|
||||
}
|
||||
@@ -155,7 +155,7 @@ namespace AZ
|
||||
: public Sample<Quaternion>
|
||||
{
|
||||
public:
|
||||
Quaternion GetInterpolatedValue(TimeType /*time*/) override final
|
||||
Quaternion GetInterpolatedValue(TimeType /*time*/) final
|
||||
{
|
||||
return GetTargetValue();
|
||||
}
|
||||
|
||||
@@ -216,6 +216,11 @@ namespace AZ
|
||||
return m_source->GetMaxAllocationSize();
|
||||
}
|
||||
|
||||
auto AllocatorOverrideShim::GetMaxContiguousAllocationSize() const -> size_type
|
||||
{
|
||||
return m_source->GetMaxContiguousAllocationSize();
|
||||
}
|
||||
|
||||
IAllocatorAllocate* AllocatorOverrideShim::GetSubAllocator()
|
||||
{
|
||||
return m_source->GetSubAllocator();
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace AZ
|
||||
size_type NumAllocatedBytes() const override;
|
||||
size_type Capacity() const override;
|
||||
size_type GetMaxAllocationSize() const override;
|
||||
size_type GetMaxContiguousAllocationSize() const override;
|
||||
IAllocatorAllocate* GetSubAllocator() override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -188,6 +188,11 @@ BestFitExternalMapAllocator::GetMaxAllocationSize() const
|
||||
return m_schema->GetMaxAllocationSize();
|
||||
}
|
||||
|
||||
auto BestFitExternalMapAllocator::GetMaxContiguousAllocationSize() const -> size_type
|
||||
{
|
||||
return m_schema->GetMaxContiguousAllocationSize();
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// GetSubAllocator
|
||||
// [1/28/2011]
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace AZ
|
||||
size_type NumAllocatedBytes() const override;
|
||||
size_type Capacity() const override;
|
||||
size_type GetMaxAllocationSize() const override;
|
||||
size_type GetMaxContiguousAllocationSize() const override;
|
||||
IAllocatorAllocate* GetSubAllocator() override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -136,6 +136,12 @@ BestFitExternalMapSchema::GetMaxAllocationSize() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto BestFitExternalMapSchema::GetMaxContiguousAllocationSize() const -> size_type
|
||||
{
|
||||
// Return the maximum size of any single allocation
|
||||
return AZ_CORE_MAX_ALLOCATOR_SIZE;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// GarbageCollect
|
||||
// [1/28/2011]
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace AZ
|
||||
AZ_FORCE_INLINE size_type NumAllocatedBytes() const { return m_used; }
|
||||
AZ_FORCE_INLINE size_type Capacity() const { return m_desc.m_memoryBlockByteSize; }
|
||||
size_type GetMaxAllocationSize() const;
|
||||
size_type GetMaxContiguousAllocationSize() const;
|
||||
AZ_FORCE_INLINE IAllocatorAllocate* GetSubAllocator() const { return m_desc.m_mapAllocator; }
|
||||
|
||||
/**
|
||||
|
||||
@@ -244,6 +244,11 @@ namespace AZ
|
||||
return maxChunk;
|
||||
}
|
||||
|
||||
auto HeapSchema::GetMaxContiguousAllocationSize() const -> size_type
|
||||
{
|
||||
return MAX_REQUEST;
|
||||
}
|
||||
|
||||
AZ_FORCE_INLINE HeapSchema::size_type
|
||||
HeapSchema::ChunckSize(pointer_type ptr)
|
||||
{
|
||||
|
||||
@@ -48,17 +48,18 @@ namespace AZ
|
||||
HeapSchema(const Descriptor& desc);
|
||||
virtual ~HeapSchema();
|
||||
|
||||
virtual pointer_type Allocate(size_type byteSize, size_type alignment, int flags, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0);
|
||||
virtual void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0);
|
||||
virtual pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) { (void)ptr; (void)newSize; (void)newAlignment; return NULL; }
|
||||
virtual size_type Resize(pointer_type ptr, size_type newSize) { (void)ptr; (void)newSize; return 0; }
|
||||
virtual size_type AllocationSize(pointer_type ptr);
|
||||
pointer_type Allocate(size_type byteSize, size_type alignment, int flags, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0) override;
|
||||
void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0) override;
|
||||
pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) override { (void)ptr; (void)newSize; (void)newAlignment; return NULL; }
|
||||
size_type Resize(pointer_type ptr, size_type newSize) override { (void)ptr; (void)newSize; return 0; }
|
||||
size_type AllocationSize(pointer_type ptr) override;
|
||||
|
||||
virtual size_type NumAllocatedBytes() const { return m_used; }
|
||||
virtual size_type Capacity() const { return m_capacity; }
|
||||
virtual size_type GetMaxAllocationSize() const;
|
||||
virtual IAllocatorAllocate* GetSubAllocator() { return m_subAllocator; }
|
||||
virtual void GarbageCollect() {}
|
||||
size_type NumAllocatedBytes() const override { return m_used; }
|
||||
size_type Capacity() const override { return m_capacity; }
|
||||
size_type GetMaxAllocationSize() const override;
|
||||
size_type GetMaxContiguousAllocationSize() const override;
|
||||
IAllocatorAllocate* GetSubAllocator() override { return m_subAllocator; }
|
||||
void GarbageCollect() override {}
|
||||
|
||||
private:
|
||||
AZ_FORCE_INLINE size_type ChunckSize(pointer_type ptr);
|
||||
|
||||
@@ -1069,6 +1069,7 @@ namespace AZ {
|
||||
/// returns allocation size for the pointer if it belongs to the allocator. result is undefined if the pointer doesn't belong to the allocator.
|
||||
size_t AllocationSize(void* ptr);
|
||||
size_t GetMaxAllocationSize() const;
|
||||
size_t GetMaxContiguousAllocationSize() const;
|
||||
size_t GetUnAllocatedMemory(bool isPrint) const;
|
||||
|
||||
void* SystemAlloc(size_t size, size_t align);
|
||||
@@ -2301,6 +2302,11 @@ namespace AZ {
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
size_t HpAllocator::GetMaxContiguousAllocationSize() const
|
||||
{
|
||||
return AZ_CORE_MAX_ALLOCATOR_SIZE;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// GetUnAllocatedMemory
|
||||
// [9/30/2013]
|
||||
@@ -2677,6 +2683,11 @@ namespace AZ {
|
||||
return m_allocator->GetMaxAllocationSize();
|
||||
}
|
||||
|
||||
auto HphaSchema::GetMaxContiguousAllocationSize() const -> size_type
|
||||
{
|
||||
return m_allocator->GetMaxContiguousAllocationSize();
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// GetUnAllocatedMemory
|
||||
// [9/30/2013]
|
||||
|
||||
@@ -56,21 +56,22 @@ namespace AZ
|
||||
HphaSchema(const Descriptor& desc);
|
||||
virtual ~HphaSchema();
|
||||
|
||||
virtual pointer_type Allocate(size_type byteSize, size_type alignment, int flags = 0, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0);
|
||||
virtual void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0);
|
||||
virtual pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment);
|
||||
pointer_type Allocate(size_type byteSize, size_type alignment, int flags = 0, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0) override;
|
||||
void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0) override;
|
||||
pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) override;
|
||||
/// Resizes allocated memory block to the size possible and returns that size.
|
||||
virtual size_type Resize(pointer_type ptr, size_type newSize);
|
||||
virtual size_type AllocationSize(pointer_type ptr);
|
||||
size_type Resize(pointer_type ptr, size_type newSize) override;
|
||||
size_type AllocationSize(pointer_type ptr) override;
|
||||
|
||||
virtual size_type NumAllocatedBytes() const;
|
||||
virtual size_type Capacity() const;
|
||||
virtual size_type GetMaxAllocationSize() const;
|
||||
virtual size_type GetUnAllocatedMemory(bool isPrint = false) const;
|
||||
virtual IAllocatorAllocate* GetSubAllocator() { return m_desc.m_subAllocator; }
|
||||
size_type NumAllocatedBytes() const override;
|
||||
size_type Capacity() const override;
|
||||
size_type GetMaxAllocationSize() const override;
|
||||
size_type GetMaxContiguousAllocationSize() const override;
|
||||
size_type GetUnAllocatedMemory(bool isPrint = false) const override;
|
||||
IAllocatorAllocate* GetSubAllocator() override { return m_desc.m_subAllocator; }
|
||||
|
||||
/// Return unused memory to the OS (if we don't use fixed block). Don't call this unless you really need free memory, it is slow.
|
||||
virtual void GarbageCollect();
|
||||
void GarbageCollect() override;
|
||||
|
||||
private:
|
||||
// [LY-84974][sconel@][2018-08-10] SliceStrike integration up to CL 671758
|
||||
|
||||
@@ -62,6 +62,8 @@ namespace AZ
|
||||
virtual size_type Capacity() const = 0;
|
||||
/// Returns max allocation size if possible. If not returned value is 0
|
||||
virtual size_type GetMaxAllocationSize() const { return 0; }
|
||||
/// Returns the maximum contiguous allocation size of a single allocation
|
||||
virtual size_type GetMaxContiguousAllocationSize() const { return 0; }
|
||||
/**
|
||||
* Returns memory allocated by the allocator and available to the user for allocations.
|
||||
* IMPORTANT: this is not the overhead memory this is just the memory that is allocated, but not used. Example: the pool allocators
|
||||
|
||||
@@ -144,6 +144,11 @@ AZ::MallocSchema::size_type AZ::MallocSchema::GetMaxAllocationSize() const
|
||||
return 0xFFFFFFFFull;
|
||||
}
|
||||
|
||||
AZ::MallocSchema::size_type AZ::MallocSchema::GetMaxContiguousAllocationSize() const
|
||||
{
|
||||
return AZ_CORE_MAX_ALLOCATOR_SIZE;
|
||||
}
|
||||
|
||||
AZ::IAllocatorAllocate* AZ::MallocSchema::GetSubAllocator()
|
||||
{
|
||||
return nullptr;
|
||||
|
||||
@@ -41,17 +41,18 @@ namespace AZ
|
||||
//---------------------------------------------------------------------
|
||||
// IAllocatorAllocate
|
||||
//---------------------------------------------------------------------
|
||||
virtual pointer_type Allocate(size_type byteSize, size_type alignment, int flags, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0) override;
|
||||
virtual void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0) override;
|
||||
virtual pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) override;
|
||||
virtual size_type Resize(pointer_type ptr, size_type newSize) override;
|
||||
virtual size_type AllocationSize(pointer_type ptr) override;
|
||||
pointer_type Allocate(size_type byteSize, size_type alignment, int flags, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0) override;
|
||||
void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0) override;
|
||||
pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) override;
|
||||
size_type Resize(pointer_type ptr, size_type newSize) override;
|
||||
size_type AllocationSize(pointer_type ptr) override;
|
||||
|
||||
virtual size_type NumAllocatedBytes() const override;
|
||||
virtual size_type Capacity() const override;
|
||||
virtual size_type GetMaxAllocationSize() const override;
|
||||
virtual IAllocatorAllocate* GetSubAllocator() override;
|
||||
virtual void GarbageCollect() override;
|
||||
size_type NumAllocatedBytes() const override;
|
||||
size_type Capacity() const override;
|
||||
size_type GetMaxAllocationSize() const override;
|
||||
size_type GetMaxContiguousAllocationSize() const override;
|
||||
IAllocatorAllocate* GetSubAllocator() override;
|
||||
void GarbageCollect() override;
|
||||
|
||||
private:
|
||||
typedef void* (*MallocFn)(size_t);
|
||||
|
||||
@@ -839,12 +839,17 @@ namespace AZ
|
||||
return AZ::AllocatorInstance<Parent>::Get().GetMaxAllocationSize();
|
||||
}
|
||||
|
||||
size_type GetMaxContiguousAllocationSize() const override
|
||||
{
|
||||
return AZ::AllocatorInstance<Parent>::Get().GetMaxContiguousAllocationSize();
|
||||
}
|
||||
|
||||
size_type GetUnAllocatedMemory(bool isPrint = false) const override
|
||||
{
|
||||
return AZ::AllocatorInstance<Parent>::Get().GetUnAllocatedMemory(isPrint);
|
||||
}
|
||||
|
||||
virtual IAllocatorAllocate* GetSubAllocator() override
|
||||
IAllocatorAllocate* GetSubAllocator() override
|
||||
{
|
||||
return AZ::AllocatorInstance<Parent>::Get().GetSubAllocator();
|
||||
}
|
||||
@@ -896,7 +901,7 @@ namespace AZ
|
||||
}
|
||||
AZ_FORCE_INLINE const char* get_name() const { return m_name; }
|
||||
AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; }
|
||||
size_type get_max_size() const { return AllocatorInstance<Allocator>::Get().GetMaxAllocationSize(); }
|
||||
size_type max_size() const { return AllocatorInstance<Allocator>::Get().GetMaxContiguousAllocationSize(); }
|
||||
size_type get_allocated_size() const { return AllocatorInstance<Allocator>::Get().NumAllocatedBytes(); }
|
||||
|
||||
AZ_FORCE_INLINE bool is_lock_free() { return AllocatorInstance<Allocator>::Get().is_lock_free(); }
|
||||
@@ -954,7 +959,7 @@ namespace AZ
|
||||
}
|
||||
AZ_FORCE_INLINE const char* get_name() const { return m_name; }
|
||||
AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; }
|
||||
size_type get_max_size() const { return m_allocator->GetMaxAllocationSize(); }
|
||||
size_type max_size() const { return m_allocator->GetMaxContiguousAllocationSize(); }
|
||||
size_type get_allocated_size() const { return m_allocator->NumAllocatedBytes(); }
|
||||
|
||||
AZ_FORCE_INLINE bool operator==(const AZStdIAllocator& rhs) const { return m_allocator == rhs.m_allocator; }
|
||||
@@ -1006,7 +1011,7 @@ namespace AZ
|
||||
}
|
||||
constexpr const char* get_name() const { return m_name; }
|
||||
void set_name(const char* name) { m_name = name; }
|
||||
size_type get_max_size() const { return m_allocatorFunctor().GetMaxAllocationSize(); }
|
||||
size_type max_size() const { return m_allocatorFunctor().GetMaxContiguousAllocationSize(); }
|
||||
size_type get_allocated_size() const { return m_allocatorFunctor().NumAllocatedBytes(); }
|
||||
|
||||
constexpr bool operator==(const AZStdFunctorAllocator& rhs) const { return m_allocatorFunctor == rhs.m_allocatorFunctor; }
|
||||
|
||||
@@ -38,24 +38,24 @@ namespace AZ
|
||||
protected:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Driller
|
||||
virtual const char* GroupName() const { return "SystemDrillers"; }
|
||||
virtual const char* GetName() const { return "MemoryDriller"; }
|
||||
virtual const char* GetDescription() const { return "Reports all allocators and memory allocations."; }
|
||||
virtual void Start(const Param* params = NULL, int numParams = 0);
|
||||
virtual void Stop();
|
||||
const char* GroupName() const override { return "SystemDrillers"; }
|
||||
const char* GetName() const override { return "MemoryDriller"; }
|
||||
const char* GetDescription() const override { return "Reports all allocators and memory allocations."; }
|
||||
void Start(const Param* params = NULL, int numParams = 0) override;
|
||||
void Stop() override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MemoryDrillerBus
|
||||
virtual void RegisterAllocator(IAllocator* allocator);
|
||||
virtual void UnregisterAllocator(IAllocator* allocator);
|
||||
void RegisterAllocator(IAllocator* allocator) override;
|
||||
void UnregisterAllocator(IAllocator* allocator) override;
|
||||
|
||||
virtual void RegisterAllocation(IAllocator* allocator, void* address, size_t byteSize, size_t alignment, const char* name, const char* fileName, int lineNum, unsigned int stackSuppressCount);
|
||||
virtual void UnregisterAllocation(IAllocator* allocator, void* address, size_t byteSize, size_t alignment, AllocationInfo* info);
|
||||
virtual void ReallocateAllocation(IAllocator* allocator, void* prevAddress, void* newAddress, size_t newByteSize, size_t newAlignment);
|
||||
virtual void ResizeAllocation(IAllocator* allocator, void* address, size_t newSize);
|
||||
void RegisterAllocation(IAllocator* allocator, void* address, size_t byteSize, size_t alignment, const char* name, const char* fileName, int lineNum, unsigned int stackSuppressCount) override;
|
||||
void UnregisterAllocation(IAllocator* allocator, void* address, size_t byteSize, size_t alignment, AllocationInfo* info) override;
|
||||
void ReallocateAllocation(IAllocator* allocator, void* prevAddress, void* newAddress, size_t newByteSize, size_t newAlignment) override;
|
||||
void ResizeAllocation(IAllocator* allocator, void* address, size_t newSize) override;
|
||||
|
||||
virtual void DumpAllAllocations();
|
||||
void DumpAllAllocations() override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RegisterAllocatorOutput(IAllocator* allocator);
|
||||
|
||||
@@ -61,6 +61,7 @@ namespace AZ
|
||||
size_type NumAllocatedBytes() const override { return m_custom ? m_custom->NumAllocatedBytes() : m_numAllocatedBytes; }
|
||||
size_type Capacity() const override { return m_custom ? m_custom->Capacity() : AZ_CORE_MAX_ALLOCATOR_SIZE; } // custom size or unlimited
|
||||
size_type GetMaxAllocationSize() const override { return m_custom ? m_custom->GetMaxAllocationSize() : AZ_CORE_MAX_ALLOCATOR_SIZE; } // custom size or unlimited
|
||||
size_type GetMaxContiguousAllocationSize() const override { return m_custom ? m_custom->GetMaxContiguousAllocationSize() : AZ_CORE_MAX_ALLOCATOR_SIZE; } // custom size or unlimited
|
||||
IAllocatorAllocate* GetSubAllocator() override { return m_custom ? m_custom : NULL; }
|
||||
|
||||
protected:
|
||||
|
||||
@@ -232,6 +232,7 @@ namespace AZ
|
||||
size_type NumAllocatedBytes() const;
|
||||
size_type Capacity() const;
|
||||
size_type GetMaxAllocationSize() const;
|
||||
size_type GetMaxContiguousAllocationSize() const;
|
||||
IAllocatorAllocate* GetSubAllocator();
|
||||
void GarbageCollect();
|
||||
|
||||
@@ -674,6 +675,11 @@ AZ::OverrunDetectionSchema::size_type AZ::OverrunDetectionSchemaImpl::GetMaxAllo
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto AZ::OverrunDetectionSchemaImpl::GetMaxContiguousAllocationSize() const -> size_type
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
AZ::IAllocatorAllocate* AZ::OverrunDetectionSchemaImpl::GetSubAllocator()
|
||||
{
|
||||
return nullptr;
|
||||
@@ -799,6 +805,11 @@ AZ::OverrunDetectionSchema::size_type AZ::OverrunDetectionSchema::GetMaxAllocati
|
||||
return m_impl->GetMaxAllocationSize();
|
||||
}
|
||||
|
||||
auto AZ::OverrunDetectionSchema::GetMaxContiguousAllocationSize() const -> size_type
|
||||
{
|
||||
return m_impl->GetMaxContiguousAllocationSize();
|
||||
}
|
||||
|
||||
AZ::IAllocatorAllocate* AZ::OverrunDetectionSchema::GetSubAllocator()
|
||||
{
|
||||
return m_impl->GetSubAllocator();
|
||||
|
||||
@@ -77,17 +77,18 @@ namespace AZ
|
||||
//---------------------------------------------------------------------
|
||||
// IAllocatorAllocate
|
||||
//---------------------------------------------------------------------
|
||||
virtual pointer_type Allocate(size_type byteSize, size_type alignment, int flags, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0) override;
|
||||
virtual void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0) override;
|
||||
virtual pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) override;
|
||||
virtual size_type Resize(pointer_type ptr, size_type newSize) override;
|
||||
virtual size_type AllocationSize(pointer_type ptr) override;
|
||||
pointer_type Allocate(size_type byteSize, size_type alignment, int flags, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0) override;
|
||||
void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0) override;
|
||||
pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) override;
|
||||
size_type Resize(pointer_type ptr, size_type newSize) override;
|
||||
size_type AllocationSize(pointer_type ptr) override;
|
||||
|
||||
virtual size_type NumAllocatedBytes() const override;
|
||||
virtual size_type Capacity() const override;
|
||||
virtual size_type GetMaxAllocationSize() const override;
|
||||
virtual IAllocatorAllocate* GetSubAllocator() override;
|
||||
virtual void GarbageCollect() override;
|
||||
size_type NumAllocatedBytes() const override;
|
||||
size_type Capacity() const override;
|
||||
size_type GetMaxAllocationSize() const override;
|
||||
size_type GetMaxContiguousAllocationSize() const override;
|
||||
IAllocatorAllocate* GetSubAllocator() override;
|
||||
void GarbageCollect() override;
|
||||
|
||||
private:
|
||||
OverrunDetectionSchemaImpl* m_impl;
|
||||
|
||||
@@ -707,6 +707,11 @@ PoolSchema::GarbageCollect()
|
||||
//m_impl->GarbageCollect();
|
||||
}
|
||||
|
||||
auto PoolSchema::GetMaxContiguousAllocationSize() const -> size_type
|
||||
{
|
||||
return m_impl->m_allocator.m_maxAllocationSize;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// NumAllocatedBytes
|
||||
// [11/1/2010]
|
||||
@@ -1052,6 +1057,11 @@ ThreadPoolSchema::GarbageCollect()
|
||||
m_impl->GarbageCollect();
|
||||
}
|
||||
|
||||
auto ThreadPoolSchema::GetMaxContiguousAllocationSize() const -> size_type
|
||||
{
|
||||
return m_impl->m_maxAllocationSize;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// NumAllocatedBytes
|
||||
// [11/1/2010]
|
||||
|
||||
@@ -70,6 +70,7 @@ namespace AZ
|
||||
/// Return unused memory to the OS. Don't call this too often because you will force unnecessary allocations.
|
||||
void GarbageCollect() override;
|
||||
|
||||
size_type GetMaxContiguousAllocationSize() const override;
|
||||
size_type NumAllocatedBytes() const override;
|
||||
size_type Capacity() const override;
|
||||
IAllocatorAllocate* GetSubAllocator() override;
|
||||
@@ -115,6 +116,7 @@ namespace AZ
|
||||
/// Return unused memory to the OS. Don't call this too often because you will force unnecessary allocations.
|
||||
void GarbageCollect() override;
|
||||
|
||||
size_type GetMaxContiguousAllocationSize() const override;
|
||||
size_type NumAllocatedBytes() const override;
|
||||
size_type Capacity() const override;
|
||||
IAllocatorAllocate* GetSubAllocator() override;
|
||||
|
||||
@@ -179,6 +179,11 @@ namespace AZ
|
||||
return m_schema->GetMaxAllocationSize();
|
||||
}
|
||||
|
||||
size_type GetMaxContiguousAllocationSize() const override
|
||||
{
|
||||
return m_schema->GetMaxContiguousAllocationSize();
|
||||
}
|
||||
|
||||
size_type GetUnAllocatedMemory(bool isPrint = false) const override
|
||||
{
|
||||
return m_schema->GetUnAllocatedMemory(isPrint);
|
||||
|
||||
@@ -103,6 +103,7 @@ namespace AZ
|
||||
size_type Capacity() const override { return m_allocator->Capacity(); }
|
||||
/// Keep in mind this operation will execute GarbageCollect to make sure it returns, max allocation. This function WILL be slow.
|
||||
size_type GetMaxAllocationSize() const override { return m_allocator->GetMaxAllocationSize(); }
|
||||
size_type GetMaxContiguousAllocationSize() const override { return m_allocator->GetMaxContiguousAllocationSize(); }
|
||||
size_type GetUnAllocatedMemory(bool isPrint = false) const override { return m_allocator->GetUnAllocatedMemory(isPrint); }
|
||||
IAllocatorAllocate* GetSubAllocator() override { return m_isCustom ? m_allocator : m_allocator->GetSubAllocator(); }
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace AZ
|
||||
|
||||
const char* get_name() const { return m_name; }
|
||||
void set_name(const char* name) { m_name = name; }
|
||||
size_type get_max_size() const { return AZ_CORE_MAX_ALLOCATOR_SIZE; }
|
||||
constexpr size_type max_size() const { return AZ_CORE_MAX_ALLOCATOR_SIZE; }
|
||||
size_type get_allocated_size() const { return 0; }
|
||||
|
||||
bool is_lock_free() { return false; }
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace AZ
|
||||
* DO NOT OVERRIDE. This method will return in the future, but at this point things reflected here are not unreflected for all ReflectContexts (Serialize, Editor, Network, Script, etc.)
|
||||
* Place all calls to non-component reflect functions inside of a component reflect function to ensure that your types are unreflected.
|
||||
*/
|
||||
virtual void Reflect(AZ::ReflectContext*) final { }
|
||||
void Reflect(AZ::ReflectContext*) {}
|
||||
|
||||
/**
|
||||
* Override to require specific components on the system entity.
|
||||
|
||||
@@ -7,18 +7,17 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Script/ScriptContext.h>
|
||||
#include <AzCore/Script/ScriptContextAttributes.h>
|
||||
#include <AzCore/ScriptCanvas/ScriptCanvasAttributes.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/algorithm.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/std/string/tokenize.h>
|
||||
#include <AzCore/ScriptCanvas/ScriptCanvasOnDemandNames.h>
|
||||
#include <AzCore/RTTI/AzStdOnDemandPrettyName.inl>
|
||||
#include <AzCore/RTTI/AzStdOnDemandReflectionLuaFunctions.inl>
|
||||
#include <AzCore/EBus/Event.h>
|
||||
|
||||
#ifndef AZ_USE_CUSTOM_SCRIPT_BIND
|
||||
struct lua_State;
|
||||
struct lua_Debug;
|
||||
#endif // AZ_USE_CUSTOM_SCRIPT_BIND
|
||||
|
||||
// forward declare specialized types
|
||||
namespace AZStd
|
||||
@@ -59,6 +58,26 @@ namespace AZ
|
||||
class BehaviorContext;
|
||||
class ScriptDataContext;
|
||||
|
||||
namespace OnDemandLuaFunctions
|
||||
{
|
||||
inline void AnyToLua(lua_State* lua, BehaviorValueParameter& param);
|
||||
}
|
||||
namespace ScriptCanvasOnDemandReflection
|
||||
{
|
||||
template<typename T>
|
||||
struct OnDemandPrettyName;
|
||||
template<typename T>
|
||||
struct OnDemandToolTip;
|
||||
template<typename T>
|
||||
struct OnDemandCategoryName;
|
||||
}
|
||||
namespace CommonOnDemandReflections
|
||||
{
|
||||
void ReflectCommonString(ReflectContext* context);
|
||||
void ReflectCommonStringView(ReflectContext* context);
|
||||
void ReflectStdAny(ReflectContext* context);
|
||||
void ReflectVoidOutcome(ReflectContext* context);
|
||||
}
|
||||
/// OnDemand reflection for AZStd::basic_string
|
||||
template<class Element, class Traits, class Allocator>
|
||||
struct OnDemandReflection< AZStd::basic_string<Element, Traits, Allocator> >
|
||||
@@ -66,108 +85,16 @@ namespace AZ
|
||||
using ContainerType = AZStd::basic_string<Element, Traits, Allocator>;
|
||||
using SizeType = typename ContainerType::size_type;
|
||||
using ValueType = typename ContainerType::value_type;
|
||||
|
||||
|
||||
static void Reflect(ReflectContext* context)
|
||||
{
|
||||
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
|
||||
constexpr bool is_string = AZStd::is_same_v<Element, char> && AZStd::is_same_v<Traits, AZStd::char_traits<char>>
|
||||
&& AZStd::is_same_v<Allocator, AZStd::allocator>;
|
||||
if constexpr(is_string)
|
||||
{
|
||||
behaviorContext->Class<ContainerType>()
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
|
||||
->template Constructor<typename ContainerType::value_type*>()
|
||||
->Attribute(AZ::Script::Attributes::ConstructorOverride, &OnDemandLuaFunctions::ConstructBasicString<Element, Traits, Allocator>)
|
||||
->Attribute(AZ::Script::Attributes::ReaderWriterOverride, ScriptContext::CustomReaderWriter(&OnDemandLuaFunctions::StringTypeToLua<ContainerType>, &OnDemandLuaFunctions::StringTypeFromLua<ContainerType>))
|
||||
->template WrappingMember<const char*>(&ContainerType::c_str)
|
||||
->Method("c_str", &ContainerType::c_str)
|
||||
->Method("Length", [](ContainerType* thisPtr) { return aznumeric_cast<int>(thisPtr->length()); })
|
||||
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Length)
|
||||
->Method("Equal", [](const ContainerType& lhs, const ContainerType& rhs)
|
||||
{
|
||||
return lhs == rhs;
|
||||
})
|
||||
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Equal)
|
||||
->Method("Find", [](ContainerType* thisPtr, const ContainerType& stringToFind, const int& startPos)
|
||||
{
|
||||
return aznumeric_cast<int>(thisPtr->find(stringToFind, startPos));
|
||||
})
|
||||
->Method("Substring", [](ContainerType* thisPtr, const int& pos, const int& len)
|
||||
{
|
||||
return thisPtr->substr(pos, len);
|
||||
})
|
||||
->Method("Replace", [](ContainerType* thisPtr, const ContainerType& stringToReplace, const ContainerType& replacementString)
|
||||
{
|
||||
SizeType startPos = 0;
|
||||
while ((startPos = thisPtr->find(stringToReplace, startPos)) != ContainerType::npos && !stringToReplace.empty())
|
||||
{
|
||||
thisPtr->replace(startPos, stringToReplace.length(), replacementString);
|
||||
startPos += replacementString.length();
|
||||
}
|
||||
|
||||
return *thisPtr;
|
||||
})
|
||||
->Method("ReplaceByIndex", [](ContainerType* thisPtr, const int& beginIndex, const int& endIndex, const ContainerType& replacementString)
|
||||
{
|
||||
thisPtr->replace(beginIndex, endIndex - beginIndex + 1, replacementString);
|
||||
return *thisPtr;
|
||||
})
|
||||
->Method("Add", [](ContainerType* thisPtr, const ContainerType& addend)
|
||||
{
|
||||
return *thisPtr + addend;
|
||||
})
|
||||
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Concat)
|
||||
->Method("TrimLeft", [](ContainerType* thisPtr)
|
||||
{
|
||||
auto wsfront = AZStd::find_if_not(thisPtr->begin(), thisPtr->end(), [](char c) {return AZStd::is_space(c);});
|
||||
thisPtr->erase(thisPtr->begin(), wsfront);
|
||||
return *thisPtr;
|
||||
})
|
||||
->Method("TrimRight", [](ContainerType* thisPtr)
|
||||
{
|
||||
auto wsend = AZStd::find_if_not(thisPtr->rbegin(), thisPtr->rend(), [](char c) {return AZStd::is_space(c);});
|
||||
thisPtr->erase(wsend.base(), thisPtr->end());
|
||||
return *thisPtr;
|
||||
})
|
||||
->Method("ToLower", [](ContainerType* thisPtr)
|
||||
{
|
||||
ContainerType toLowerString;
|
||||
for (auto itr = thisPtr->begin(); itr < thisPtr->end(); itr++)
|
||||
{
|
||||
toLowerString.push_back(static_cast<ValueType>(tolower(*itr)));
|
||||
}
|
||||
return toLowerString;
|
||||
})
|
||||
->Method("ToUpper", [](ContainerType* thisPtr)
|
||||
{
|
||||
ContainerType toUpperString;
|
||||
for (auto itr = thisPtr->begin(); itr < thisPtr->end(); itr++)
|
||||
{
|
||||
toUpperString.push_back(static_cast<ValueType>(toupper(*itr)));
|
||||
}
|
||||
return toUpperString;
|
||||
})
|
||||
->Method("Join", [](AZStd::vector<ContainerType>* stringsToJoinPtr, const ContainerType& joinStr)
|
||||
{
|
||||
ContainerType joinString;
|
||||
for (auto& stringToJoin : *stringsToJoinPtr)
|
||||
{
|
||||
joinString.append(stringToJoin).append(joinStr);
|
||||
}
|
||||
//Cut off the last join str
|
||||
if (!stringsToJoinPtr->empty())
|
||||
{
|
||||
joinString = joinString.substr(0, joinString.length() - joinStr.length());
|
||||
}
|
||||
return joinString;
|
||||
})
|
||||
|
||||
->Method("Split", [](ContainerType* thisPtr, const ContainerType& splitter)
|
||||
{
|
||||
AZStd::vector<ContainerType> splitStringList;
|
||||
AZStd::tokenize(*thisPtr, splitter, splitStringList);
|
||||
return splitStringList;
|
||||
})
|
||||
;
|
||||
CommonOnDemandReflections::ReflectCommonString(context);
|
||||
}
|
||||
static_assert (is_string, "Unspecialized basic_string<> template reflection requested.");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -181,44 +108,9 @@ namespace AZ
|
||||
|
||||
static void Reflect(ReflectContext* context)
|
||||
{
|
||||
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<ContainerType>()
|
||||
->Attribute(AZ::Script::Attributes::Category, "Core")
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
|
||||
->template Constructor<typename ContainerType::value_type*>()
|
||||
->Attribute(AZ::Script::Attributes::ConstructorOverride, &OnDemandLuaFunctions::ConstructStringView<Element, Traits>)
|
||||
->Attribute(AZ::Script::Attributes::ReaderWriterOverride, ScriptContext::CustomReaderWriter(&OnDemandLuaFunctions::StringTypeToLua<ContainerType>, &OnDemandLuaFunctions::StringTypeFromLua<ContainerType>))
|
||||
->Method("ToString", [](const ContainerType& stringView) { return static_cast<AZStd::string>(stringView).c_str(); }, { { { "Reference", "String view object being converted to string" } } })
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, "Converts string_view to string")
|
||||
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::ToString)
|
||||
->template WrappingMember<const char*>(&ContainerType::data)
|
||||
->Method("data", &ContainerType::data)
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, "Returns reference to raw string data")
|
||||
->Method("length", [](ContainerType* thisPtr) { return aznumeric_cast<int>(thisPtr->length()); }, { { { "This", "Reference to the object the method is being performed on" } } })
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, "Returns length of string view")
|
||||
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Length)
|
||||
->Method("size", [](ContainerType* thisPtr) { return aznumeric_cast<int>(thisPtr->size()); }, { { { "This", "Reference to the object the method is being performed on" }} })
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, "Returns length of string view")
|
||||
->Method("find", [](ContainerType* thisPtr, ContainerType stringToFind, int startPos)
|
||||
{
|
||||
return aznumeric_cast<int>(thisPtr->find(stringToFind, startPos));
|
||||
}, { { { "This", "Reference to the object the method is being performed on" }, { "View", "View to search " }, { "Position", "Index in view to start search" }} })
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, "Searches for supplied string within this string")
|
||||
->Method("substr", [](ContainerType* thisPtr, int pos, int len)
|
||||
{
|
||||
return thisPtr->substr(pos, len);
|
||||
}, { {{"This", "Reference to the object the method is being performed on"}, {"Position", "Index in view that indicates the beginning of the sub string"}, {"Count", "Length of characters that sub string view occupies" }} })
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, "Creates a sub view of this string view. The string data is not actually modified")
|
||||
->Method("remove_prefix", [](ContainerType* thisPtr, int n) {thisPtr->remove_prefix(n); },
|
||||
{ { { "This", "Reference to the object the method is being performed on" }, { "Count", "Number of characters to remove from start of view" }} })
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, "Moves the supplied number of characters from the beginning of this sub view")
|
||||
->Method("remove_suffix", [](ContainerType* thisPtr, int n) {thisPtr->remove_suffix(n); },
|
||||
{ { { "This", "Reference to the object the method is being performed on" } ,{ "Count", "Number of characters to remove from end of view" }} })
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, "Moves the supplied number of characters from the end of this sub view")
|
||||
;
|
||||
}
|
||||
constexpr bool is_common = AZStd::is_same_v<Element,char> && AZStd::is_same_v<Traits,AZStd::char_traits<char>>;
|
||||
static_assert (is_common, "Unspecialized basic_string_view<> template reflection requested.");
|
||||
CommonOnDemandReflections::ReflectCommonStringView(context);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -228,7 +120,7 @@ namespace AZ
|
||||
{
|
||||
using ContainerType = AZStd::intrusive_ptr<T>;
|
||||
|
||||
// TODO: Count reflection types for a proper un-reflect
|
||||
// TODO: Count reflection types for a proper un-reflect
|
||||
|
||||
static void CustomConstructor(ContainerType* thisPtr, ScriptDataContext& dc)
|
||||
{
|
||||
@@ -276,7 +168,7 @@ namespace AZ
|
||||
{
|
||||
using ContainerType = AZStd::shared_ptr<T>;
|
||||
|
||||
// TODO: Count reflection types for a proper un-reflect
|
||||
// TODO: Count reflection types for a proper un-reflect
|
||||
|
||||
static void CustomConstructor(ContainerType* thisPtr, ScriptDataContext& dc)
|
||||
{
|
||||
@@ -435,7 +327,7 @@ namespace AZ
|
||||
thisPtr[uindex] = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool EraseCheck_VM(ContainerType& thisPtr, AZ::u64 index)
|
||||
{
|
||||
if (index < thisPtr.size())
|
||||
@@ -448,7 +340,7 @@ namespace AZ
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static ContainerType& ErasePost_VM(ContainerType& thisPtr, AZ::u64 /*index*/)
|
||||
{
|
||||
return thisPtr;
|
||||
@@ -604,7 +496,7 @@ namespace AZ
|
||||
return AZ::Failure(AZStd::string::format("Index out of bounds: %zu (size: %zu)", index, thisContainer.size()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static AZ::Outcome<void, void> Replace(ContainerType& thisContainer, size_t index, T& value)
|
||||
{
|
||||
if (index >= 0 && index < thisContainer.size())
|
||||
@@ -634,7 +526,7 @@ namespace AZ
|
||||
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Length)
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Attribute(AZ::Script::Attributes::Deprecated, true)
|
||||
|
||||
|
||||
->Method(k_accessElementName, &At, {{ {}, { "Index", "The index to read from", nullptr, BehaviorParameter::Traits::TR_INDEX }}})
|
||||
->Method(k_sizeName, [](ContainerType*) { return aznumeric_cast<int>(N); })
|
||||
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Length)
|
||||
@@ -743,27 +635,8 @@ namespace AZ
|
||||
template<> // in case someone has an issue with bool
|
||||
struct OnDemandReflection<AZ::Outcome<void, void>>
|
||||
{
|
||||
using OutcomeType = AZ::Outcome<void, void>;
|
||||
|
||||
static void Reflect(ReflectContext* context)
|
||||
{
|
||||
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
|
||||
{
|
||||
// note we can reflect iterator types and support iterators, as of know we want to keep it simple
|
||||
behaviorContext->Class<OutcomeType>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Attribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, true)
|
||||
->Attribute(AZ::ScriptCanvasAttributes::PrettyName, &ScriptCanvasOnDemandReflection::OnDemandPrettyName<OutcomeType>::Get)
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, &ScriptCanvasOnDemandReflection::OnDemandToolTip<OutcomeType>::Get)
|
||||
->Attribute(AZ::Script::Attributes::Category, &ScriptCanvasOnDemandReflection::OnDemandCategoryName<OutcomeType>::Get)
|
||||
->Attribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, AttributeIsValid::IfPresent)
|
||||
->Attribute(AZ::ScriptCanvasAttributes::VariableCreationForbidden, AttributeIsValid::IfPresent)
|
||||
->Method("Failure", []() -> OutcomeType { return AZ::Failure(); })
|
||||
->Method("Success", []() -> OutcomeType { return AZ::Success(); })
|
||||
->Method("IsSuccess", &OutcomeType::IsSuccess)
|
||||
;
|
||||
}
|
||||
static void Reflect(ReflectContext* context) {
|
||||
CommonOnDemandReflections::ReflectVoidOutcome(context);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1179,16 +1052,8 @@ namespace AZ
|
||||
template <>
|
||||
struct OnDemandReflection<AZStd::any>
|
||||
{
|
||||
static void Reflect(ReflectContext* context)
|
||||
{
|
||||
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<AZStd::any>()
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Attribute(Script::Attributes::Ignore, true) // Don't reflect any type to script (there should never be an any instance in script)
|
||||
->Attribute(Script::Attributes::ReaderWriterOverride, ScriptContext::CustomReaderWriter(&AZ::OnDemandLuaFunctions::AnyToLua, &OnDemandLuaFunctions::AnyFromLua))
|
||||
;
|
||||
}
|
||||
static void Reflect(ReflectContext* context) {
|
||||
CommonOnDemandReflections::ReflectStdAny(context);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#include <AzCore/Math/Uuid.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/RTTI/ReflectContext.h>
|
||||
#include <AzCore/RTTI/TypeInfo.h>
|
||||
#include <AzCore/std/string/alphanum.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/string/tokenize.h>
|
||||
|
||||
#include <AzCore/RTTI/AzStdOnDemandReflection.inl>
|
||||
#include <AzCore/RTTI/AzStdOnDemandReflectionLuaFunctions.inl>
|
||||
namespace AZ::CommonOnDemandReflections
|
||||
{
|
||||
void ReflectCommonString(ReflectContext* context)
|
||||
{
|
||||
using ContainerType = AZStd::string;
|
||||
using SizeType = typename ContainerType::size_type;
|
||||
using ValueType = typename ContainerType::value_type;
|
||||
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<ContainerType>()
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
|
||||
->template Constructor<typename ContainerType::value_type*>()
|
||||
->Attribute(AZ::Script::Attributes::ConstructorOverride, &OnDemandLuaFunctions::ConstructBasicString<ContainerType::value_type, ContainerType::traits_type, ContainerType::allocator_type>)
|
||||
->Attribute(AZ::Script::Attributes::ReaderWriterOverride, ScriptContext::CustomReaderWriter(&OnDemandLuaFunctions::StringTypeToLua<ContainerType>, &OnDemandLuaFunctions::StringTypeFromLua<ContainerType>))
|
||||
->template WrappingMember<const char*>(&ContainerType::c_str)
|
||||
->Method("c_str", &ContainerType::c_str)
|
||||
->Method("Length", [](ContainerType* thisPtr) { return aznumeric_cast<int>(thisPtr->length()); })
|
||||
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Length)
|
||||
->Method("Equal", [](const ContainerType& lhs, const ContainerType& rhs)
|
||||
{
|
||||
return lhs == rhs;
|
||||
})
|
||||
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Equal)
|
||||
->Method("Find", [](ContainerType* thisPtr, const ContainerType& stringToFind, const int& startPos)
|
||||
{
|
||||
return aznumeric_cast<int>(thisPtr->find(stringToFind, startPos));
|
||||
})
|
||||
->Method("Substring", [](ContainerType* thisPtr, const int& pos, const int& len)
|
||||
{
|
||||
return thisPtr->substr(pos, len);
|
||||
})
|
||||
->Method("Replace", [](ContainerType* thisPtr, const ContainerType& stringToReplace, const ContainerType& replacementString)
|
||||
{
|
||||
SizeType startPos = 0;
|
||||
while ((startPos = thisPtr->find(stringToReplace, startPos)) != ContainerType::npos && !stringToReplace.empty())
|
||||
{
|
||||
thisPtr->replace(startPos, stringToReplace.length(), replacementString);
|
||||
startPos += replacementString.length();
|
||||
}
|
||||
|
||||
return *thisPtr;
|
||||
})
|
||||
->Method("ReplaceByIndex", [](ContainerType* thisPtr, const int& beginIndex, const int& endIndex, const ContainerType& replacementString)
|
||||
{
|
||||
thisPtr->replace(beginIndex, endIndex - beginIndex + 1, replacementString);
|
||||
return *thisPtr;
|
||||
})
|
||||
->Method("Add", [](ContainerType* thisPtr, const ContainerType& addend)
|
||||
{
|
||||
return *thisPtr + addend;
|
||||
})
|
||||
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Concat)
|
||||
->Method("TrimLeft", [](ContainerType* thisPtr)
|
||||
{
|
||||
auto wsfront = AZStd::find_if_not(thisPtr->begin(), thisPtr->end(), [](char c) {return AZStd::is_space(c);});
|
||||
thisPtr->erase(thisPtr->begin(), wsfront);
|
||||
return *thisPtr;
|
||||
})
|
||||
->Method("TrimRight", [](ContainerType* thisPtr)
|
||||
{
|
||||
auto wsend = AZStd::find_if_not(thisPtr->rbegin(), thisPtr->rend(), [](char c) {return AZStd::is_space(c);});
|
||||
thisPtr->erase(wsend.base(), thisPtr->end());
|
||||
return *thisPtr;
|
||||
})
|
||||
->Method("ToLower", [](ContainerType* thisPtr)
|
||||
{
|
||||
ContainerType toLowerString;
|
||||
for (auto itr = thisPtr->begin(); itr < thisPtr->end(); itr++)
|
||||
{
|
||||
toLowerString.push_back(static_cast<ValueType>(tolower(*itr)));
|
||||
}
|
||||
return toLowerString;
|
||||
})
|
||||
->Method("ToUpper", [](ContainerType* thisPtr)
|
||||
{
|
||||
ContainerType toUpperString;
|
||||
for (auto itr = thisPtr->begin(); itr < thisPtr->end(); itr++)
|
||||
{
|
||||
toUpperString.push_back(static_cast<ValueType>(toupper(*itr)));
|
||||
}
|
||||
return toUpperString;
|
||||
})
|
||||
->Method("Join", [](AZStd::vector<ContainerType>* stringsToJoinPtr, const ContainerType& joinStr)
|
||||
{
|
||||
ContainerType joinString;
|
||||
for (auto& stringToJoin : *stringsToJoinPtr)
|
||||
{
|
||||
joinString.append(stringToJoin).append(joinStr);
|
||||
}
|
||||
//Cut off the last join str
|
||||
if (!stringsToJoinPtr->empty())
|
||||
{
|
||||
joinString = joinString.substr(0, joinString.length() - joinStr.length());
|
||||
}
|
||||
return joinString;
|
||||
})
|
||||
|
||||
->Method("Split", [](ContainerType* thisPtr, const ContainerType& splitter)
|
||||
{
|
||||
AZStd::vector<ContainerType> splitStringList;
|
||||
AZStd::tokenize(*thisPtr, splitter, splitStringList);
|
||||
return splitStringList;
|
||||
})
|
||||
;
|
||||
}
|
||||
}
|
||||
void ReflectCommonStringView(ReflectContext* context)
|
||||
{
|
||||
using ContainerType = AZStd::string_view;
|
||||
|
||||
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<ContainerType>()
|
||||
->Attribute(AZ::Script::Attributes::Category, "Core")
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
|
||||
->template Constructor<typename ContainerType::value_type*>()
|
||||
->Attribute(AZ::Script::Attributes::ConstructorOverride, &OnDemandLuaFunctions::ConstructStringView<ContainerType::value_type, ContainerType::traits_type>)
|
||||
->Attribute(AZ::Script::Attributes::ReaderWriterOverride, ScriptContext::CustomReaderWriter(&OnDemandLuaFunctions::StringTypeToLua<ContainerType>, &OnDemandLuaFunctions::StringTypeFromLua<ContainerType>))
|
||||
->Method("ToString", [](const ContainerType& stringView) { return static_cast<AZStd::string>(stringView).c_str(); }, { { { "Reference", "String view object being converted to string" } } })
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, "Converts string_view to string")
|
||||
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::ToString)
|
||||
->template WrappingMember<const char*>(&ContainerType::data)
|
||||
->Method("data", &ContainerType::data)
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, "Returns reference to raw string data")
|
||||
->Method("length", [](ContainerType* thisPtr) { return aznumeric_cast<int>(thisPtr->length()); }, { { { "This", "Reference to the object the method is being performed on" } } })
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, "Returns length of string view")
|
||||
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Length)
|
||||
->Method("size", [](ContainerType* thisPtr) { return aznumeric_cast<int>(thisPtr->size()); }, { { { "This", "Reference to the object the method is being performed on" }} })
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, "Returns length of string view")
|
||||
->Method("find", [](ContainerType* thisPtr, ContainerType stringToFind, int startPos)
|
||||
{
|
||||
return aznumeric_cast<int>(thisPtr->find(stringToFind, startPos));
|
||||
}, { { { "This", "Reference to the object the method is being performed on" }, { "View", "View to search " }, { "Position", "Index in view to start search" }} })
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, "Searches for supplied string within this string")
|
||||
->Method("substr", [](ContainerType* thisPtr, int pos, int len)
|
||||
{
|
||||
return thisPtr->substr(pos, len);
|
||||
}, { {{"This", "Reference to the object the method is being performed on"}, {"Position", "Index in view that indicates the beginning of the sub string"}, {"Count", "Length of characters that sub string view occupies" }} })
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, "Creates a sub view of this string view. The string data is not actually modified")
|
||||
->Method("remove_prefix", [](ContainerType* thisPtr, int n) {thisPtr->remove_prefix(n); },
|
||||
{ { { "This", "Reference to the object the method is being performed on" }, { "Count", "Number of characters to remove from start of view" }} })
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, "Moves the supplied number of characters from the beginning of this sub view")
|
||||
->Method("remove_suffix", [](ContainerType* thisPtr, int n) {thisPtr->remove_suffix(n); },
|
||||
{ { { "This", "Reference to the object the method is being performed on" } ,{ "Count", "Number of characters to remove from end of view" }} })
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, "Moves the supplied number of characters from the end of this sub view")
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ReflectVoidOutcome(ReflectContext* context)
|
||||
{
|
||||
using OutcomeType = AZ::Outcome<void, void>;
|
||||
|
||||
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
|
||||
{
|
||||
// note we can reflect iterator types and support iterators, as of know we want to keep it simple
|
||||
behaviorContext->Class<OutcomeType>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Attribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, true)
|
||||
->Attribute(AZ::ScriptCanvasAttributes::PrettyName, &ScriptCanvasOnDemandReflection::OnDemandPrettyName<OutcomeType>::Get)
|
||||
->Attribute(AZ::Script::Attributes::ToolTip, &ScriptCanvasOnDemandReflection::OnDemandToolTip<OutcomeType>::Get)
|
||||
->Attribute(AZ::Script::Attributes::Category, &ScriptCanvasOnDemandReflection::OnDemandCategoryName<OutcomeType>::Get)
|
||||
->Attribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, AttributeIsValid::IfPresent)
|
||||
->Attribute(AZ::ScriptCanvasAttributes::VariableCreationForbidden, AttributeIsValid::IfPresent)
|
||||
->Method("Failure", []() -> OutcomeType { return AZ::Failure(); })
|
||||
->Method("Success", []() -> OutcomeType { return AZ::Success(); })
|
||||
->Method("IsSuccess", &OutcomeType::IsSuccess)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void ReflectStdAny(ReflectContext* context)
|
||||
{
|
||||
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<AZStd::any>()
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Attribute(
|
||||
Script::Attributes::Ignore, true) // Don't reflect any type to script (there should never be an any instance in script)
|
||||
->Attribute(
|
||||
Script::Attributes::ReaderWriterOverride,
|
||||
ScriptContext::CustomReaderWriter(&AZ::OnDemandLuaFunctions::AnyToLua, &OnDemandLuaFunctions::AnyFromLua));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AZ
|
||||
@@ -594,8 +594,8 @@ namespace AZ
|
||||
void SetArgumentName(size_t index, const AZStd::string& name) override;
|
||||
const AZStd::string* GetArgumentToolTip(size_t index) const override;
|
||||
void SetArgumentToolTip(size_t index, const AZStd::string& name) override;
|
||||
virtual void SetDefaultValue(size_t index, BehaviorDefaultValuePtr defaultValue) override;
|
||||
virtual BehaviorDefaultValuePtr GetDefaultValue(size_t index) const override;
|
||||
void SetDefaultValue(size_t index, BehaviorDefaultValuePtr defaultValue) override;
|
||||
BehaviorDefaultValuePtr GetDefaultValue(size_t index) const override;
|
||||
const BehaviorParameter* GetResult() const override;
|
||||
|
||||
void OverrideParameterTraits(size_t index, AZ::u32 addTraits, AZ::u32 removeTraits) override;
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#ifndef AZCORE_RTTI_H
|
||||
#define AZCORE_RTTI_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/RTTI/TypeInfo.h>
|
||||
#include <AzCore/Module/Environment.h>
|
||||
@@ -44,21 +44,9 @@ namespace AZ
|
||||
/// RTTI typeId
|
||||
typedef void (* RTTI_EnumCallback)(const AZ::TypeId& /*typeId*/, void* /*userData*/);
|
||||
|
||||
// Disabling missing override warning because we intentionally want to allow for declaring RTTI base classes that don't impelment RTTI.
|
||||
#if defined(AZ_COMPILER_CLANG)
|
||||
# define AZ_PUSH_DISABLE_OVERRIDE_WARNING \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Winconsistent-missing-override\"")
|
||||
# define AZ_POP_DISABLE_OVERRIDE_WARNING \
|
||||
_Pragma("clang diagnostic pop")
|
||||
#else
|
||||
# define AZ_PUSH_DISABLE_OVERRIDE_WARNING
|
||||
# define AZ_POP_DISABLE_OVERRIDE_WARNING
|
||||
#endif
|
||||
|
||||
// We require AZ_TYPE_INFO to be declared
|
||||
#define AZ_RTTI_COMMON() \
|
||||
AZ_PUSH_DISABLE_OVERRIDE_WARNING \
|
||||
AZ_PUSH_DISABLE_WARNING(26433, "-Winconsistent-missing-override") \
|
||||
void RTTI_Enable(); \
|
||||
virtual inline const AZ::TypeId& RTTI_GetType() const { return RTTI_Type(); } \
|
||||
virtual inline const char* RTTI_GetTypeName() const { return RTTI_TypeName(); } \
|
||||
@@ -66,7 +54,7 @@ namespace AZ
|
||||
virtual void RTTI_EnumTypes(AZ::RTTI_EnumCallback cb, void* userData) { RTTI_EnumHierarchy(cb, userData); } \
|
||||
static inline const AZ::TypeId& RTTI_Type() { return TYPEINFO_Uuid(); } \
|
||||
static inline const char* RTTI_TypeName() { return TYPEINFO_Name(); } \
|
||||
AZ_POP_DISABLE_OVERRIDE_WARNING
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
//#define AZ_RTTI_1(_1) static_assert(false,"You must provide a valid classUuid!")
|
||||
|
||||
@@ -74,8 +62,10 @@ namespace AZ
|
||||
#define AZ_RTTI_1() AZ_RTTI_COMMON() \
|
||||
static bool RTTI_IsContainType(const AZ::TypeId& id) { return id == RTTI_Type(); } \
|
||||
static void RTTI_EnumHierarchy(AZ::RTTI_EnumCallback cb, void* userData) { cb(RTTI_Type(), userData); } \
|
||||
AZ_PUSH_DISABLE_WARNING(26433, "-Winconsistent-missing-override") \
|
||||
virtual inline const void* RTTI_AddressOf(const AZ::TypeId& id) const { return (id == RTTI_Type()) ? this : nullptr; } \
|
||||
virtual inline void* RTTI_AddressOf(const AZ::TypeId& id) { return (id == RTTI_Type()) ? this : nullptr; }
|
||||
virtual inline void* RTTI_AddressOf(const AZ::TypeId& id) { return (id == RTTI_Type()) ? this : nullptr; } \
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
/// AZ_RTTI(BaseClass)
|
||||
#define AZ_RTTI_2(_1) AZ_RTTI_COMMON() \
|
||||
@@ -85,14 +75,14 @@ namespace AZ
|
||||
static void RTTI_EnumHierarchy(AZ::RTTI_EnumCallback cb, void* userData) { \
|
||||
cb(RTTI_Type(), userData); \
|
||||
AZ::Internal::RttiCaller<_1>::RTTI_EnumHierarchy(cb, userData); } \
|
||||
AZ_PUSH_DISABLE_OVERRIDE_WARNING \
|
||||
AZ_PUSH_DISABLE_WARNING(26433, "-Winconsistent-missing-override") \
|
||||
virtual inline const void* RTTI_AddressOf(const AZ::TypeId& id) const { \
|
||||
if (id == RTTI_Type()) { return this; } \
|
||||
return AZ::Internal::RttiCaller<_1>::RTTI_AddressOf(this, id); } \
|
||||
virtual inline void* RTTI_AddressOf(const AZ::TypeId& id) { \
|
||||
if (id == RTTI_Type()) { return this; } \
|
||||
return AZ::Internal::RttiCaller<_1>::RTTI_AddressOf(this, id); } \
|
||||
AZ_POP_DISABLE_OVERRIDE_WARNING
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
/// AZ_RTTI(BaseClass1,BaseClass2)
|
||||
#define AZ_RTTI_3(_1, _2) AZ_RTTI_COMMON() \
|
||||
@@ -104,7 +94,7 @@ namespace AZ
|
||||
cb(RTTI_Type(), userData); \
|
||||
AZ::Internal::RttiCaller<_1>::RTTI_EnumHierarchy(cb, userData); \
|
||||
AZ::Internal::RttiCaller<_2>::RTTI_EnumHierarchy(cb, userData); } \
|
||||
AZ_PUSH_DISABLE_OVERRIDE_WARNING \
|
||||
AZ_PUSH_DISABLE_WARNING(26433, "-Winconsistent-missing-override") \
|
||||
virtual inline const void* RTTI_AddressOf(const AZ::TypeId& id) const { \
|
||||
if (id == RTTI_Type()) { return this; } \
|
||||
const void* r = AZ::Internal::RttiCaller<_1>::RTTI_AddressOf(this, id); if (r) { return r; } \
|
||||
@@ -113,7 +103,7 @@ namespace AZ
|
||||
if (id == RTTI_Type()) { return this; } \
|
||||
void* r = AZ::Internal::RttiCaller<_1>::RTTI_AddressOf(this, id); if (r) { return r; } \
|
||||
return AZ::Internal::RttiCaller<_2>::RTTI_AddressOf(this, id); } \
|
||||
AZ_POP_DISABLE_OVERRIDE_WARNING
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
/// AZ_RTTI(BaseClass1,BaseClass2,BaseClass3)
|
||||
#define AZ_RTTI_4(_1, _2, _3) AZ_RTTI_COMMON() \
|
||||
@@ -127,7 +117,7 @@ namespace AZ
|
||||
AZ::Internal::RttiCaller<_1>::RTTI_EnumHierarchy(cb, userData); \
|
||||
AZ::Internal::RttiCaller<_2>::RTTI_EnumHierarchy(cb, userData); \
|
||||
AZ::Internal::RttiCaller<_3>::RTTI_EnumHierarchy(cb, userData); } \
|
||||
AZ_PUSH_DISABLE_OVERRIDE_WARNING \
|
||||
AZ_PUSH_DISABLE_WARNING(26433, "-Winconsistent-missing-override") \
|
||||
virtual inline const void* RTTI_AddressOf(const AZ::TypeId& id) const { \
|
||||
if (id == RTTI_Type()) { return this; } \
|
||||
const void* r = AZ::Internal::RttiCaller<_1>::RTTI_AddressOf(this, id); if (r) { return r; } \
|
||||
@@ -138,7 +128,7 @@ namespace AZ
|
||||
void* r = AZ::Internal::RttiCaller<_1>::RTTI_AddressOf(this, id); if (r) { return r; } \
|
||||
r = AZ::Internal::RttiCaller<_2>::RTTI_AddressOf(this, id); if (r) { return r; } \
|
||||
return AZ::Internal::RttiCaller<_3>::RTTI_AddressOf(this, id); } \
|
||||
AZ_POP_DISABLE_OVERRIDE_WARNING
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
/// AZ_RTTI(BaseClass1,BaseClass2,BaseClass3,BaseClass4)
|
||||
#define AZ_RTTI_5(_1, _2, _3, _4) AZ_RTTI_COMMON() \
|
||||
@@ -154,7 +144,7 @@ namespace AZ
|
||||
AZ::Internal::RttiCaller<_2>::RTTI_EnumHierarchy(cb, userData); \
|
||||
AZ::Internal::RttiCaller<_3>::RTTI_EnumHierarchy(cb, userData); \
|
||||
AZ::Internal::RttiCaller<_4>::RTTI_EnumHierarchy(cb, userData); } \
|
||||
AZ_PUSH_DISABLE_OVERRIDE_WARNING \
|
||||
AZ_PUSH_DISABLE_WARNING(26433, "-Winconsistent-missing-override") \
|
||||
virtual inline const void* RTTI_AddressOf(const AZ::TypeId& id) const { \
|
||||
if (id == RTTI_Type()) { return this; } \
|
||||
const void* r = AZ::Internal::RttiCaller<_1>::RTTI_AddressOf(this, id); if (r) { return r; } \
|
||||
@@ -167,7 +157,7 @@ namespace AZ
|
||||
r = AZ::Internal::RttiCaller<_2>::RTTI_AddressOf(this, id); if (r) { return r; } \
|
||||
r = AZ::Internal::RttiCaller<_3>::RTTI_AddressOf(this, id); if (r) { return r; } \
|
||||
return AZ::Internal::RttiCaller<_4>::RTTI_AddressOf(this, id); } \
|
||||
AZ_POP_DISABLE_OVERRIDE_WARNING
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
/// AZ_RTTI(BaseClass1,BaseClass2,BaseClass3,BaseClass4,BaseClass5)
|
||||
#define AZ_RTTI_6(_1, _2, _3, _4, _5) AZ_RTTI_COMMON() \
|
||||
@@ -185,7 +175,7 @@ namespace AZ
|
||||
AZ::Internal::RttiCaller<_3>::RTTI_EnumHierarchy(cb, userData); \
|
||||
AZ::Internal::RttiCaller<_4>::RTTI_EnumHierarchy(cb, userData); \
|
||||
AZ::Internal::RttiCaller<_5>::RTTI_EnumHierarchy(cb, userData); } \
|
||||
AZ_PUSH_DISABLE_OVERRIDE_WARNING \
|
||||
AZ_PUSH_DISABLE_WARNING(26433, "-Winconsistent-missing-override") \
|
||||
virtual inline const void* RTTI_AddressOf(const AZ::TypeId& id) const { \
|
||||
if (id == RTTI_Type()) { return this; } \
|
||||
const void* r = AZ::Internal::RttiCaller<_1>::RTTI_AddressOf(this, id); if (r) { return r; } \
|
||||
@@ -200,7 +190,7 @@ namespace AZ
|
||||
r = AZ::Internal::RttiCaller<_3>::RTTI_AddressOf(this, id); if (r) { return r; } \
|
||||
r = AZ::Internal::RttiCaller<_4>::RTTI_AddressOf(this, id); if (r) { return r; } \
|
||||
return AZ::Internal::RttiCaller<_5>::RTTI_AddressOf(this, id); } \
|
||||
AZ_POP_DISABLE_OVERRIDE_WARNING
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// MACRO specialization to allow optional parameters for template version of AZ_RTTI
|
||||
@@ -951,10 +941,7 @@ namespace AZ
|
||||
{
|
||||
return AZStd::shared_ptr<DestType>(ptr, castPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
return AZStd::shared_ptr<DestType>();
|
||||
}
|
||||
return AZStd::shared_ptr<DestType>();
|
||||
}
|
||||
|
||||
// RttiCast specialization for intrusive_ptr.
|
||||
@@ -1077,7 +1064,6 @@ namespace AZ
|
||||
{
|
||||
return AZ::Internal::RttiIsTypeOfIdHelper<U>::Check(id, data, typename HasAZRtti<AZStd::remove_pointer_t<U>>::kind_type());
|
||||
}
|
||||
|
||||
} // namespace AZ
|
||||
|
||||
#endif // AZCORE_RTTI_H
|
||||
#pragma once
|
||||
|
||||
@@ -222,7 +222,7 @@ namespace AZ
|
||||
|
||||
int AddRefCount(int value)
|
||||
{
|
||||
AZ_Assert(value == 1 || value == -1, "ModRefCount is only for incrementing or decrementing on copy or destruction of ExposedLambda")
|
||||
AZ_Assert(value == 1 || value == -1, "ModRefCount is only for incrementing or decrementing on copy or destruction of ExposedLambda");
|
||||
lua_rawgeti(m_lua, LUA_REGISTRYINDEX, m_refCountRegistryIndex);
|
||||
// Lua: refCount-old
|
||||
const int refCount = Internal::azlua_tointeger(m_lua, -1) + value;
|
||||
@@ -2306,7 +2306,7 @@ LUA_API const Node* lua_getDummyNode()
|
||||
else // even references are stored by value as we need to convert from lua native type, i.e. there is not real reference for NativeTypes (numbers, strings, etc.)
|
||||
{
|
||||
bool usedBackupAlloc = false;
|
||||
if (backupAllocator != nullptr && sizeof(T) > tempAllocator.get_max_size())
|
||||
if (backupAllocator != nullptr && sizeof(T) > AZStd::allocator_traits<decltype(tempAllocator)>::max_size(tempAllocator))
|
||||
{
|
||||
value.m_value = backupAllocator->allocate(sizeof(T), AZStd::alignment_of<T>::value, 0);
|
||||
usedBackupAlloc = true;
|
||||
@@ -2340,7 +2340,7 @@ LUA_API const Node* lua_getDummyNode()
|
||||
else // it's a value type
|
||||
{
|
||||
bool usedBackupAlloc = false;
|
||||
if (backupAllocator != nullptr && valueClass->m_size > tempAllocator.get_max_size())
|
||||
if (backupAllocator != nullptr && valueClass->m_size > AZStd::allocator_traits<decltype(tempAllocator)>::max_size(tempAllocator))
|
||||
{
|
||||
value.m_value = backupAllocator->allocate(valueClass->m_size, valueClass->m_alignment, 0);
|
||||
usedBackupAlloc = true;
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Casting/numeric_cast_internal.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerialization.h>
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
#include <AzCore/std/string/osstring.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
//! A helper function to casts between numeric types, and consider the data which is being converted comse from user data.
|
||||
//! A helper function to casts between numeric types, and consider the data which is being converted comes from user data.
|
||||
//! If a conversion from FromType to ToType will not cause overflow or underflow, the result is stored in result, and the function returns Success
|
||||
//! Otherwise, the target is left untouched.
|
||||
template <typename ToType, typename FromType>
|
||||
@@ -24,9 +24,9 @@ namespace AZ
|
||||
{
|
||||
using namespace JsonSerializationResult;
|
||||
|
||||
if (NumericCastInternal::FitsInToType<ToType>(value))
|
||||
if (NumericCastInternal::template FitsInToType<ToType>(value))
|
||||
{
|
||||
result = aznumeric_cast<ToType>(value);
|
||||
result = static_cast<ToType>(value);
|
||||
return reporting("Successfully cast number.", ResultCode(Tasks::Convert, Outcomes::Success), path);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -19,8 +19,8 @@ namespace AZ
|
||||
public:
|
||||
AZ_COMPONENT(JsonSystemComponent, "{3C2C7234-9512-4E24-86F0-C40865D7EECE}", Component);
|
||||
|
||||
void Activate();
|
||||
void Deactivate();
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
|
||||
static void Reflect(ReflectContext* reflectContext);
|
||||
};
|
||||
|
||||
@@ -240,11 +240,6 @@ namespace AZ
|
||||
{
|
||||
IO::SizeType length = stream.GetLength();
|
||||
|
||||
if (length > AZ::Utils::DefaultMaxFileSize)
|
||||
{
|
||||
return AZ::Failure(AZStd::string{ "Data is too large." });
|
||||
}
|
||||
|
||||
AZStd::vector<char> memoryBuffer;
|
||||
memoryBuffer.resize_no_construct(static_cast<AZStd::vector<char>::size_type>(static_cast<AZStd::vector<char>::size_type>(length) + 1));
|
||||
|
||||
@@ -259,12 +254,12 @@ namespace AZ
|
||||
return ReadJsonString(AZStd::string_view{memoryBuffer.data(), memoryBuffer.size()});
|
||||
}
|
||||
|
||||
AZ::Outcome<rapidjson::Document, AZStd::string> ReadJsonFile(AZStd::string_view filePath)
|
||||
AZ::Outcome<rapidjson::Document, AZStd::string> ReadJsonFile(AZStd::string_view filePath, size_t maxFileSize)
|
||||
{
|
||||
// Read into memory first and then parse the json, rather than passing a file stream to rapidjson.
|
||||
// This should avoid creating a large number of micro-reads from the file.
|
||||
|
||||
auto readResult = AZ::Utils::ReadFile<AZStd::string>(filePath);
|
||||
auto readResult = AZ::Utils::ReadFile<AZStd::string>(filePath, maxFileSize);
|
||||
if(!readResult.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(readResult.GetError());
|
||||
@@ -308,6 +303,55 @@ namespace AZ
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
AZ::Outcome<void, AZStd::string> LoadObjectFromStringByType(void* objectToLoad, const Uuid& classId, AZStd::string_view stream,
|
||||
const JsonDeserializerSettings* settings)
|
||||
{
|
||||
JsonDeserializerSettings loadSettings;
|
||||
AZStd::string deserializeErrors;
|
||||
auto prepare = PrepareDeserializerSettings(settings, loadSettings, deserializeErrors);
|
||||
if (!prepare.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(prepare.GetError());
|
||||
}
|
||||
|
||||
auto parseResult = ReadJsonString(stream);
|
||||
if (!parseResult.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(parseResult.GetError());
|
||||
}
|
||||
|
||||
const rapidjson::Document& jsonDocument = parseResult.GetValue();
|
||||
|
||||
auto validateResult = ValidateJsonClassHeader(jsonDocument);
|
||||
if (!validateResult.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(validateResult.GetError());
|
||||
}
|
||||
|
||||
const char* className = jsonDocument.FindMember(ClassNameTag)->value.GetString();
|
||||
|
||||
// validate class name
|
||||
auto classData = loadSettings.m_serializeContext->FindClassData(classId);
|
||||
if (!classData)
|
||||
{
|
||||
return AZ::Failure(AZStd::string::format("Try to load class from Id %s", classId.ToString<AZStd::string>().c_str()));
|
||||
}
|
||||
|
||||
if (azstricmp(classData->m_name, className) != 0)
|
||||
{
|
||||
return AZ::Failure(AZStd::string::format("Try to load class %s from class %s data", classData->m_name, className));
|
||||
}
|
||||
|
||||
JsonSerializationResult::ResultCode result = JsonSerialization::Load(objectToLoad, classId, jsonDocument.FindMember(ClassDataTag)->value, loadSettings);
|
||||
|
||||
if (!WasLoadSuccess(result.GetOutcome()) || !deserializeErrors.empty())
|
||||
{
|
||||
return AZ::Failure(deserializeErrors);
|
||||
}
|
||||
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
AZ::Outcome<void, AZStd::string> LoadObjectFromStreamByType(void* objectToLoad, const Uuid& classId, IO::GenericStream& stream,
|
||||
const JsonDeserializerSettings* settings)
|
||||
{
|
||||
|
||||
@@ -70,13 +70,18 @@ namespace AZ
|
||||
//! Parse json text. Returns a failure with error message if the content is not valid JSON.
|
||||
AZ::Outcome<rapidjson::Document, AZStd::string> ReadJsonString(AZStd::string_view jsonText);
|
||||
|
||||
//! Parse a json file. Returns a failure with error message if the content is not valid JSON.
|
||||
AZ::Outcome<rapidjson::Document, AZStd::string> ReadJsonFile(AZStd::string_view filePath);
|
||||
//! Parse a json file. Returns a failure with error message if the content is not valid JSON or if
|
||||
//! the file size is larger than the max file size provided.
|
||||
AZ::Outcome<rapidjson::Document, AZStd::string> ReadJsonFile(
|
||||
AZStd::string_view filePath, size_t maxFileSize = AZStd::numeric_limits<size_t>::max());
|
||||
|
||||
//! Parse a json stream. Returns a failure with error message if the content is not valid JSON.
|
||||
AZ::Outcome<rapidjson::Document, AZStd::string> ReadJsonStream(IO::GenericStream& stream);
|
||||
|
||||
//! Load object with known class type
|
||||
AZ::Outcome<void, AZStd::string> LoadObjectFromStringByType(void* objectToLoad, const Uuid& objectType, AZStd::string_view source,
|
||||
const JsonDeserializerSettings* settings = nullptr);
|
||||
|
||||
AZ::Outcome<void, AZStd::string> LoadObjectFromStreamByType(void* objectToLoad, const Uuid& objectType, IO::GenericStream& stream,
|
||||
const JsonDeserializerSettings* settings = nullptr);
|
||||
|
||||
|
||||
@@ -293,7 +293,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
AZ_Assert(!keyValues.Empty(), "Intermediate array for associative container can't be empty "
|
||||
"because an empty array would be stored as an empty default object.")
|
||||
"because an empty array would be stored as an empty default object.");
|
||||
|
||||
if (CanBeConvertedToObject(keyValues))
|
||||
{
|
||||
|
||||
@@ -46,7 +46,8 @@ namespace AZ
|
||||
public:
|
||||
AZ_RTTI(JsonUnorderedMapSerializer, "{EF4478D3-1820-4FDB-A7B7-C9711EB41602}", JsonMapSerializer);
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
|
||||
|
||||
using JsonMapSerializer::Store;
|
||||
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
|
||||
const Uuid& valueTypeId, JsonSerializerContext& context) override;
|
||||
};
|
||||
@@ -63,6 +64,7 @@ namespace AZ
|
||||
const SerializeContext::ClassElement* keyElement, const SerializeContext::ClassElement* valueElement,
|
||||
const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context) override;
|
||||
|
||||
using JsonMapSerializer::Store;
|
||||
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
|
||||
const Uuid& valueTypeId, JsonSerializerContext& context) override;
|
||||
};
|
||||
|
||||
@@ -2300,7 +2300,7 @@ namespace AZ
|
||||
{
|
||||
if (classData->m_converter)
|
||||
{
|
||||
AZ_Assert(false, "A deprecated element with a data converter was passed to CloneObject, this is not supported.")
|
||||
AZ_Assert(false, "A deprecated element with a data converter was passed to CloneObject, this is not supported.");
|
||||
}
|
||||
// push a dummy node in the stack
|
||||
cloneData->m_parentStack.push_back();
|
||||
|
||||
@@ -370,6 +370,11 @@ namespace AZ
|
||||
//! @param applyPatchSettings The ApplyPatchSettings which are using during JSON Merging
|
||||
virtual void SetApplyPatchSettings(const AZ::JsonApplyPatchSettings& applyPatchSettings) = 0;
|
||||
virtual void GetApplyPatchSettings(AZ::JsonApplyPatchSettings& applyPatchSettings) = 0;
|
||||
|
||||
//! Stores option to indicate whether the FileIOBase instance should be used for file operations
|
||||
//! @param useFileIo If true the FileIOBase instance will attempted to be used for FileIOBase
|
||||
//! operations before falling back to use SystemFile
|
||||
virtual void SetUseFileIO(bool useFileIo) = 0;
|
||||
};
|
||||
|
||||
inline SettingsRegistryInterface::Visitor::~Visitor() = default;
|
||||
|
||||
@@ -9,11 +9,14 @@
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/JSON/error/en.h>
|
||||
#include <AzCore/NativeUI//NativeUIRequests.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerialization.h>
|
||||
#include <AzCore/Serialization/Json/StackedString.h>
|
||||
#include <AzCore/Settings/SettingsRegistryImpl.h>
|
||||
#include <AzCore/std/containers/variant.h>
|
||||
#include <AzCore/std/sort.h>
|
||||
#include <AzCore/std/parallel/scoped_lock.h>
|
||||
|
||||
@@ -131,6 +134,12 @@ namespace AZ
|
||||
pointer.Create(m_settings, m_settings.GetAllocator()).SetArray();
|
||||
}
|
||||
|
||||
SettingsRegistryImpl::SettingsRegistryImpl(bool useFileIo)
|
||||
: SettingsRegistryImpl()
|
||||
{
|
||||
m_useFileIo = useFileIo;
|
||||
}
|
||||
|
||||
void SettingsRegistryImpl::SetContext(SerializeContext* context)
|
||||
{
|
||||
AZStd::scoped_lock lock(m_settingMutex);
|
||||
@@ -723,15 +732,10 @@ namespace AZ
|
||||
RegistryFileList fileList;
|
||||
scratchBuffer->clear();
|
||||
|
||||
AZ::IO::FixedMaxPathString folderPath{ path };
|
||||
constexpr AZStd::string_view pathSeparators{ AZ_CORRECT_AND_WRONG_DATABASE_SEPARATOR };
|
||||
if (pathSeparators.find_first_of(folderPath.back()) == AZStd::string_view::npos)
|
||||
{
|
||||
folderPath.push_back(AZ_CORRECT_DATABASE_SEPARATOR);
|
||||
}
|
||||
AZ::IO::FixedMaxPath folderPath{ path };
|
||||
|
||||
const size_t platformKeyOffset = folderPath.size();
|
||||
folderPath.push_back('*');
|
||||
const size_t platformKeyOffset = folderPath.Native().size();
|
||||
folderPath /= '*';
|
||||
|
||||
Value specialzationArray(kArrayType);
|
||||
size_t specializationCount = specializations.GetCount();
|
||||
@@ -741,47 +745,13 @@ namespace AZ
|
||||
specialzationArray.PushBack(Value(name.data(), aznumeric_caster(name.length()), m_settings.GetAllocator()), m_settings.GetAllocator());
|
||||
}
|
||||
pointer.Create(m_settings, m_settings.GetAllocator()).SetObject()
|
||||
.AddMember(StringRef("Folder"), Value(folderPath.c_str(), aznumeric_caster(folderPath.size()), m_settings.GetAllocator()), m_settings.GetAllocator())
|
||||
.AddMember(StringRef("Folder"), Value(folderPath.c_str(), aznumeric_caster(folderPath.Native().size()), m_settings.GetAllocator()), m_settings.GetAllocator())
|
||||
.AddMember(StringRef("Specializations"), AZStd::move(specialzationArray), m_settings.GetAllocator());
|
||||
|
||||
auto callback = [this, &fileList, &specializations, &pointer, &folderPath](const char* filename, bool isFile) -> bool
|
||||
|
||||
auto CreateSettingsFindCallback = [this, &fileList, &specializations, &pointer, &folderPath](bool isPlatformFile)
|
||||
{
|
||||
if (isFile)
|
||||
{
|
||||
if (fileList.size() >= MaxRegistryFolderEntries)
|
||||
{
|
||||
AZ_Error("Settings Registry", false, "Too many files in registry folder.");
|
||||
AZStd::scoped_lock lock(m_settingMutex);
|
||||
pointer.Create(m_settings, m_settings.GetAllocator()).SetObject()
|
||||
.AddMember(StringRef("Error"), StringRef("Too many files in registry folder."), m_settings.GetAllocator())
|
||||
.AddMember(StringRef("Path"), Value(folderPath.c_str(), aznumeric_caster(folderPath.size()), m_settings.GetAllocator()), m_settings.GetAllocator())
|
||||
.AddMember(StringRef("File"), Value(filename, m_settings.GetAllocator()), m_settings.GetAllocator());
|
||||
return false;
|
||||
}
|
||||
|
||||
fileList.push_back();
|
||||
RegistryFile& registryFile = fileList.back();
|
||||
if (!ExtractFileDescription(registryFile, filename, specializations))
|
||||
{
|
||||
fileList.pop_back();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
SystemFile::FindFiles(folderPath.c_str(), callback);
|
||||
|
||||
|
||||
if (!platform.empty())
|
||||
{
|
||||
// Move the folderPath prefix back to the supplied path before the wildcard
|
||||
folderPath.erase(platformKeyOffset);
|
||||
folderPath += PlatformFolder;
|
||||
folderPath.push_back(AZ_CORRECT_DATABASE_SEPARATOR);
|
||||
folderPath += platform;
|
||||
folderPath.push_back(AZ_CORRECT_DATABASE_SEPARATOR);
|
||||
folderPath.push_back('*');
|
||||
|
||||
auto platformCallback = [this, &fileList, &specializations, &pointer, &folderPath](const char* filename, bool isFile) -> bool
|
||||
return [this, &fileList, &specializations, &pointer, &folderPath, isPlatformFile](AZStd::string_view filename, bool isFile) -> bool
|
||||
{
|
||||
if (isFile)
|
||||
{
|
||||
@@ -791,8 +761,8 @@ namespace AZ
|
||||
AZStd::scoped_lock lock(m_settingMutex);
|
||||
pointer.Create(m_settings, m_settings.GetAllocator()).SetObject()
|
||||
.AddMember(StringRef("Error"), StringRef("Too many files in registry folder."), m_settings.GetAllocator())
|
||||
.AddMember(StringRef("Path"), Value(folderPath.c_str(), aznumeric_caster(folderPath.size()), m_settings.GetAllocator()), m_settings.GetAllocator())
|
||||
.AddMember(StringRef("File"), Value(filename, m_settings.GetAllocator()), m_settings.GetAllocator());
|
||||
.AddMember(StringRef("Path"), Value(folderPath.c_str(), aznumeric_caster(folderPath.Native().size()), m_settings.GetAllocator()), m_settings.GetAllocator())
|
||||
.AddMember(StringRef("File"), Value(filename.data(), aznumeric_caster(filename.size()), m_settings.GetAllocator()), m_settings.GetAllocator());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -800,7 +770,7 @@ namespace AZ
|
||||
RegistryFile& registryFile = fileList.back();
|
||||
if (ExtractFileDescription(registryFile, filename, specializations))
|
||||
{
|
||||
registryFile.m_isPlatformFile = true;
|
||||
registryFile.m_isPlatformFile = isPlatformFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -809,7 +779,42 @@ namespace AZ
|
||||
}
|
||||
return true;
|
||||
};
|
||||
SystemFile::FindFiles(folderPath.c_str(), platformCallback);
|
||||
};
|
||||
|
||||
struct FindFilesPayload
|
||||
{
|
||||
bool m_isPlatformFile{};
|
||||
AZStd::fixed_vector<AZStd::string_view, 2> m_pathSegmentsToAppend;
|
||||
};
|
||||
|
||||
AZStd::fixed_vector<FindFilesPayload, 2> findFilesPayloads{ {false} };
|
||||
if (!platform.empty())
|
||||
{
|
||||
findFilesPayloads.push_back(FindFilesPayload{ true, { PlatformFolder, platform } });
|
||||
}
|
||||
|
||||
for (const FindFilesPayload& findFilesPayload : findFilesPayloads)
|
||||
{
|
||||
// Erase back to initial path
|
||||
folderPath.Native().erase(platformKeyOffset);
|
||||
for (AZStd::string_view pathSegmentToAppend : findFilesPayload.m_pathSegmentsToAppend)
|
||||
{
|
||||
folderPath /= pathSegmentToAppend;
|
||||
}
|
||||
|
||||
auto findFilesCallback = CreateSettingsFindCallback(findFilesPayload.m_isPlatformFile);
|
||||
if (AZ::IO::FileIOBase* fileIo = m_useFileIo ? AZ::IO::FileIOBase::GetInstance() : nullptr; fileIo != nullptr)
|
||||
{
|
||||
auto FileIoToSystemFileFindFiles = [findFilesCallback = AZStd::move(findFilesCallback), fileIo](const char* filePath) -> bool
|
||||
{
|
||||
return findFilesCallback(AZ::IO::PathView(filePath).Filename().Native(), !fileIo->IsDirectory(filePath));
|
||||
};
|
||||
fileIo->FindFiles(folderPath.c_str(), "*", FileIoToSystemFileFindFiles);
|
||||
}
|
||||
else
|
||||
{
|
||||
SystemFile::FindFiles((folderPath / "*").c_str(), findFilesCallback);
|
||||
}
|
||||
}
|
||||
|
||||
if (!fileList.empty())
|
||||
@@ -831,16 +836,14 @@ namespace AZ
|
||||
// Load the registry files in the sorted order.
|
||||
for (RegistryFile& registryFile : fileList)
|
||||
{
|
||||
folderPath.erase(platformKeyOffset); // Erase all characters after the platformKeyOffset
|
||||
folderPath.Native().erase(platformKeyOffset); // Erase all characters after the platformKeyOffset
|
||||
if (registryFile.m_isPlatformFile)
|
||||
{
|
||||
folderPath += PlatformFolder;
|
||||
folderPath.push_back(AZ_CORRECT_DATABASE_SEPARATOR);
|
||||
folderPath += platform;
|
||||
folderPath.push_back(AZ_CORRECT_DATABASE_SEPARATOR);
|
||||
folderPath /= PlatformFolder;
|
||||
folderPath /= platform;
|
||||
}
|
||||
|
||||
folderPath += registryFile.m_relativePath;
|
||||
folderPath /= registryFile.m_relativePath;
|
||||
|
||||
if (!registryFile.m_isPatch)
|
||||
{
|
||||
@@ -1027,39 +1030,44 @@ namespace AZ
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SettingsRegistryImpl::ExtractFileDescription(RegistryFile& output, const char* filename, const Specializations& specializations)
|
||||
bool SettingsRegistryImpl::ExtractFileDescription(RegistryFile& output, AZStd::string_view filename, const Specializations& specializations)
|
||||
{
|
||||
if (!filename || filename[0] == 0)
|
||||
static constexpr auto PatchExtensionWithDot = AZStd::fixed_string<32>(".") + PatchExtension;
|
||||
static constexpr auto ExtensionWithDot = AZStd::fixed_string<32>(".") + Extension;
|
||||
static constexpr AZ::IO::PathView PatchExtensionView(PatchExtensionWithDot);
|
||||
static constexpr AZ::IO::PathView ExtensionView(ExtensionWithDot);
|
||||
|
||||
if (filename.empty())
|
||||
{
|
||||
AZ_Error("Settings Registry", false, "Settings file without name found");
|
||||
return false;
|
||||
}
|
||||
|
||||
AZStd::string_view filePath{ filename };
|
||||
const size_t filePathSize = filePath.size();
|
||||
AZ::IO::PathView filePath{ filename };
|
||||
const size_t filePathSize = filePath.Native().size();
|
||||
|
||||
// The filePath.empty() check makes sure that the file extension after the final <dot> isn't added to the output.m_tags
|
||||
AZStd::optional<AZStd::string_view> pathTag = AZ::StringFunc::TokenizeNext(filePath, '.');
|
||||
for (; pathTag && !filePath.empty(); pathTag = AZ::StringFunc::TokenizeNext(filePath, '.'))
|
||||
auto AppendSpecTags = [&output](AZStd::string_view pathTag)
|
||||
{
|
||||
output.m_tags.push_back(Specializations::Hash(*pathTag));
|
||||
}
|
||||
output.m_tags.push_back(Specializations::Hash(pathTag));
|
||||
};
|
||||
AZ::StringFunc::TokenizeVisitor(filePath.Stem().Native(), AppendSpecTags, '.');
|
||||
|
||||
// If token is invalid, then the filename has no <dot> characters and therefore no extension
|
||||
if (pathTag)
|
||||
if (AZ::IO::PathView fileExtension = filePath.Extension(); !fileExtension.empty())
|
||||
{
|
||||
if (pathTag->size() >= AZStd::char_traits<char>::length(PatchExtension) && azstrnicmp(pathTag->data(), PatchExtension, pathTag->size()) == 0)
|
||||
if (fileExtension == PatchExtensionView)
|
||||
{
|
||||
output.m_isPatch = true;
|
||||
}
|
||||
else if (pathTag->size() != AZStd::char_traits<char>::length(Extension) || azstrnicmp(pathTag->data(), Extension, pathTag->size()) != 0)
|
||||
else if (fileExtension != ExtensionView)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("Settings Registry", false, R"(Settings file without extension found: "%s")", filename);
|
||||
AZ_Error("Settings Registry", false, R"(Settings file without extension found: "%.*s")", AZ_STRING_ARG(filename));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1074,7 +1082,7 @@ namespace AZ
|
||||
{
|
||||
if (*currentIt == *(currentIt - 1))
|
||||
{
|
||||
AZ_Error("Settings Registry", false, R"(One or more tags are duplicated in registry file "%s")", filename);
|
||||
AZ_Error("Settings Registry", false, R"(One or more tags are duplicated in registry file "%.*s")", AZ_STRING_ARG(filename));
|
||||
return false;
|
||||
}
|
||||
++currentIt;
|
||||
@@ -1103,11 +1111,123 @@ namespace AZ
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("Settings Registry", false, R"(Found relative path to settings file "%s" is too long.)", filename);
|
||||
AZ_Error("Settings Registry", false, R"(Found relative path to settings file "%.*s" is too long.)", AZ_STRING_ARG(filename));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//! Structure which encapsulates Commands to either the FileIOBase or SystemFile classes based on
|
||||
//! the SettingsRegistry option to use FileIO
|
||||
struct SettingsRegistryFileReader
|
||||
{
|
||||
using FileHandleType = AZStd::variant<AZStd::monostate, AZ::IO::SystemFile, AZ::IO::HandleType>;
|
||||
|
||||
SettingsRegistryFileReader() = default;
|
||||
SettingsRegistryFileReader(bool useFileIo, const char* filePath)
|
||||
{
|
||||
Open(useFileIo, filePath);
|
||||
}
|
||||
|
||||
~SettingsRegistryFileReader()
|
||||
{
|
||||
if (auto fileHandle = AZStd::get_if<AZ::IO::HandleType>(&m_file); fileHandle != nullptr)
|
||||
{
|
||||
if (AZ::IO::FileIOBase* fileIo = AZ::IO::FileIOBase::GetInstance(); fileIo != nullptr)
|
||||
{
|
||||
fileIo->Close(*fileHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Open(bool useFileIo, const char* filePath)
|
||||
{
|
||||
Close();
|
||||
if (AZ::IO::FileIOBase* fileIo = useFileIo ? AZ::IO::FileIOBase::GetInstance() : nullptr; fileIo != nullptr)
|
||||
{
|
||||
AZ::IO::HandleType fileHandle;
|
||||
if (fileIo->Open(filePath, IO::OpenMode::ModeRead, fileHandle))
|
||||
{
|
||||
m_file = fileHandle;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ::IO::SystemFile file;
|
||||
if (file.Open(filePath, IO::SystemFile::OpenMode::SF_OPEN_READ_ONLY))
|
||||
{
|
||||
m_file = AZStd::move(file);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsOpen() const
|
||||
{
|
||||
if (auto fileHandle = AZStd::get_if<AZ::IO::HandleType>(&m_file); fileHandle != nullptr)
|
||||
{
|
||||
return *fileHandle != AZ::IO::InvalidHandle;
|
||||
}
|
||||
else if (auto systemFile = AZStd::get_if<AZ::IO::SystemFile>(&m_file); systemFile != nullptr)
|
||||
{
|
||||
return systemFile->IsOpen();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
if (auto fileHandle = AZStd::get_if<AZ::IO::HandleType>(&m_file); fileHandle != nullptr)
|
||||
{
|
||||
if (AZ::IO::FileIOBase* fileIo = AZ::IO::FileIOBase::GetInstance(); fileIo != nullptr)
|
||||
{
|
||||
fileIo->Close(*fileHandle);
|
||||
}
|
||||
}
|
||||
|
||||
m_file = AZStd::monostate{};
|
||||
}
|
||||
|
||||
u64 Length() const
|
||||
{
|
||||
if (auto fileHandle = AZStd::get_if<AZ::IO::HandleType>(&m_file); fileHandle != nullptr)
|
||||
{
|
||||
if (u64 fileSize{}; AZ::IO::FileIOBase::GetInstance()->Size(*fileHandle, fileSize))
|
||||
{
|
||||
return fileSize;
|
||||
}
|
||||
}
|
||||
else if (auto systemFile = AZStd::get_if<AZ::IO::SystemFile>(&m_file); systemFile != nullptr)
|
||||
{
|
||||
return systemFile->Length();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
AZ::IO::SizeType Read(AZ::IO::SizeType byteSize, void* buffer)
|
||||
{
|
||||
if (auto fileHandle = AZStd::get_if<AZ::IO::HandleType>(&m_file); fileHandle != nullptr)
|
||||
{
|
||||
if (AZ::u64 bytesRead{}; AZ::IO::FileIOBase::GetInstance()->Read(*fileHandle, buffer, byteSize, false, &bytesRead))
|
||||
{
|
||||
return bytesRead;
|
||||
}
|
||||
}
|
||||
else if (auto systemFile = AZStd::get_if<AZ::IO::SystemFile>(&m_file); systemFile != nullptr)
|
||||
{
|
||||
return systemFile->Read(byteSize, buffer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FileHandleType m_file;
|
||||
};
|
||||
|
||||
bool SettingsRegistryImpl::MergeSettingsFileInternal(const char* path, Format format, AZStd::string_view rootKey,
|
||||
AZStd::vector<char>& scratchBuffer)
|
||||
{
|
||||
@@ -1116,8 +1236,8 @@ namespace AZ
|
||||
|
||||
Pointer pointer(AZ_SETTINGS_REGISTRY_HISTORY_KEY "/-");
|
||||
|
||||
SystemFile file;
|
||||
if (!file.Open(path, SystemFile::OpenMode::SF_OPEN_READ_ONLY))
|
||||
SettingsRegistryFileReader fileReader(m_useFileIo, path);
|
||||
if (!fileReader.IsOpen())
|
||||
{
|
||||
AZ_Error("Settings Registry", false, R"(Unable to open registry file "%s".)", path);
|
||||
pointer.Create(m_settings, m_settings.GetAllocator()).SetObject()
|
||||
@@ -1126,7 +1246,7 @@ namespace AZ
|
||||
return false;
|
||||
}
|
||||
|
||||
u64 fileSize = file.Length();
|
||||
u64 fileSize = fileReader.Length();
|
||||
if (fileSize == 0)
|
||||
{
|
||||
AZ_Warning("Settings Registry", false, R"(Registry file "%s" is 0 bytes in length. There is no nothing to merge)", path);
|
||||
@@ -1136,9 +1256,10 @@ namespace AZ
|
||||
.AddMember(StringRef("Path"), Value(path, m_settings.GetAllocator()), m_settings.GetAllocator());
|
||||
return false;
|
||||
}
|
||||
|
||||
scratchBuffer.clear();
|
||||
scratchBuffer.resize_no_construct(fileSize + 1);
|
||||
if (file.Read(fileSize, scratchBuffer.data()) != fileSize)
|
||||
if (fileReader.Read(fileSize, scratchBuffer.data()) != fileSize)
|
||||
{
|
||||
AZ_Error("Settings Registry", false, R"(Unable to read registry file "%s".)", path);
|
||||
pointer.Create(m_settings, m_settings.GetAllocator()).SetObject()
|
||||
@@ -1268,4 +1389,9 @@ namespace AZ
|
||||
{
|
||||
applyPatchSettings = m_applyPatchSettings;
|
||||
}
|
||||
|
||||
void SettingsRegistryImpl::SetUseFileIO(bool useFileIo)
|
||||
{
|
||||
m_useFileIo = useFileIo;
|
||||
}
|
||||
} // namespace AZ
|
||||
|
||||
@@ -35,6 +35,10 @@ namespace AZ
|
||||
static constexpr size_t MaxRegistryFolderEntries = 128;
|
||||
|
||||
SettingsRegistryImpl();
|
||||
//! @param useFileIo - If true attempt to redirect
|
||||
//! file read operations through the FileIOBase instance first before falling back to SystemFile
|
||||
//! otherwise always use SystemFile
|
||||
explicit SettingsRegistryImpl(bool useFileIo);
|
||||
AZ_DISABLE_COPY_MOVE(SettingsRegistryImpl);
|
||||
~SettingsRegistryImpl() override = default;
|
||||
|
||||
@@ -83,6 +87,8 @@ namespace AZ
|
||||
void SetApplyPatchSettings(const AZ::JsonApplyPatchSettings& applyPatchSettings) override;
|
||||
void GetApplyPatchSettings(AZ::JsonApplyPatchSettings& applyPatchSettings) override;
|
||||
|
||||
void SetUseFileIO(bool useFileIo) override;
|
||||
|
||||
private:
|
||||
using TagList = AZStd::fixed_vector<size_t, Specializations::MaxCount + 1>;
|
||||
struct RegistryFile
|
||||
@@ -104,7 +110,7 @@ namespace AZ
|
||||
// Compares if lhs is less than rhs in terms of processing order. This can also detect and report conflicts.
|
||||
bool IsLessThan(bool& collisionFound, const RegistryFile& lhs, const RegistryFile& rhs, const Specializations& specializations,
|
||||
const rapidjson::Pointer& historyPointer, AZStd::string_view folderPath);
|
||||
bool ExtractFileDescription(RegistryFile& output, const char* filename, const Specializations& specializations);
|
||||
bool ExtractFileDescription(RegistryFile& output, AZStd::string_view filename, const Specializations& specializations);
|
||||
bool MergeSettingsFileInternal(const char* path, Format format, AZStd::string_view rootKey, AZStd::vector<char>& scratchBuffer);
|
||||
|
||||
void SignalNotifier(AZStd::string_view jsonPath, Type type);
|
||||
@@ -119,5 +125,7 @@ namespace AZ
|
||||
JsonSerializerSettings m_serializationSettings;
|
||||
JsonDeserializerSettings m_deserializationSettings;
|
||||
JsonApplyPatchSettings m_applyPatchSettings;
|
||||
|
||||
bool m_useFileIo{};
|
||||
};
|
||||
} // namespace AZ
|
||||
|
||||
@@ -78,6 +78,7 @@ namespace AZ::Internal
|
||||
|
||||
struct EnginePathsVisitor : public AZ::SettingsRegistryInterface::Visitor
|
||||
{
|
||||
using AZ::SettingsRegistryInterface::Visitor::Visit;
|
||||
void Visit(
|
||||
[[maybe_unused]] AZStd::string_view path, AZStd::string_view valueName,
|
||||
[[maybe_unused]] AZ::SettingsRegistryInterface::Type type, AZStd::string_view value) override
|
||||
@@ -109,12 +110,12 @@ namespace AZ::Internal
|
||||
{
|
||||
FixedValueString engineName;
|
||||
settingsRegistry.Get(engineName, engineMonikerKey);
|
||||
AZ_Warning("SettingsRegistryMergeUtils",engineInfo.m_moniker == engineName,
|
||||
AZ_Warning("SettingsRegistryMergeUtils", engineInfo.m_moniker == engineName,
|
||||
R"(The engine name key "%s" mapped to engine path "%s" within the global manifest of "%s")"
|
||||
R"( does not match the "engine_name" field "%s" in the engine.json)" "\n"
|
||||
"This engine should be re-registered.",
|
||||
engineInfo.m_moniker.c_str(), engineInfo.m_path.c_str(), engineManifestPath.c_str(),
|
||||
engineName.c_str())
|
||||
engineName.c_str());
|
||||
engineInfo.m_moniker = engineName;
|
||||
}
|
||||
}
|
||||
@@ -355,6 +356,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
: m_settingsSpecialization{ specializations }
|
||||
{}
|
||||
|
||||
using AZ::SettingsRegistryInterface::Visitor::Visit;
|
||||
void Visit([[maybe_unused]] AZStd::string_view path, AZStd::string_view valueName,
|
||||
[[maybe_unused]] AZ::SettingsRegistryInterface::Type type, bool value) override
|
||||
{
|
||||
@@ -761,6 +763,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
return SettingsRegistryInterface::VisitResponse::Continue;
|
||||
}
|
||||
|
||||
using AZ::SettingsRegistryInterface::Visitor::Visit;
|
||||
void Visit(AZStd::string_view, [[maybe_unused]] AZStd::string_view valueName, SettingsRegistryInterface::Type, AZStd::string_view value) override
|
||||
{
|
||||
if (processingSourcePathKey)
|
||||
@@ -896,6 +899,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
struct CommandLineVisitor
|
||||
: AZ::SettingsRegistryInterface::Visitor
|
||||
{
|
||||
using AZ::SettingsRegistryInterface::Visitor::Visit;
|
||||
void Visit(AZStd::string_view, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type
|
||||
, AZStd::string_view value) override
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/IO/ByteContainerStream.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Settings/SettingsRegistryImpl.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
|
||||
@@ -3464,7 +3464,7 @@ namespace AZ
|
||||
const SliceComponent::DataFlagsPerEntity* SliceComponent::GetCorrectBundleOfDataFlags(EntityId entityId) const
|
||||
{
|
||||
// It would be possible to search non-instantiated slices by crawling over lists, but we haven't needed the capability yet.
|
||||
AZ_Assert(IsInstantiated(), "Data flag access is only permitted after slice is instantiated.")
|
||||
AZ_Assert(IsInstantiated(), "Data flag access is only permitted after slice is instantiated.");
|
||||
|
||||
if (IsInstantiated())
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/RTTI/TypeSafeIntegral.h>
|
||||
#include <AzCore/std/time.h>
|
||||
#include <AzCore/std/chrono/chrono.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -25,6 +26,13 @@ namespace AZ
|
||||
|
||||
//! @class ITime
|
||||
//! @brief This is an AZ::Interface<> for managing time related operations.
|
||||
//! AZ::ITime and associated types may not operate in realtime. These abstractions are to allow our application
|
||||
//! simulation to operate both slower and faster than realtime in a well defined and user controllable manner
|
||||
//! The rate at which time passes for AZ::ITime is controlled by the cvar t_scale
|
||||
//! t_scale == 0 means simulation time should halt
|
||||
//! 0 < t_scale < 1 will cause time to pass slower than realtime, with t_scale 0.1 being roughly 1/10th realtime
|
||||
//! t_scale == 1 will cause time to pass at roughly realtime
|
||||
//! t_scale > 1 will cause time to pass faster than normal, with t_scale 10 being roughly 10x realtime
|
||||
class ITime
|
||||
{
|
||||
public:
|
||||
@@ -89,6 +97,22 @@ namespace AZ
|
||||
{
|
||||
return static_cast<float>(value) / 1000000.0f;
|
||||
}
|
||||
|
||||
//! Converts from milliseconds to AZStd::chrono::time_point
|
||||
inline auto TimeMsToChrono(TimeMs value)
|
||||
{
|
||||
auto epoch = AZStd::chrono::time_point<AZStd::chrono::high_resolution_clock>();
|
||||
auto chronoValue = AZStd::chrono::milliseconds(aznumeric_cast<int64_t>(value));
|
||||
return epoch + chronoValue;
|
||||
}
|
||||
|
||||
//! Converts from microseconds to AZStd::chrono::time_point
|
||||
inline auto TimeUsToChrono(TimeUs value)
|
||||
{
|
||||
auto epoch = AZStd::chrono::time_point<AZStd::chrono::high_resolution_clock>();
|
||||
auto chronoValue = AZStd::chrono::microseconds(aznumeric_cast<int64_t>(value));
|
||||
return epoch + chronoValue;
|
||||
}
|
||||
} // namespace AZ
|
||||
|
||||
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(AZ::TimeMs);
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace AZ
|
||||
|
||||
MOCK_METHOD1(SetApplyPatchSettings, void(const JsonApplyPatchSettings&));
|
||||
MOCK_METHOD1(GetApplyPatchSettings, void(JsonApplyPatchSettings&));
|
||||
MOCK_METHOD1(SetUseFileIO, void(bool));
|
||||
};
|
||||
} // namespace AZ
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace UnitTest
|
||||
|
||||
virtual ~AllocatorsBase() = default;
|
||||
|
||||
void SetupAllocator()
|
||||
void SetupAllocator(const AZ::SystemAllocator::Descriptor& allocatorDesc = {})
|
||||
{
|
||||
m_drillerManager = AZ::Debug::DrillerManager::Create();
|
||||
m_drillerManager->Register(aznew AZ::Debug::MemoryDriller);
|
||||
@@ -54,7 +54,7 @@ namespace UnitTest
|
||||
// Only create the SystemAllocator if it s not ready
|
||||
if (!AZ::AllocatorInstance<AZ::SystemAllocator>::IsReady())
|
||||
{
|
||||
AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
|
||||
AZ::AllocatorInstance<AZ::SystemAllocator>::Create(allocatorDesc);
|
||||
m_ownsAllocator = true;
|
||||
}
|
||||
}
|
||||
@@ -85,6 +85,7 @@ namespace UnitTest
|
||||
{
|
||||
public:
|
||||
ScopedAllocatorSetupFixture() { SetupAllocator(); }
|
||||
explicit ScopedAllocatorSetupFixture(const AZ::SystemAllocator::Descriptor& allocatorDesc) { SetupAllocator(allocatorDesc); }
|
||||
~ScopedAllocatorSetupFixture() { TeardownAllocator(); }
|
||||
};
|
||||
|
||||
@@ -130,17 +131,23 @@ namespace UnitTest
|
||||
, public AllocatorsBase
|
||||
{
|
||||
public:
|
||||
// Bring in both const and non-const SetUp and TearDown function into scope to resolve warning 4266
|
||||
// no override available for virtual member function from base 'benchmark::Fixture'; function is hidden
|
||||
using ::benchmark::Fixture::SetUp, ::benchmark::Fixture::TearDown;
|
||||
|
||||
//Benchmark interface
|
||||
void SetUp(const ::benchmark::State& st) override
|
||||
{
|
||||
AZ_UNUSED(st);
|
||||
SetupAllocator();
|
||||
}
|
||||
void SetUp(::benchmark::State& st) override
|
||||
{
|
||||
AZ_UNUSED(st);
|
||||
SetupAllocator();
|
||||
}
|
||||
|
||||
void TearDown(const ::benchmark::State& st) override
|
||||
{
|
||||
AZ_UNUSED(st);
|
||||
TeardownAllocator();
|
||||
}
|
||||
void TearDown(::benchmark::State& st) override
|
||||
{
|
||||
AZ_UNUSED(st);
|
||||
|
||||
@@ -116,9 +116,9 @@ namespace AZ
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// UserSettingsBus
|
||||
virtual AZStd::intrusive_ptr<UserSettings> FindUserSettings(u32 id);
|
||||
virtual void AddUserSettings(u32 id, UserSettings* settings);
|
||||
virtual bool Save(const char* settingsPath, SerializeContext* sc);
|
||||
AZStd::intrusive_ptr<UserSettings> FindUserSettings(u32 id) override;
|
||||
void AddUserSettings(u32 id, UserSettings* settings) override;
|
||||
bool Save(const char* settingsPath, SerializeContext* sc) override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void Reflect(ReflectContext* reflection);
|
||||
|
||||
@@ -22,10 +22,6 @@ namespace AZ
|
||||
{
|
||||
namespace Utils
|
||||
{
|
||||
//! Protects from allocating too much memory. The choice of a 1MB threshold is arbitrary.
|
||||
//! If you need to work with larger files, please use AZ::IO directly instead of these utility functions.
|
||||
inline constexpr size_t DefaultMaxFileSize = 5 * 1024 * 1024;
|
||||
|
||||
//! Terminates the application without going through the shutdown procedure.
|
||||
//! This is used when due to abnormal circumstances the application can no
|
||||
//! longer continue. On most platforms and in most configurations this will
|
||||
@@ -115,6 +111,7 @@ namespace AZ
|
||||
//! Read a file into a string. Returns a failure with error message if the content could not be loaded or if
|
||||
//! the file size is larger than the max file size provided.
|
||||
template<typename Container = AZStd::string>
|
||||
AZ::Outcome<Container, AZStd::string> ReadFile(AZStd::string_view filePath, size_t maxFileSize = DefaultMaxFileSize);
|
||||
AZ::Outcome<Container, AZStd::string> ReadFile(
|
||||
AZStd::string_view filePath, size_t maxFileSize = AZStd::numeric_limits<size_t>::max());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
// the intention is that you only include the customized version of rapidXML through this header, so that
|
||||
// you can override behavior here.
|
||||
#include <stdio.h>
|
||||
#include <rapidxml/rapidxml.h>
|
||||
|
||||
#endif // AZCORE_RAPIDXML_RAPIDXML_H_INCLUDED
|
||||
|
||||
@@ -35,6 +35,7 @@ set(FILES
|
||||
Asset/AssetInternal/WeakAsset.h
|
||||
Casting/lossy_cast.h
|
||||
Casting/numeric_cast.h
|
||||
Casting/numeric_cast_internal.h
|
||||
Component/Component.cpp
|
||||
Component/Component.h
|
||||
Component/ComponentApplication.cpp
|
||||
@@ -176,6 +177,8 @@ set(FILES
|
||||
IO/Path/Path.cpp
|
||||
IO/Path/Path.h
|
||||
IO/Path/Path.inl
|
||||
IO/Path/PathIterable.inl
|
||||
IO/Path/PathParser.inl
|
||||
IO/Path/Path_fwd.h
|
||||
IO/SystemFile.cpp
|
||||
IO/SystemFile.h
|
||||
@@ -440,6 +443,7 @@ set(FILES
|
||||
RTTI/AttributeReader.h
|
||||
RTTI/AzStdOnDemandPrettyName.inl
|
||||
RTTI/AzStdOnDemandReflection.inl
|
||||
RTTI/AzStdOnDemandReflectionSpecializations.cpp
|
||||
RTTI/AzStdOnDemandReflectionLuaFunctions.inl
|
||||
RTTI/BehaviorContext.cpp
|
||||
RTTI/BehaviorContext.h
|
||||
|
||||
@@ -143,6 +143,9 @@
|
||||
* example. AZ_VA_NUM_ARGS(x,y,z) -> expands to 3
|
||||
*/
|
||||
#ifndef AZ_VA_NUM_ARGS
|
||||
|
||||
# define AZ_VA_HAS_ARGS(...) ""#__VA_ARGS__[0] != 0
|
||||
|
||||
// we add the zero to avoid the case when we require at least 1 param at the end...
|
||||
# define AZ_VA_NUM_ARGS(...) AZ_VA_NUM_ARGS_IMPL_((__VA_ARGS__, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
|
||||
# define AZ_VA_NUM_ARGS_IMPL_(tuple) AZ_VA_NUM_ARGS_IMPL tuple
|
||||
@@ -170,15 +173,15 @@
|
||||
// This is a pain they we use macros to call functions (with no params).
|
||||
|
||||
// we implement functions for up to 10 params
|
||||
#define AZ_FUNCTION_CALL_1(_1) _1()
|
||||
#define AZ_FUNCTION_CALL_2(_1, _2) _1(_2)
|
||||
#define AZ_FUNCTION_CALL_3(_1, _2, _3) _1(_2, _3)
|
||||
#define AZ_FUNCTION_CALL_4(_1, _2, _3, _4) _1(_2, _3, _4)
|
||||
#define AZ_FUNCTION_CALL_5(_1, _2, _3, _4, _5) _1(_2, _3, _4, _5)
|
||||
#define AZ_FUNCTION_CALL_6(_1, _2, _3, _4, _5, _6) _1(_2, _3, _4, _5, _6)
|
||||
#define AZ_FUNCTION_CALL_7(_1, _2, _3, _4, _5, _6, _7) _1(_2, _3, _4, _5, _6, _7)
|
||||
#define AZ_FUNCTION_CALL_8(_1, _2, _3, _4, _5, _6, _7, _8) _1(_2, _3, _4, _5, _6, _7, _8)
|
||||
#define AZ_FUNCTION_CALL_9(_1, _2, _3, _4, _5, _6, _7, _8, _9) _1(_2, _3, _4, _5, _6, _7, _8, _9)
|
||||
#define AZ_FUNCTION_CALL_1(_1) _1()
|
||||
#define AZ_FUNCTION_CALL_2(_1, _2) _1(_2)
|
||||
#define AZ_FUNCTION_CALL_3(_1, _2, _3) _1(_2, _3)
|
||||
#define AZ_FUNCTION_CALL_4(_1, _2, _3, _4) _1(_2, _3, _4)
|
||||
#define AZ_FUNCTION_CALL_5(_1, _2, _3, _4, _5) _1(_2, _3, _4, _5)
|
||||
#define AZ_FUNCTION_CALL_6(_1, _2, _3, _4, _5, _6) _1(_2, _3, _4, _5, _6)
|
||||
#define AZ_FUNCTION_CALL_7(_1, _2, _3, _4, _5, _6, _7) _1(_2, _3, _4, _5, _6, _7)
|
||||
#define AZ_FUNCTION_CALL_8(_1, _2, _3, _4, _5, _6, _7, _8) _1(_2, _3, _4, _5, _6, _7, _8)
|
||||
#define AZ_FUNCTION_CALL_9(_1, _2, _3, _4, _5, _6, _7, _8, _9) _1(_2, _3, _4, _5, _6, _7, _8, _9)
|
||||
#define AZ_FUNCTION_CALL_10(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) _1(_2, _3, _4, _5, _6, _7, _8, _9, _10)
|
||||
|
||||
// We require at least 1 param FunctionName
|
||||
@@ -293,7 +296,20 @@ namespace AZ
|
||||
#define AZ_DEFAULT_COPY_MOVE(_Class) AZ_DEFAULT_COPY(_Class) AZ_DEFAULT_MOVE(_Class)
|
||||
|
||||
// Macro that can be used to avoid unreferenced variable warnings
|
||||
#define AZ_UNUSED(x) (void)x
|
||||
#define AZ_UNUSED_1(x) (void)(x);
|
||||
#define AZ_UNUSED_2(x1, x2) AZ_UNUSED_1(x1) AZ_UNUSED_1(x2)
|
||||
#define AZ_UNUSED_3(x1, x2, x3) AZ_UNUSED_1(x1) AZ_UNUSED_2(x2, x3)
|
||||
#define AZ_UNUSED_4(x1, x2, x3, x4) AZ_UNUSED_2(x1, x2) AZ_UNUSED_2(x3, x4)
|
||||
#define AZ_UNUSED_5(x1, x2, x3, x4, x5) AZ_UNUSED_2(x1, x2) AZ_UNUSED_3(x3, x4, x5)
|
||||
#define AZ_UNUSED_6(x1, x2, x3, x4, x5, x6) AZ_UNUSED_3(x1, x2, x3) AZ_UNUSED_3(x4, x5, x6)
|
||||
#define AZ_UNUSED_7(x1, x2, x3, x4, x5, x6, x7) AZ_UNUSED_3(x1, x2, x3) AZ_UNUSED_4(x4, x5, x6, x7)
|
||||
#define AZ_UNUSED_8(x1, x2, x3, x4, x5, x6, x7, x8) AZ_UNUSED_4(x1, x2, x3, x4) AZ_UNUSED_4(x5, x6, x7, x8)
|
||||
#define AZ_UNUSED_9(x1, x2, x3, x4, x5, x6, x7, x8, x9) AZ_UNUSED_4(x1, x2, x3, x4) AZ_UNUSED_5(x5, x6, x7, x8, x9)
|
||||
#define AZ_UNUSED_10(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10) AZ_UNUSED_5(x1, x2, x3, x4, x5) AZ_UNUSED_5(x6, x7, x8, x9, x10)
|
||||
#define AZ_UNUSED_11(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11) AZ_UNUSED_5(x1, x2, x3, x4, x5) AZ_UNUSED_6(x6, x7, x8, x9, x10, x11)
|
||||
#define AZ_UNUSED_12(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) AZ_UNUSED_6(x1, x2, x3, x4, x5, x6) AZ_UNUSED_6(x7, x8, x9, x10, x11, x12)
|
||||
|
||||
#define AZ_UNUSED(...) AZ_MACRO_SPECIALIZE(AZ_UNUSED_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
|
||||
|
||||
#define AZ_DEFINE_ENUM_BITWISE_OPERATORS(EnumType) \
|
||||
inline constexpr EnumType operator | (EnumType a, EnumType b) \
|
||||
|
||||
@@ -831,7 +831,6 @@ namespace AZStd
|
||||
// find first element that value is before, using operator<
|
||||
typename iterator_traits<ForwardIterator>::difference_type count = AZStd::distance(first, last);
|
||||
typename iterator_traits<ForwardIterator>::difference_type step{};
|
||||
count = AZStd::distance(first, last);
|
||||
for (; 0 < count; )
|
||||
{ // divide and conquer, find half that contains answer
|
||||
step = count / 2;
|
||||
|
||||
@@ -40,15 +40,11 @@ namespace AZStd
|
||||
return AZ::AllocatorInstance<AZ::SystemAllocator>::Get().Resize(ptr, newSize);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// get_max_size
|
||||
// [1/1/2008]
|
||||
//=========================================================================
|
||||
allocator::size_type
|
||||
allocator::get_max_size() const
|
||||
auto allocator::max_size() const -> size_type
|
||||
{
|
||||
return AZ::AllocatorInstance<AZ::SystemAllocator>::Get().GetMaxAllocationSize();
|
||||
return AZ::AllocatorInstance<AZ::SystemAllocator>::Get().GetMaxContiguousAllocationSize();
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// get_allocated_size
|
||||
// [1/1/2008]
|
||||
|
||||
@@ -49,8 +49,8 @@ namespace AZStd
|
||||
* const char* get_name() const;
|
||||
* void set_name(const char* name);
|
||||
*
|
||||
* // Returns maximum size we can allocate from this allocator.
|
||||
* size_type get_max_size() const;
|
||||
* // Returns theoretical maximum size of a single contiguous allocation from this allocator.
|
||||
* size_type max_size() const;
|
||||
* <optional> size_type get_allocated_size() const;
|
||||
* };
|
||||
*
|
||||
@@ -100,7 +100,8 @@ namespace AZStd
|
||||
pointer_type allocate(size_type byteSize, size_type alignment, int flags = 0);
|
||||
void deallocate(pointer_type ptr, size_type byteSize, size_type alignment);
|
||||
size_type resize(pointer_type ptr, size_type newSize);
|
||||
size_type get_max_size() const;
|
||||
// max_size actually returns the true maximum size of a single allocation
|
||||
size_type max_size() const;
|
||||
size_type get_allocated_size() const;
|
||||
|
||||
AZ_FORCE_INLINE bool is_lock_free() { return false; }
|
||||
@@ -157,7 +158,7 @@ namespace AZStd
|
||||
AZ_FORCE_INLINE const char* get_name() const;
|
||||
AZ_FORCE_INLINE void set_name(const char* name);
|
||||
|
||||
AZ_FORCE_INLINE size_type get_max_size() const;
|
||||
AZ_FORCE_INLINE size_type max_size() const;
|
||||
|
||||
AZ_FORCE_INLINE bool is_lock_free();
|
||||
AZ_FORCE_INLINE bool is_stale_read_allowed();
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace AZStd
|
||||
AZ_FORCE_INLINE const char* get_name() const { return m_name; }
|
||||
AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; }
|
||||
|
||||
AZ_FORCE_INLINE size_type get_max_size() const { return m_allocator->get_max_size(); }
|
||||
constexpr size_type max_size() const { return m_allocator->max_size(); }
|
||||
|
||||
AZ_FORCE_INLINE size_type get_allocated_size() const { return m_allocator->get_allocated_size(); }
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace AZStd
|
||||
|
||||
AZ_FORCE_INLINE const char* get_name() const { return m_name; }
|
||||
AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; }
|
||||
AZ_FORCE_INLINE size_type get_max_size() const { return m_size - (m_freeData - m_data); }
|
||||
constexpr size_type max_size() const { return m_size; }
|
||||
AZ_FORCE_INLINE size_type get_allocated_size() const { return m_freeData - m_data; }
|
||||
|
||||
pointer_type allocate(size_type byteSize, size_type alignment, int flags = 0)
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace AZStd
|
||||
|
||||
AZ_FORCE_INLINE const char* get_name() const { return m_name; }
|
||||
AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; }
|
||||
AZ_FORCE_INLINE size_type get_max_size() const { return Size - (m_freeData - reinterpret_cast<const char*>(&m_data)); }
|
||||
constexpr size_type max_size() const { return Size; }
|
||||
AZ_FORCE_INLINE size_type get_allocated_size() const { return m_freeData - reinterpret_cast<const char*>(&m_data); }
|
||||
|
||||
pointer_type allocate(size_type byteSize, size_type alignment, int flags = 0)
|
||||
@@ -190,7 +190,7 @@ namespace AZStd
|
||||
|
||||
AZ_FORCE_INLINE const char* get_name() const { return m_name; }
|
||||
AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; }
|
||||
AZ_FORCE_INLINE size_type get_max_size() const { return (NumNodes - m_numOfAllocatedNodes) * sizeof(Node); }
|
||||
constexpr size_type max_size() const { return NumNodes * sizeof(Node); }
|
||||
AZ_FORCE_INLINE size_type get_allocated_size() const { return m_numOfAllocatedNodes * sizeof(Node); }
|
||||
|
||||
inline Node* allocate()
|
||||
|
||||
@@ -6,11 +6,10 @@
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef AZSTD_DEQUE_H
|
||||
#define AZSTD_DEQUE_H 1
|
||||
|
||||
|
||||
#include <AzCore/std/allocator.h>
|
||||
#include <AzCore/std/allocator_traits.h>
|
||||
#include <AzCore/std/algorithm.h>
|
||||
#include <AzCore/std/createdestroy.h>
|
||||
#include <AzCore/std/typetraits/aligned_storage.h>
|
||||
@@ -350,7 +349,7 @@ namespace AZStd
|
||||
}
|
||||
|
||||
AZ_FORCE_INLINE size_type size() const { return m_size; }
|
||||
AZ_FORCE_INLINE size_type max_size() const { return m_allocator.get_max_size() / sizeof(block_node_type); }
|
||||
AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits<allocator_type>::max_size(m_allocator) / sizeof(block_node_type); }
|
||||
AZ_FORCE_INLINE bool empty() const { return m_size == 0; }
|
||||
|
||||
AZ_FORCE_INLINE const_reference at(size_type offset) const { return *const_iterator(AZSTD_CHECKED_ITERATOR_2(const_iterator_impl, m_firstOffset + offset, this)); }
|
||||
@@ -1243,5 +1242,3 @@ namespace AZStd
|
||||
return removedCount;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // AZSTD_DEQUE_H
|
||||
|
||||
@@ -286,7 +286,7 @@ namespace AZStd
|
||||
}
|
||||
|
||||
AZ_FORCE_INLINE size_type size() const { return m_numElements; }
|
||||
AZ_FORCE_INLINE size_type max_size() const { return m_allocator.max_size() / sizeof(node_type); }
|
||||
AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits<allocator_type>::max_size(m_allocator) / sizeof(node_type); }
|
||||
AZ_FORCE_INLINE bool empty() const { return (m_numElements == 0); }
|
||||
|
||||
AZ_FORCE_INLINE iterator begin() { return iterator(AZSTD_CHECKED_ITERATOR(iterator_impl, m_head.m_next)); }
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#ifndef AZSTD_LIST_H
|
||||
#define AZSTD_LIST_H 1
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/allocator.h>
|
||||
#include <AzCore/std/allocator_traits.h>
|
||||
#include <AzCore/std/algorithm.h>
|
||||
#include <AzCore/std/createdestroy.h>
|
||||
#include <AzCore/std/typetraits/alignment_of.h>
|
||||
@@ -316,7 +316,7 @@ namespace AZStd
|
||||
}
|
||||
|
||||
AZ_FORCE_INLINE size_type size() const { return m_numElements; }
|
||||
AZ_FORCE_INLINE size_type max_size() const { return m_allocator.max_size() / sizeof(node_type); }
|
||||
AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits<allocator_type>::max_size(m_allocator) / sizeof(node_type); }
|
||||
AZ_FORCE_INLINE bool empty() const { return (m_numElements == 0); }
|
||||
|
||||
AZ_FORCE_INLINE iterator begin() { return iterator(AZSTD_CHECKED_ITERATOR(iterator_impl, m_head.m_next)); }
|
||||
@@ -1346,5 +1346,3 @@ namespace AZStd
|
||||
return container.remove_if(predicate);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // AZSTD_LIST_H
|
||||
|
||||
@@ -484,7 +484,7 @@ namespace AZStd
|
||||
|
||||
AZ_FORCE_INLINE bool empty() const { return m_numElements == 0; }
|
||||
AZ_FORCE_INLINE size_type size() const { return m_numElements; }
|
||||
AZ_FORCE_INLINE size_type max_size() const { return m_allocator.max_size() / sizeof(node_type); }
|
||||
AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits<allocator_type>::max_size(m_allocator) / sizeof(node_type); }
|
||||
|
||||
rbtree(this_type&& rhs)
|
||||
: m_numElements(0) // it will be set during swap
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#ifndef AZSTD_RINGBUFFER_H
|
||||
#define AZSTD_RINGBUFFER_H 1
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/allocator.h>
|
||||
#include <AzCore/std/allocator_traits.h>
|
||||
#include <AzCore/std/algorithm.h>
|
||||
#include <AzCore/std/createdestroy.h>
|
||||
#include <AzCore/std/utils.h>
|
||||
@@ -416,7 +417,7 @@ namespace AZStd
|
||||
}
|
||||
|
||||
AZ_FORCE_INLINE size_type size() const { return m_size; }
|
||||
AZ_FORCE_INLINE size_type max_size() const { return m_allocator.max_size() / sizeof(node_type); }
|
||||
AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits<allocator_type>::max_size(m_allocator) / sizeof(node_type); }
|
||||
AZ_FORCE_INLINE bool empty() const { return m_size == 0; }
|
||||
AZ_FORCE_INLINE bool full() const { return size_type(m_end - m_buff) == m_size; }
|
||||
AZ_FORCE_INLINE size_type free() const { return size_type(m_end - m_buff) - m_size; }
|
||||
@@ -1240,6 +1241,3 @@ namespace AZStd
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // AZSTD_RINGBUFFER_H
|
||||
#pragma once
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <AzCore/std/allocator.h>
|
||||
#include <AzCore/std/algorithm.h>
|
||||
#include <AzCore/std/allocator_traits.h>
|
||||
#include <AzCore/std/createdestroy.h>
|
||||
#include <AzCore/std/typetraits/alignment_of.h>
|
||||
#include <AzCore/std/typetraits/is_integral.h>
|
||||
@@ -431,7 +432,7 @@ namespace AZStd
|
||||
}
|
||||
|
||||
AZ_FORCE_INLINE size_type size() const { return m_last - m_start; }
|
||||
AZ_FORCE_INLINE size_type max_size() const { return m_allocator.get_max_size() / sizeof(node_type); }
|
||||
AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits<allocator_type>::max_size(m_allocator) / sizeof(node_type); }
|
||||
AZ_FORCE_INLINE bool empty() const { return m_start == m_last; }
|
||||
|
||||
void reserve(size_type numElements)
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace AZStd
|
||||
* Internally the buffer is allocated using aligned_storage.
|
||||
* \note only allocate/deallocate are thread safe.
|
||||
* reset, leak_before_destroy and comparison operators are not thread safe.
|
||||
* get_max_size and get_allocated_size are thread safe but the returned value is not perfectly in
|
||||
* get_allocated_size is thread safe but the returned value is not perfectly in
|
||||
* sync on the actual number of allocations (the number of allocations is incremented before the
|
||||
* allocation happens and decremented after the allocation happens, trying to give a conservative
|
||||
* number)
|
||||
@@ -71,7 +71,7 @@ namespace AZStd
|
||||
|
||||
AZ_FORCE_INLINE const char* get_name() const { return m_name; }
|
||||
AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; }
|
||||
AZ_FORCE_INLINE size_type get_max_size() const { return (NumNodes - m_numOfAllocatedNodes.load(AZStd::memory_order_relaxed)) * sizeof(Node); }
|
||||
constexpr size_type max_size() const { return NumNodes * sizeof(Node); }
|
||||
AZ_FORCE_INLINE size_type get_allocated_size() const { return m_numOfAllocatedNodes.load(AZStd::memory_order_relaxed) * sizeof(Node); }
|
||||
|
||||
inline Node* allocate()
|
||||
|
||||
@@ -187,7 +187,7 @@ namespace AZStd
|
||||
: m_f(AZStd::move(f)) {}
|
||||
thread_info_impl(Internal::thread_move_t<F> f)
|
||||
: m_f(f) {}
|
||||
virtual void execute() { m_f(); }
|
||||
void execute() override { m_f(); }
|
||||
private:
|
||||
F m_f;
|
||||
|
||||
|
||||
@@ -129,16 +129,16 @@ namespace AZStd
|
||||
{
|
||||
}
|
||||
|
||||
virtual void dispose() // nothrow
|
||||
void dispose() override // nothrow
|
||||
{
|
||||
AZStd::checked_delete(px_);
|
||||
}
|
||||
virtual void destroy() // nothrow
|
||||
void destroy() override // nothrow
|
||||
{
|
||||
this->~this_type();
|
||||
a_.deallocate(this, sizeof(this_type), AZStd::alignment_of<this_type>::value);
|
||||
}
|
||||
virtual void* get_deleter(Internal::sp_typeinfo const&)
|
||||
void* get_deleter(Internal::sp_typeinfo const&) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -176,18 +176,18 @@ namespace AZStd
|
||||
{
|
||||
}
|
||||
|
||||
virtual void dispose() // nothrow
|
||||
void dispose() override // nothrow
|
||||
{
|
||||
d_(p_);
|
||||
}
|
||||
|
||||
virtual void destroy() // nothrow
|
||||
void destroy() override // nothrow
|
||||
{
|
||||
this->~this_type();
|
||||
a_.deallocate(this, sizeof(this_type), AZStd::alignment_of<this_type>::value);
|
||||
}
|
||||
|
||||
virtual void* get_deleter(Internal::sp_typeinfo const& ti)
|
||||
void* get_deleter(Internal::sp_typeinfo const& ti) override
|
||||
{
|
||||
return ti == aztypeid(D) ? &reinterpret_cast<char&>(d_) : 0;
|
||||
}
|
||||
|
||||
@@ -96,6 +96,10 @@ namespace AZStd
|
||||
&& !is_convertible_v<const T&, const Element*>>>
|
||||
constexpr basic_fixed_string(const T& convertibleToView, size_type rhsOffset, size_type count);
|
||||
|
||||
|
||||
// #12
|
||||
constexpr basic_fixed_string(AZStd::nullptr_t) = delete;
|
||||
|
||||
constexpr operator AZStd::basic_string_view<Element, Traits>() const;
|
||||
|
||||
constexpr auto begin() -> iterator;
|
||||
@@ -120,6 +124,7 @@ namespace AZStd
|
||||
constexpr auto operator=(const T& convertible_to_view)
|
||||
-> AZStd::enable_if_t<is_convertible_v<const T&, basic_string_view<Element, Traits>>
|
||||
&& !is_convertible_v<const T&, const Element*>, basic_fixed_string&>;
|
||||
constexpr auto operator=(AZStd::nullptr_t) -> basic_fixed_string& = delete;
|
||||
|
||||
constexpr auto operator+=(const basic_fixed_string& rhs) -> basic_fixed_string&;
|
||||
constexpr auto operator+=(const_pointer ptr) -> basic_fixed_string&;
|
||||
|
||||
@@ -215,6 +215,7 @@ namespace AZStd
|
||||
|
||||
struct ErrorSink
|
||||
{
|
||||
virtual ~ErrorSink() = default;
|
||||
virtual void RegexError(regex_constants::error_type code) = 0;
|
||||
};
|
||||
}
|
||||
@@ -1079,7 +1080,7 @@ namespace AZStd
|
||||
NodeBase* m_next;
|
||||
NodeBase* m_previous;
|
||||
|
||||
virtual ~NodeBase() { }
|
||||
virtual ~NodeBase() = default;
|
||||
};
|
||||
|
||||
inline void DestroyNode(NodeBase* node, NodeBase* end = nullptr)
|
||||
@@ -1758,7 +1759,7 @@ namespace AZStd
|
||||
return (*this);
|
||||
}
|
||||
|
||||
~basic_regex()
|
||||
~basic_regex() override
|
||||
{ // destroy the object
|
||||
Clear();
|
||||
}
|
||||
@@ -2916,7 +2917,7 @@ namespace AZStd
|
||||
}
|
||||
|
||||
template<class ForwardIterator, class Element, class RegExTraits>
|
||||
inline NodeBase* Builder<ForwardIterator, Element, RegExTraits>::BeginGroup(void)
|
||||
inline NodeBase* Builder<ForwardIterator, Element, RegExTraits>::BeginGroup()
|
||||
{ // add group node
|
||||
return (NewNode(NT_group));
|
||||
}
|
||||
@@ -3026,7 +3027,7 @@ namespace AZStd
|
||||
}
|
||||
|
||||
template<class ForwardIterator, class Element, class RegExTraits>
|
||||
inline RootNode* Builder<ForwardIterator, Element, RegExTraits>::EndPattern(void)
|
||||
inline RootNode* Builder<ForwardIterator, Element, RegExTraits>::EndPattern()
|
||||
{ // wrap up
|
||||
NewNode(NT_end);
|
||||
return m_root;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <AzCore/std/base.h>
|
||||
#include <AzCore/std/iterator.h>
|
||||
#include <AzCore/std/allocator.h>
|
||||
#include <AzCore/std/allocator_traits.h>
|
||||
#include <AzCore/std/algorithm.h>
|
||||
#include <AzCore/std/typetraits/alignment_of.h>
|
||||
#include <AzCore/std/typetraits/is_integral.h>
|
||||
@@ -167,6 +168,9 @@ namespace AZStd
|
||||
{
|
||||
}
|
||||
|
||||
// C++23 overload to prevent initializing a string_view via a nullptr or integer type
|
||||
constexpr basic_string(AZStd::nullptr_t) = delete;
|
||||
|
||||
inline ~basic_string()
|
||||
{
|
||||
// destroy the string
|
||||
@@ -196,6 +200,7 @@ namespace AZStd
|
||||
inline this_type& operator=(AZStd::basic_string_view<Element, Traits> view) { return assign(view); }
|
||||
inline this_type& operator=(const_pointer ptr) { return assign(ptr); }
|
||||
inline this_type& operator=(Element ch) { return assign(1, ch); }
|
||||
inline this_type& operator=(AZStd::nullptr_t) = delete;
|
||||
inline this_type& operator+=(const this_type& rhs) { return append(rhs); }
|
||||
inline this_type& operator+=(const_pointer ptr) { return append(ptr); }
|
||||
inline this_type& operator+=(Element ch) { return append(1, ch); }
|
||||
@@ -862,8 +867,7 @@ namespace AZStd
|
||||
inline size_type max_size() const
|
||||
{
|
||||
// return maximum possible length of sequence
|
||||
size_type num = m_allocator.get_max_size();
|
||||
return (num <= 1 ? 1 : num - 1);
|
||||
return AZStd::allocator_traits<allocator_type>::max_size(m_allocator) / sizeof(value_type);
|
||||
}
|
||||
|
||||
inline void resize(size_type newSize)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user