Merge branch 'development' into Prefab/DestroyGameEntitySupport

Signed-off-by: srikappa-amzn <srikappa@amazon.com>
This commit is contained in:
srikappa-amzn
2021-09-28 06:57:38 -07:00
1501 changed files with 34384 additions and 17743 deletions
@@ -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
)
@@ -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 " \
@@ -1251,6 +1251,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
@@ -196,14 +196,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;
@@ -207,12 +207,6 @@ namespace AZ
ActivateComponent(**it);
}
// Cache the transform interface to the transform interface
// Generally this pattern is not recommended unless for component event buses
// As we have a guarantee (by design) that components can't change during active state)
// Even though technically they can connect disconnect from the bus.
m_transform = TransformBus::FindFirstHandler(m_id);
SetState(State::Active);
EBUS_EVENT_ID(m_id, EntityBus, OnEntityActivated, m_id);
@@ -1330,6 +1324,19 @@ namespace AZ
return *processSignature;
}
AZ::TransformInterface* Entity::GetTransform() const
{
// Lazy evaluation of the cached entity transform.
if(!m_transform)
{
// Generally this pattern is not recommended unless for component event buses
// As we have a guarantee (by design) that components can't change during active state)
// Even though technically they can connect disconnect from the bus.
m_transform = TransformBus::FindFirstHandler(m_id);
}
return m_transform;
}
//=========================================================================
// MakeId
// Ids must be unique across a project at authoring time. Runtime doesn't matter
@@ -362,10 +362,9 @@ namespace AZ
//! @return The Process Signature of the local machine.
static AZ::u32 GetProcessSignature();
/// @cond EXCLUDE_DOCS
//! @deprecated Use the TransformBus to communicate with the TransformInterface.
inline TransformInterface* GetTransform() const { return m_transform; }
/// @endcond
//! Gets the TransformInterface for the entity.
//! @return The TransformInterface for the entity.
TransformInterface* GetTransform() const;
//! Sorts an entity's components based on the dependencies between components.
//! If all dependencies are met, the required services can be activated
@@ -414,7 +413,7 @@ namespace AZ
//! A cached pointer to the transform interface.
//! We recommend using AZ::TransformBus and caching locally instead of accessing
//! the transform interface directly through this pointer.
TransformInterface* m_transform;
mutable TransformInterface* m_transform;
//! A user-friendly name for the entity. This makes error messages easier to read.
AZStd::string m_name;
@@ -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();
@@ -59,6 +59,20 @@ namespace AZStd
namespace AZ::Debug
{
// interface for externally defined profiler systems
class Profiler
{
public:
AZ_RTTI(Profiler, "{3E5D6329-72D1-41BA-9158-68A349D1A4D5}");
Profiler() = default;
virtual ~Profiler() = default;
// support for the extra macro args (e.g. format strings) will come in a later PR
virtual void BeginRegion(const Budget* budget, const char* eventName) = 0;
virtual void EndRegion(const Budget* budget) = 0;
};
class ProfileScope
{
public:
@@ -6,6 +6,8 @@
*
*/
#include <AzCore/Interface/Interface.h>
namespace AZ::Debug
{
template<typename... T>
@@ -22,9 +24,11 @@ namespace AZ::Debug
PIXBeginEvent(PIX_COLOR_INDEX(budget->Crc() & 0xff), eventName, args...);
#endif
budget->BeginProfileRegion();
// TODO: injecting instrumentation for other profilers
// NOTE: external profiler registration won't occur inline in a header necessarily in this manner, but the exact mechanism
// will be introduced in a future PR
if (auto profiler = AZ::Interface<Profiler>::Get(); profiler)
{
profiler->BeginRegion(budget, eventName);
}
#endif
}
@@ -39,6 +43,10 @@ namespace AZ::Debug
#if defined(USE_PIX)
PIXEndEvent();
#endif
if (auto profiler = AZ::Interface<Profiler>::Get(); profiler)
{
profiler->EndRegion(budget);
}
#endif
}
@@ -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
@@ -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();
};
+1
View File
@@ -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);
@@ -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:
@@ -0,0 +1,200 @@
/*
* 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/IO/FileReader.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/IO/Path/Path.h>
namespace AZ::IO
{
FileReader::FileReader() = default;
FileReader::FileReader(AZ::IO::FileIOBase* fileIoBase, const char* filePath)
{
Open(fileIoBase, filePath);
}
FileReader::~FileReader()
{
Close();
}
FileReader::FileReader(FileReader&& other)
{
AZStd::swap(m_file, other.m_file);
AZStd::swap(m_fileIoBase, other.m_fileIoBase);
}
FileReader& FileReader::operator=(FileReader&& other)
{
// Close the current file and take over other file
Close();
m_file = AZStd::move(other.m_file);
m_fileIoBase = AZStd::move(other.m_fileIoBase);
other.m_file = AZStd::monostate{};
other.m_fileIoBase = {};
return *this;
}
bool FileReader::Open(AZ::IO::FileIOBase* fileIoBase, const char* filePath)
{
// Close file if the FileReader has an instance open
Close();
if (fileIoBase != nullptr)
{
AZ::IO::HandleType fileHandle;
if (fileIoBase->Open(filePath, IO::OpenMode::ModeRead, fileHandle))
{
m_file = fileHandle;
m_fileIoBase = fileIoBase;
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 FileReader::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 FileReader::Close()
{
if (auto fileHandle = AZStd::get_if<AZ::IO::HandleType>(&m_file); fileHandle != nullptr)
{
if (AZ::IO::FileIOBase* fileIo = m_fileIoBase; fileIo != nullptr)
{
fileIo->Close(*fileHandle);
}
}
m_file = AZStd::monostate{};
m_fileIoBase = {};
}
auto FileReader::Length() const -> SizeType
{
if (auto fileHandle = AZStd::get_if<AZ::IO::HandleType>(&m_file); fileHandle != nullptr)
{
if (SizeType fileSize{}; m_fileIoBase->Size(*fileHandle, fileSize))
{
return fileSize;
}
}
else if (auto systemFile = AZStd::get_if<AZ::IO::SystemFile>(&m_file); systemFile != nullptr)
{
return systemFile->Length();
}
return 0;
}
auto FileReader::Read(SizeType byteSize, void* buffer) -> SizeType
{
if (auto fileHandle = AZStd::get_if<AZ::IO::HandleType>(&m_file); fileHandle != nullptr)
{
if (SizeType bytesRead{}; m_fileIoBase->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;
}
auto FileReader::Tell() const -> SizeType
{
if (auto fileHandle = AZStd::get_if<AZ::IO::HandleType>(&m_file); fileHandle != nullptr)
{
if (SizeType fileOffset{}; m_fileIoBase->Tell(*fileHandle, fileOffset))
{
return fileOffset;
}
}
else if (auto systemFile = AZStd::get_if<AZ::IO::SystemFile>(&m_file); systemFile != nullptr)
{
return systemFile->Tell();
}
return 0;
}
bool FileReader::Seek(AZ::s64 offset, SeekType type)
{
if (auto fileHandle = AZStd::get_if<AZ::IO::HandleType>(&m_file); fileHandle != nullptr)
{
return m_fileIoBase->Seek(*fileHandle, offset, type);
}
else if (auto systemFile = AZStd::get_if<AZ::IO::SystemFile>(&m_file); systemFile != nullptr)
{
systemFile->Seek(offset, static_cast<AZ::IO::SystemFile::SeekMode>(type));
return true;
}
return false;
}
bool FileReader::Eof() const
{
if (auto fileHandle = AZStd::get_if<AZ::IO::HandleType>(&m_file); fileHandle != nullptr)
{
return m_fileIoBase->Eof(*fileHandle);
}
else if (auto systemFile = AZStd::get_if<AZ::IO::SystemFile>(&m_file); systemFile != nullptr)
{
return systemFile->Eof();
}
return false;
}
bool FileReader::GetFilePath(AZ::IO::FixedMaxPath& filePath) const
{
if (auto fileHandle = AZStd::get_if<AZ::IO::HandleType>(&m_file); fileHandle != nullptr)
{
AZ::IO::FixedMaxPathString& pathStringRef = filePath.Native();
if (m_fileIoBase->GetFilename(*fileHandle, pathStringRef.data(), pathStringRef.capacity()))
{
pathStringRef.resize_no_construct(AZStd::char_traits<char>::length(pathStringRef.data()));
return true;
}
}
else if (auto systemFile = AZStd::get_if<AZ::IO::SystemFile>(&m_file); systemFile != nullptr)
{
filePath = systemFile->Name();
return true;
}
return false;
}
}
@@ -0,0 +1,92 @@
/*
* 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/IO/Path/Path_fwd.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/std/containers/variant.h>
namespace AZ::IO
{
class FileIOBase;
enum class SeekType : AZ::u32;
//! Structure which encapsulates delegates File Read operations
//! to either the FileIOBase or SystemFile classes based if a FileIOBase* instance has been supplied
//! to the FileSystemReader class
//! the SettingsRegistry option to use FileIO
class FileReader
{
using HandleType = AZ::u32;
using FileHandleType = AZStd::variant<AZStd::monostate, AZ::IO::SystemFile, HandleType>;
public:
using SizeType = AZ::u64;
//! Creates FileReader instance in the default state with no file opend
FileReader();
~FileReader();
//! Creates a new FileReader instance and attempts to open the file at the supplied path
//! Uses the FileIOBase instance if supplied
//! @param fileIOBase pointer to fileIOBase instance
//! @param null-terminated filePath to open
FileReader(AZ::IO::FileIOBase* fileIoBase, const char* filePath);
//! Takes ownership of the supplied FileReader handle
FileReader(FileReader&& other);
//! Moves ownership of FileReader handle to this instance
FileReader& operator=(FileReader&& other);
//! Opens a File using the FileIOBase instance if non-nullptr
//! Otherwise fall back to use SystemFile
//! @param fileIOBase pointer to fileIOBase instance
//! @param null-terminated filePath to open
//! @return true if the File is opened successfully
bool Open(AZ::IO::FileIOBase* fileIoBase, const char* filePath);
//! Returns true if a file is currently open
//! @return true if the file is open
bool IsOpen() const;
//! Closes the File
void Close();
//! Retrieve the length of the OpenFile
SizeType Length() const;
//! Attempts to read up to byte size bytes into the supplied buffer
//! @param byteSize - Maximum number of bytes to read
//! @param buffer - Buffer to read bytes into
//! @returns the number of bytes read if the file is open, otherwise 0
SizeType Read(SizeType byteSize, void* buffer);
//! Returns the current file offset
//! @returns file offset if the file is open, otherwise 0
SizeType Tell() const;
//! Seeks within the open file to the offset supplied
//! @param offset File offset to seek to
//! @param type parameter to indicate the reference point to start the seek from
//! @returns true if the file is open and the seek succeeded
bool Seek(AZ::s64 offset, SeekType type);
//! Returns true if the file is open and in the EOF state
bool Eof() const;
//! Store the file path of the open file into the output file path parameter
//! The filePath reference is left unmodified, if the path was not stored
//! @return true if the filePath was stored
bool GetFilePath(AZ::IO::FixedMaxPath& filePath) const;
private:
FileHandleType m_file;
AZ::IO::FileIOBase* m_fileIoBase{};
};
}
@@ -160,12 +160,12 @@ void SystemFile::Seek(SeekSizeType offset, SeekMode mode)
Platform::Seek(m_handle, this, offset, mode);
}
SystemFile::SizeType SystemFile::Tell()
SystemFile::SizeType SystemFile::Tell() const
{
return Platform::Tell(m_handle, this);
}
bool SystemFile::Eof()
bool SystemFile::Eof() const
{
return Platform::Eof(m_handle, this);
}
+2 -2
View File
@@ -72,9 +72,9 @@ namespace AZ
/// Seek in current file.
void Seek(SeekSizeType offset, SeekMode mode);
/// Get the cursor position in the current file.
SizeType Tell();
SizeType Tell() const;
/// Is the cursor at the end of the file?
bool Eof();
bool Eof() const;
/// Get the time the file was last modified.
AZ::u64 ModificationTime();
/// Read data from a file synchronous. Return number of bytes actually read in the buffer.
@@ -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();
}
@@ -353,6 +353,7 @@ namespace AZ
Method("CreateFromMatrix3x3AndTranslation", &Transform::CreateFromMatrix3x3AndTranslation)->
Method("CreateUniformScale", &Transform::CreateUniformScale)->
Method("CreateTranslation", &Transform::CreateTranslation)->
Method("CreateLookAt", &Transform::CreateLookAt)->
Method("ConstructFromValuesNumeric", &Internal::ConstructTransformFromValues);
}
}
@@ -48,18 +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;
size_type GetMaxContiguousAllocationSize() const override;
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);
@@ -56,22 +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;
size_type GetMaxContiguousAllocationSize() const override;
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
@@ -41,18 +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 size_type GetMaxContiguousAllocationSize() 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);
+1 -1
View File
@@ -849,7 +849,7 @@ namespace AZ
return AZ::AllocatorInstance<Parent>::Get().GetUnAllocatedMemory(isPrint);
}
virtual IAllocatorAllocate* GetSubAllocator() override
IAllocatorAllocate* GetSubAllocator() override
{
return AZ::AllocatorInstance<Parent>::Get().GetSubAllocator();
}
@@ -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);
@@ -77,18 +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;
size_type NumAllocatedBytes() const override;
size_type Capacity() const override;
size_type GetMaxAllocationSize() const override;
size_type GetMaxContiguousAllocationSize() const override;
virtual IAllocatorAllocate* GetSubAllocator() override;
virtual void GarbageCollect() override;
IAllocatorAllocate* GetSubAllocator() override;
void GarbageCollect() override;
private:
OverrunDetectionSchemaImpl* m_impl;
+1 -1
View File
@@ -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.
@@ -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;
+19 -33
View File
@@ -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
@@ -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);
};
@@ -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;
};
@@ -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,15 @@
#include <cctype>
#include <cerrno>
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/IO/FileReader.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 +135,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 +733,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 +746,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 +762,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 +771,7 @@ namespace AZ
RegistryFile& registryFile = fileList.back();
if (ExtractFileDescription(registryFile, filename, specializations))
{
registryFile.m_isPlatformFile = true;
registryFile.m_isPlatformFile = isPlatformFile;
}
else
{
@@ -809,7 +780,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 +837,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 +1031,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 +1083,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,7 +1112,7 @@ 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;
}
}
@@ -1116,8 +1125,8 @@ namespace AZ
Pointer pointer(AZ_SETTINGS_REGISTRY_HISTORY_KEY "/-");
SystemFile file;
if (!file.Open(path, SystemFile::OpenMode::SF_OPEN_READ_ONLY))
FileReader fileReader(m_useFileIo ? AZ::IO::FileIOBase::GetInstance(): nullptr, 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 +1135,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 +1145,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 +1278,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
@@ -6,6 +6,8 @@
*
*/
#include <AzCore/IO/FileIO.h>
#include <AzCore/IO/FileReader.h>
#include <AzCore/IO/GenericStreams.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/IO/TextStreamWriters.h>
@@ -78,6 +80,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
@@ -355,6 +358,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
{
@@ -386,8 +390,36 @@ namespace AZ::SettingsRegistryMergeUtils
const ConfigParserSettings& configParserSettings)
{
auto configPath = FindEngineRoot(registry) / filePath;
IO::SystemFile configFile;
if (!configFile.Open(configPath.c_str(), IO::SystemFile::OpenMode::SF_OPEN_READ_ONLY))
IO::FileReader configFile;
bool configFileOpened{};
switch (configParserSettings.m_fileReaderClass)
{
case ConfigParserSettings::FileReaderClass::UseFileIOIfAvailableFallbackToSystemFile:
{
auto fileIo = AZ::IO::FileIOBase::GetInstance();
configFileOpened = configFile.Open(fileIo, configPath.c_str());
break;
}
case ConfigParserSettings::FileReaderClass::UseSystemFileOnly:
{
configFileOpened = configFile.Open(nullptr, configPath.c_str());
break;
}
case ConfigParserSettings::FileReaderClass::UseFileIOOnly:
{
auto fileIo = AZ::IO::FileIOBase::GetInstance();
if (fileIo == nullptr)
{
return false;
}
configFileOpened = configFile.Open(fileIo, configPath.c_str());
break;
}
default:
AZ_Error("SettingsRegistryMergeUtils", false, "An Invalid FileReaderClass enum value has been supplied");
return false;
}
if (!configFileOpened)
{
AZ_Warning("SettingsRegistryMergeUtils", false, R"(Unable to open file "%s")", configPath.c_str());
return false;
@@ -478,7 +510,7 @@ namespace AZ::SettingsRegistryMergeUtils
AZ_Error("SettingsRegistryMergeUtils", false,
R"(The config file "%s" contains a line which is longer than the max line length of %zu.)" "\n"
R"(Parsing will halt. The line content so far is:)" "\n"
R"("%.*s")" "\n", configFile.Name(), configBuffer.max_size(),
R"("%.*s")" "\n", configPath.c_str(), configBuffer.max_size(),
aznumeric_cast<int>(configBuffer.size()), configBuffer.data());
configFileParsed = false;
break;
@@ -761,6 +793,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 +929,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
{
@@ -155,6 +155,15 @@ namespace AZ::SettingsRegistryMergeUtils
//! structure which is forwarded to the SettingsRegistryInterface MergeCommandLineArgument function
//! The structure contains a functor which returns true if a character is a valid delimiter
SettingsRegistryInterface::CommandLineArgumentSettings m_commandLineSettings;
//! enumeration to indicate if AZ::IO::FileIOBase should be used to open the config file over AZ::IO::SystemFile
enum class FileReaderClass
{
UseFileIOIfAvailableFallbackToSystemFile,
UseSystemFileOnly,
UseFileIOOnly
};
FileReaderClass m_fileReaderClass = FileReaderClass::UseFileIOIfAvailableFallbackToSystemFile;
};
//! Loads basic configuration files which have structures similar to Windows INI files
//! It is inspired by the Python configparser module: https://docs.python.org/3.10/library/configparser.html
@@ -57,6 +57,7 @@ namespace AZ
MOCK_METHOD1(SetApplyPatchSettings, void(const JsonApplyPatchSettings&));
MOCK_METHOD1(GetApplyPatchSettings, void(JsonApplyPatchSettings&));
MOCK_METHOD1(SetUseFileIO, void(bool));
};
} // namespace AZ
@@ -131,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);
@@ -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
@@ -166,6 +166,8 @@ set(FILES
IO/FileIO.cpp
IO/FileIO.h
IO/FileIOEventBus.h
IO/FileReader.cpp
IO/FileReader.h
IO/IOUtils.h
IO/IOUtils.cpp
IO/IStreamer.h
@@ -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;
@@ -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;
@@ -168,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
@@ -197,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); }
@@ -502,6 +502,9 @@ namespace AZStd
swap(other);
}
// C++23 overload to prevent initializing a string_view via a nullptr or integer type
constexpr basic_string_view(AZStd::nullptr_t) = delete;
constexpr const_reference operator[](size_type index) const { return data()[index]; }
/// Returns value, not reference. If index is out of bounds, 0 is returned (can't be reference).
constexpr value_type at(size_type index) const
@@ -72,6 +72,7 @@ namespace AZ
{
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
bool fileFound = false;
if (AZ::IO::FixedMaxPath projectModulePath;
settingsRegistry->Get(projectModulePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectConfigurationBinPath))
{
@@ -79,6 +80,23 @@ namespace AZ
if (AZ::IO::SystemFile::Exists(projectModulePath.c_str()))
{
m_fileName.assign(projectModulePath.c_str(), projectModulePath.Native().size());
fileFound = true;
}
}
if (!fileFound)
{
if (AZ::IO::FixedMaxPath installedBinariesPath;
settingsRegistry->Get(installedBinariesPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_InstalledBinaryFolder))
{
if (AZ::IO::FixedMaxPath engineRootFolder;
settingsRegistry->Get(engineRootFolder.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder))
{
installedBinariesPath = engineRootFolder / installedBinariesPath / fullFilePath;
if (AZ::IO::SystemFile::Exists(installedBinariesPath.c_str()))
{
m_fileName.assign(installedBinariesPath.c_str(), installedBinariesPath.Native().size());
}
}
}
}
}
@@ -9,6 +9,7 @@
#include <AzCore/Utils/Utils.h>
#include <cstdlib>
#include <pwd.h>
namespace AZ
{
@@ -39,6 +40,14 @@ namespace AZ
AZ::IO::FixedMaxPath path{homePath};
return path.Native();
}
struct passwd* pass = getpwuid(getuid());
if (pass)
{
AZ::IO::FixedMaxPath path{pass->pw_dir};
return path.Native();
}
return {};
}
@@ -21,7 +21,7 @@ namespace AZ
class WinAPIOverrunDetectionSchema : public OverrunDetectionSchema::PlatformAllocator
{
public:
virtual SystemInformation GetSystemInformation() override
SystemInformation GetSystemInformation() override
{
SystemInformation result;
SYSTEM_INFO info;
@@ -32,7 +32,7 @@ namespace AZ
return result;
}
virtual void* ReserveBytes(size_t amount) override
void* ReserveBytes(size_t amount) override
{
void* result = VirtualAlloc(0, amount, MEM_RESERVE, PAGE_NOACCESS);
@@ -45,12 +45,12 @@ namespace AZ
return result;
}
virtual void ReleaseReservedBytes(void* base) override
void ReleaseReservedBytes(void* base) override
{
VirtualFree(base, 0, MEM_RELEASE);
}
virtual void* CommitBytes(void* base, size_t amount) override
void* CommitBytes(void* base, size_t amount) override
{
void* result = VirtualAlloc(base, amount, MEM_COMMIT, PAGE_READWRITE);
@@ -63,7 +63,7 @@ namespace AZ
return result;
}
virtual void DecommitBytes(void* base, size_t amount) override
void DecommitBytes(void* base, size_t amount) override
{
VirtualFree(base, amount, MEM_DECOMMIT);
}
@@ -267,6 +267,7 @@ namespace AZ::IO
SettingsRegistryInterface::VisitResponse::Continue : SettingsRegistryInterface::VisitResponse::Skip;
}
using SettingsRegistryInterface::Visitor::Visit;
void Visit([[maybe_unused]] AZStd::string_view path, [[maybe_unused]] AZStd::string_view valueName,
[[maybe_unused]] AZ::SettingsRegistryInterface::Type type, AZStd::string_view value) override
{
+1 -15
View File
@@ -1210,9 +1210,6 @@ namespace UnitTest
AZStd::string findStr("Hay");
string_view view3(findStr);
string_view nullptrView4(nullptr);
EXPECT_EQ(emptyView1, nullptrView4);
// copy
const size_t destBufferSize = 32;
@@ -1264,9 +1261,6 @@ namespace UnitTest
AZStd::size_t rfindResult = view3.rfind('a', 2);
EXPECT_EQ(1, rfindResult);
rfindResult = nullptrView4.rfind("");
EXPECT_EQ(string_view::npos, rfindResult);
rfindResult = emptyView1.rfind("");
EXPECT_EQ(string_view::npos, rfindResult);
@@ -1373,17 +1367,11 @@ namespace UnitTest
{
string_view view1("The quick brown fox jumped over the lazy dog");
string_view view2("Needle in Haystack");
string_view nullBeaverView(nullptr);
string_view emptyBeaverView;
string_view superEmptyBeaverView("");
EXPECT_EQ(nullBeaverView, emptyBeaverView);
EXPECT_EQ(superEmptyBeaverView, nullBeaverView);
EXPECT_EQ(emptyBeaverView, superEmptyBeaverView);
EXPECT_EQ(nullBeaverView, "");
EXPECT_EQ(nullBeaverView, nullptr);
EXPECT_EQ("", emptyBeaverView);
EXPECT_EQ(nullptr, superEmptyBeaverView);
EXPECT_EQ("", superEmptyBeaverView);
EXPECT_EQ("The quick brown fox jumped over the lazy dog", view1);
EXPECT_NE("The slow brown fox jumped over the lazy dog", view1);
@@ -1421,8 +1409,6 @@ namespace UnitTest
EXPECT_LE(beaverView, "Busy Beaver");
EXPECT_LE("Likable Beaver", notBeaverView);
EXPECT_LE("Busy Beaver", beaverView);
EXPECT_LE(nullBeaverView, nullBeaverView);
EXPECT_LE(nullBeaverView, lowerBeaverStr);
EXPECT_LE(microBeaverStr, view1);
EXPECT_LE(compareStr, beaverView);
@@ -100,6 +100,7 @@ namespace JsonSerializationTests
AZ::AllocatorInstance<AZ::PoolAllocator>::Destroy();
}
using JsonSerializerConformityTestDescriptor<AZ::Data::Asset<TestAssetData>>::Reflect;
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
context->RegisterGenericType<Asset>();
@@ -0,0 +1,72 @@
/*
* 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/IO/FileReader.h>
#include <FileIOBaseTestTypes.h>
#include <AzCore/UnitTest/TestTypes.h>
namespace UnitTest
{
template <typename FileIOType>
class FileReaderTestFixture
: public ScopedAllocatorSetupFixture
{
public:
void SetUp() override
{
if constexpr (AZStd::is_same_v<FileIOType, TestFileIOBase>)
{
m_fileIo = AZStd::make_unique<TestFileIOBase>();
}
}
void TearDown() override
{
m_fileIo.reset();
}
protected:
AZStd::unique_ptr<AZ::IO::FileIOBase> m_fileIo{};
};
using FileIOTypes = ::testing::Types<void, TestFileIOBase>;
TYPED_TEST_CASE(FileReaderTestFixture, FileIOTypes);
TYPED_TEST(FileReaderTestFixture, ConstructorWithFilePath_OpensFileSuccessfully)
{
AZ::IO::FileReader fileReader(this->m_fileIo.get(), AZ::IO::SystemFile::GetNullFilename());
EXPECT_TRUE(fileReader.IsOpen());
}
TYPED_TEST(FileReaderTestFixture, Open_OpensFileSucessfully)
{
AZ::IO::FileReader fileReader;
fileReader.Open(this->m_fileIo.get(), AZ::IO::SystemFile::GetNullFilename());
EXPECT_TRUE(fileReader.IsOpen());
}
TYPED_TEST(FileReaderTestFixture, Eof_OnNULDeviceFile_Succeeds)
{
AZ::IO::FileReader fileReader(this->m_fileIo.get(), AZ::IO::SystemFile::GetNullFilename());
EXPECT_TRUE(fileReader.Eof());
}
TYPED_TEST(FileReaderTestFixture, GetFilePath_ReturnsNULDeviceFilename_Succeeds)
{
AZ::IO::FileReader fileReader(this->m_fileIo.get(), AZ::IO::SystemFile::GetNullFilename());
AZ::IO::FixedMaxPath filePath;
EXPECT_TRUE(fileReader.GetFilePath(filePath));
AZ::IO::FixedMaxPath nulFilename{ AZ::IO::SystemFile::GetNullFilename() };
if (this->m_fileIo)
{
EXPECT_TRUE(this->m_fileIo->ResolvePath(nulFilename, nulFilename));
}
EXPECT_EQ(nulFilename, filePath);
}
} // namespace UnitTest
@@ -956,18 +956,8 @@ AZ_POP_DISABLE_WARNING
namespace Benchmark
{
class PathBenchmarkFixture
: public ::benchmark::Fixture
, public ::UnitTest::AllocatorsBase
: public ::UnitTest::AllocatorsBenchmarkFixture
{
public:
void SetUp([[maybe_unused]] const ::benchmark::State& state) override
{
::UnitTest::AllocatorsBase::SetupAllocator();
}
void TearDown([[maybe_unused]] const ::benchmark::State& state) override
{
::UnitTest::AllocatorsBase::TeardownAllocator();
}
protected:
AZStd::fixed_vector<const char*, 20> m_appendPaths{ "foo", "bar", "baz", "bazzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz",
"boo/bar/base", "C:\\path\\to\\O3DE", "C", "\\\\", "/", R"(test\\path/with\mixed\separators)" };
+18 -2
View File
@@ -1704,7 +1704,7 @@ namespace Benchmark
static const AZ::u32 MEDIUM_NUMBER_OF_JOBS = 1024;
static const AZ::u32 LARGE_NUMBER_OF_JOBS = 16384;
void SetUp([[maybe_unused]] ::benchmark::State& state) override
void internalSetUp()
{
AllocatorInstance<PoolAllocator>::Create();
AllocatorInstance<ThreadPoolAllocator>::Create();
@@ -1749,8 +1749,16 @@ namespace Benchmark
return randomDepthDistribution(randomDepthGenerator);
});
}
void SetUp(::benchmark::State&) override
{
internalSetUp();
}
void SetUp(const ::benchmark::State&) override
{
internalSetUp();
}
void TearDown([[maybe_unused]] ::benchmark::State& state) override
void internalTearDown()
{
JobContext::SetGlobalContext(nullptr);
@@ -1763,6 +1771,14 @@ namespace Benchmark
AllocatorInstance<ThreadPoolAllocator>::Destroy();
AllocatorInstance<PoolAllocator>::Destroy();
}
void TearDown(::benchmark::State&) override
{
internalTearDown();
}
void TearDown(const ::benchmark::State&) override
{
internalTearDown();
}
protected:
inline void RunCalculatePiJob(AZ::s32 depth, AZ::s8 priority)
@@ -19,8 +19,7 @@ namespace Benchmark
class BM_MathFrustum
: public benchmark::Fixture
{
public:
void SetUp([[maybe_unused]] const ::benchmark::State& state) override
void internalSetUp()
{
m_testFrustum = AZ::Frustum(AZ::ViewFrustumAttributes(AZ::Transform::CreateIdentity(), 1.0f, 2.0f * atanf(0.5f), 10.0f, 90.0f));
@@ -40,6 +39,15 @@ namespace Benchmark
return data;
});
}
public:
void SetUp(const benchmark::State&) override
{
internalSetUp();
}
void SetUp(benchmark::State&) override
{
internalSetUp();
}
struct Data
{
@@ -23,8 +23,7 @@ namespace Benchmark
class BM_MathMatrix3x3
: public benchmark::Fixture
{
public:
void SetUp([[maybe_unused]] const ::benchmark::State& state) override
void internalSetUp()
{
m_testDataArray.resize(1000);
@@ -44,6 +43,15 @@ namespace Benchmark
return testData;
});
}
public:
void SetUp(const benchmark::State&) override
{
internalSetUp();
}
void SetUp(benchmark::State&) override
{
internalSetUp();
}
struct TestData
{
@@ -21,8 +21,7 @@ namespace Benchmark
class BM_MathMatrix3x4
: public benchmark::Fixture
{
public:
void SetUp([[maybe_unused]] const::benchmark::State& state) override
void internalSetUp()
{
m_testDataArray.resize(1000);
@@ -58,6 +57,15 @@ namespace Benchmark
return testData;
});
}
public:
void SetUp(const benchmark::State&) override
{
internalSetUp();
}
void SetUp(benchmark::State&) override
{
internalSetUp();
}
struct TestData
{
@@ -20,8 +20,7 @@ namespace Benchmark
class BM_MathMatrix4x4
: public benchmark::Fixture
{
public:
void SetUp([[maybe_unused]] const ::benchmark::State& state) override
void internalSetUp()
{
m_testDataArray.resize(1000);
@@ -41,6 +40,15 @@ namespace Benchmark
return testData;
});
}
public:
void SetUp(const benchmark::State&) override
{
internalSetUp();
}
void SetUp(benchmark::State&) override
{
internalSetUp();
}
struct TestData
{
@@ -19,8 +19,7 @@ namespace Benchmark
class BM_MathObb
: public benchmark::Fixture
{
public:
void SetUp([[maybe_unused]] const ::benchmark::State& state) override
void internalSetUp()
{
m_position.Set(1.0f, 2.0f, 3.0f);
m_rotation = AZ::Quaternion::CreateRotationZ(AZ::Constants::QuarterPi);
@@ -28,6 +27,16 @@ namespace Benchmark
m_obb = AZ::Obb::CreateFromPositionRotationAndHalfLengths(m_position, m_rotation, m_halfLengths);
}
public:
void SetUp(const benchmark::State&) override
{
internalSetUp();
}
void SetUp(benchmark::State&) override
{
internalSetUp();
}
AZ::Obb m_obb;
AZ::Vector3 m_position;
AZ::Quaternion m_rotation;
@@ -18,14 +18,7 @@ namespace Benchmark
class BM_MathPlane
: public benchmark::Fixture
{
public:
BM_MathPlane()
{
const unsigned int seed = 1;
rng = std::mt19937_64(seed);
}
void SetUp([[maybe_unused]] const ::benchmark::State& state) override
void internalSetUp()
{
for (int i = 0; i < m_numIters; ++i)
{
@@ -39,7 +32,7 @@ namespace Benchmark
m_distance = unif(rng);
m_dists.push_back(m_distance);
//set these differently so they don't overlap with same values as other vectors
// set these differently so they don't overlap with same values as other vectors
m_normal = AZ::Vector3(unif(rng), unif(rng), unif(rng));
m_normal.Normalize();
m_distance = unif(rng);
@@ -47,6 +40,21 @@ namespace Benchmark
m_planes.push_back(m_plane);
}
}
public:
BM_MathPlane()
{
const unsigned int seed = 1;
rng = std::mt19937_64(seed);
}
void SetUp(const benchmark::State&) override
{
internalSetUp();
}
void SetUp(benchmark::State&) override
{
internalSetUp();
}
AZ::Plane m_plane;
AZ::Vector3 m_normal;
@@ -17,8 +17,7 @@ namespace Benchmark
class BM_MathQuaternion
: public benchmark::Fixture
{
public:
void SetUp([[maybe_unused]] const ::benchmark::State& state) override
void internalSetUp()
{
m_quatDataArray.resize(1000);
@@ -42,6 +41,15 @@ namespace Benchmark
return quatData;
});
}
public:
void SetUp(const benchmark::State&) override
{
internalSetUp();
}
void SetUp(benchmark::State&) override
{
internalSetUp();
}
struct QuatData
{
@@ -35,8 +35,7 @@ namespace Benchmark
class BM_MathShapeIntersection
: public benchmark::Fixture
{
public:
void SetUp([[maybe_unused]] const ::benchmark::State& state) override
void internalSetUp()
{
m_testDataArray.resize(1000);
@@ -58,6 +57,15 @@ namespace Benchmark
return testData;
});
}
public:
void SetUp(const benchmark::State&) override
{
internalSetUp();
}
void SetUp(benchmark::State&) override
{
internalSetUp();
}
struct TestData
{
@@ -22,8 +22,7 @@ namespace Benchmark
class BM_MathTransform
: public benchmark::Fixture
{
public:
void SetUp([[maybe_unused]] const ::benchmark::State& state) override
void internalSetUp()
{
m_testDataArray.resize(1000);
@@ -51,6 +50,15 @@ namespace Benchmark
return testData;
});
}
public:
void SetUp(const benchmark::State&) override
{
internalSetUp();
}
void SetUp(benchmark::State&) override
{
internalSetUp();
}
struct TestData
{
@@ -19,8 +19,7 @@ namespace Benchmark
class BM_MathVector2
: public benchmark::Fixture
{
public:
void SetUp([[maybe_unused]] const ::benchmark::State& state) override
void internalSetUp()
{
m_vecDataArray.resize(1000);
@@ -37,6 +36,15 @@ namespace Benchmark
return vecData;
});
}
public:
void SetUp(const benchmark::State&) override
{
internalSetUp();
}
void SetUp(benchmark::State&) override
{
internalSetUp();
}
struct VecData
{
@@ -19,8 +19,7 @@ namespace Benchmark
class BM_MathVector3
: public benchmark::Fixture
{
public:
void SetUp([[maybe_unused]] const ::benchmark::State& state) override
void internalSetUp()
{
m_vecDataArray.resize(1000);
@@ -37,6 +36,15 @@ namespace Benchmark
return vecData;
});
}
public:
void SetUp(const benchmark::State&) override
{
internalSetUp();
}
void SetUp(benchmark::State&) override
{
internalSetUp();
}
struct VecData
{
@@ -19,8 +19,7 @@ namespace Benchmark
class BM_MathVector4
: public benchmark::Fixture
{
public:
void SetUp([[maybe_unused]] const ::benchmark::State& state) override
void internalSetUp()
{
m_vecDataArray.resize(1000);
@@ -38,6 +37,15 @@ namespace Benchmark
return vecData;
});
}
public:
void SetUp(const benchmark::State&) override
{
internalSetUp();
}
void SetUp(benchmark::State&) override
{
internalSetUp();
}
struct VecData
{
@@ -120,19 +120,34 @@ namespace Benchmark
class HphaSchemaBenchmarkFixture
: public ::benchmark::Fixture
{
public:
void SetUp(const ::benchmark::State& state) override
void internalSetUp()
{
AZ_UNUSED(state);
AZ::AllocatorInstance<HphaSchema_TestAllocator>::Create();
}
void TearDown(const ::benchmark::State& state) override
void internalTearDown()
{
AZ_UNUSED(state);
AZ::AllocatorInstance<HphaSchema_TestAllocator>::Destroy();
}
public:
void SetUp(const benchmark::State&) override
{
internalSetUp();
}
void SetUp(benchmark::State&) override
{
internalSetUp();
}
void TearDown(const benchmark::State&) override
{
internalTearDown();
}
void TearDown(benchmark::State&) override
{
internalTearDown();
}
static void BM_Allocations(benchmark::State& state, const AllocationSizeArray& allocationArray)
{
AZStd::vector<void*> allocations;
@@ -362,7 +362,7 @@ namespace UnitTest
// Test specific construction case that was failing.
// The constructor calls Name::SetName() which does a move assignment
// Name& Name::operator=(Name&& rhs) was leaving m_view pointing to the m_data in a temporary Name object.
AZ::Name emptyName(AZStd::string_view(nullptr));
AZ::Name emptyName(AZStd::string_view{});
EXPECT_TRUE(emptyName.IsEmpty());
EXPECT_EQ(0, emptyName.GetStringView().data()[0]);
}
@@ -1155,6 +1155,23 @@ namespace Benchmark
{
class StorageDriveWindowsFixture : public benchmark::Fixture
{
void internalTearDown()
{
using namespace AZ::IO;
AZStd::string temp;
m_absolutePath.swap(temp);
delete m_streamer;
m_streamer = nullptr;
SystemFile::Delete(TestFileName);
AZ::IO::FileIOBase::SetInstance(nullptr);
AZ::IO::FileIOBase::SetInstance(m_previousFileIO);
delete m_fileIO;
m_fileIO = nullptr;
}
public:
constexpr static const char* TestFileName = "StreamerBenchmark.bin";
constexpr static size_t FileSize = 64_mib;
@@ -1197,20 +1214,13 @@ namespace Benchmark
}
}
void TearDown([[maybe_unused]] const ::benchmark::State& state) override
void TearDown(const benchmark::State&) override
{
using namespace AZ::IO;
AZStd::string temp;
m_absolutePath.swap(temp);
delete m_streamer;
SystemFile::Delete(TestFileName);
AZ::IO::FileIOBase::SetInstance(nullptr);
AZ::IO::FileIOBase::SetInstance(m_previousFileIO);
delete m_fileIO;
internalTearDown();
}
void TearDown(benchmark::State&) override
{
internalTearDown();
}
void RepeatedlyReadFile(benchmark::State& state)
@@ -35,6 +35,7 @@ namespace JsonSerializationTests
features.m_fixedSizeArray = true;
}
using JsonSerializerConformityTestDescriptor<T>::Reflect;
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
context->RegisterGenericType<T>();
@@ -243,6 +244,7 @@ namespace JsonSerializationTests
])";
}
using ArraySerializerTestDescriptionBase<AZStd::array<BaseClass2*, 4>>::Reflect;
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
Base::Reflect(context);
@@ -299,6 +301,7 @@ namespace JsonSerializationTests
AZ::JsonArraySerializer m_serializer;
public:
using BaseJsonSerializerFixture::RegisterAdditional;
void RegisterAdditional(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
context->RegisterGenericType<Array>();
@@ -60,6 +60,7 @@ namespace JsonSerializationTests
return "[188, 288, 388]";
}
using BasicContainerConformityTestDescriptor<Container>::Reflect;
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
context->RegisterGenericType<Container>();
@@ -133,6 +134,7 @@ namespace JsonSerializationTests
return "[188, 288, 388]";
}
using BasicContainerConformityTestDescriptor<Container>::Reflect;
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
context->RegisterGenericType<Container>();
@@ -225,6 +227,7 @@ namespace JsonSerializationTests
features.m_supportsPartialInitialization = true;
}
using BasicContainerConformityTestDescriptor<Container>::Reflect;
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
SimpleClass::Reflect(context, true);
@@ -291,6 +294,7 @@ namespace JsonSerializationTests
using Container = AZStd::vector<SimpleClass>;
using BaseClassContainer = AZStd::vector<AZStd::shared_ptr<BaseClass>>;
using JsonBasicContainerSerializerTests::RegisterAdditional;
void RegisterAdditional(AZStd::unique_ptr<AZ::SerializeContext>& serializeContext) override
{
SimpleClass::Reflect(serializeContext, true);
@@ -352,6 +356,7 @@ namespace JsonSerializationTests
static constexpr size_t ContainerSize = 4;
using Container = AZStd::fixed_vector<int, ContainerSize>;
using JsonBasicContainerSerializerTests::RegisterAdditional;
void RegisterAdditional(AZStd::unique_ptr<AZ::SerializeContext>& serializeContext) override
{
serializeContext->RegisterGenericType<Container>();
@@ -387,6 +392,7 @@ namespace JsonSerializationTests
public:
using Set = AZStd::set<int>;
using JsonBasicContainerSerializerTests::RegisterAdditional;
void RegisterAdditional(AZStd::unique_ptr<AZ::SerializeContext>& serializeContext) override
{
serializeContext->RegisterGenericType<Set>();
@@ -83,6 +83,7 @@ namespace JsonSerializationTests
BaseJsonSerializerFixture::TearDown();
}
using BaseJsonSerializerFixture::RegisterAdditional;
void RegisterAdditional(AZStd::unique_ptr<AZ::SerializeContext>& serializeContext) override
{
serializeContext->Class<BoolPointerWrapper>()
@@ -95,6 +95,7 @@ namespace JsonSerializationTests
BaseJsonSerializerFixture::TearDown();
}
using BaseJsonSerializerFixture::RegisterAdditional;
void RegisterAdditional(AZStd::unique_ptr<AZ::SerializeContext>& serializeContext) override
{
serializeContext->Class<DoublePointerWrapper>()
@@ -44,6 +44,7 @@ namespace JsonSerializationTests
features.m_supportsPartialInitialization = false;
}
using JsonSerializerConformityTestDescriptor<Map>::Reflect;
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
context->RegisterGenericType<Map>();
@@ -247,6 +248,7 @@ namespace JsonSerializationTests
features.m_supportsPartialInitialization = true;
}
using MapBaseTestDescription<T<SimpleClass*, SimpleClass*>, Serializer>::Reflect;
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
SimpleClass::Reflect(context, true);
@@ -33,6 +33,7 @@ namespace JsonSerializationTests
return AZStd::make_shared<SmartPointer>();
}
using JsonSerializerConformityTestDescriptor<SmartPointer>::Reflect;
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
context->RegisterGenericType<SmartPointer>();
@@ -102,6 +103,7 @@ namespace JsonSerializationTests
return *lhs == *rhs;
}
using Base::Reflect;
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
SimpleClass::Reflect(context, true);
@@ -176,6 +178,7 @@ namespace JsonSerializationTests
features.m_supportsPartialInitialization = true;
}
using SmartPointerBaseTestDescription<T<BaseClass>>::Reflect;
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
SimpleInheritence::Reflect(context, true);
@@ -340,6 +343,7 @@ namespace JsonSerializationTests
features.m_supportsPartialInitialization = true;
}
using SmartPointerBaseTestDescription<T<BaseClass2>>::Reflect;
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
MultipleInheritence::Reflect(context, true);
@@ -513,7 +517,8 @@ namespace JsonSerializationTests
public:
using SmartPointer = typename SmartPointerSimpleDerivedClassTestDescription<AZStd::shared_ptr>::SmartPointer;
using InstanceSmartPointer = AZStd::shared_ptr<SimpleInheritence>;
using BaseJsonSerializerFixture::RegisterAdditional;
void RegisterAdditional(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
m_description.Reflect(context);
@@ -72,6 +72,7 @@ namespace JsonSerializationTests
TupleSerializerTestsInternal::ConfigureFeatures(features);
}
using JsonSerializerConformityTestDescriptor<AZStd::pair<int, double>>::Reflect;
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
context->Class<PairPlaceholder>()->Field("pair", &PairPlaceholder::m_pair);
@@ -126,6 +127,7 @@ namespace JsonSerializationTests
TupleSerializerTestsInternal::ConfigureFeatures(features);
}
using JsonSerializerConformityTestDescriptor<Tuple>::Reflect;
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
context->RegisterGenericType<Tuple>();
@@ -344,6 +346,7 @@ namespace JsonSerializationTests
features.m_enableNewInstanceTests = false;
}
using JsonSerializerConformityTestDescriptor::Reflect;
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
context->Class<TupleClass>()
@@ -477,6 +480,7 @@ namespace JsonSerializationTests
features.m_typeToInject = rapidjson::kNullType;
}
using JsonSerializerConformityTestDescriptor<Tuple>::Reflect;
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
context->RegisterGenericType<Tuple>();
@@ -535,6 +539,7 @@ namespace JsonSerializationTests
BaseJsonSerializerFixture::TearDown();
}
using BaseJsonSerializerFixture::RegisterAdditional;
void RegisterAdditional(AZStd::unique_ptr<AZ::SerializeContext>& serializeContext) override
{
SimpleClass::Reflect(serializeContext, true);
@@ -54,6 +54,7 @@ namespace JsonSerializationTests
features.m_supportsPartialInitialization = false;
}
using JsonSerializerConformityTestDescriptor<AZStd::unordered_set<int>>::Reflect;
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
context->RegisterGenericType<Set>();
@@ -108,6 +109,7 @@ namespace JsonSerializationTests
context->RegisterGenericType<MultiSet>();
}
using JsonSerializerConformityTestDescriptor<MultiSet>::Reflect;
bool AreEqual(const MultiSet& lhs, const MultiSet& rhs) override
{
return
@@ -139,6 +141,7 @@ namespace JsonSerializationTests
BaseJsonSerializerFixture::TearDown();
}
using BaseJsonSerializerFixture::RegisterAdditional;
void RegisterAdditional(AZStd::unique_ptr<AZ::SerializeContext>& serializeContext) override
{
serializeContext->RegisterGenericType<Set>();
@@ -423,6 +423,8 @@ namespace SettingsRegistryTests
struct : public AZ::SettingsRegistryInterface::Visitor
{
using AZ::SettingsRegistryInterface::Visitor::Visit;
using ValueType [[maybe_unused]] = typename SettingsType<TypeParam>::ValueType;
void Visit([[maybe_unused]] AZStd::string_view path, [[maybe_unused]] AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type type, ValueType value) override
{
@@ -452,6 +454,8 @@ namespace SettingsRegistryTests
struct : public AZ::SettingsRegistryInterface::Visitor
{
using AZ::SettingsRegistryInterface::Visitor::Visit;
using ValueType [[maybe_unused]] = typename SettingsType<TypeParam>::ValueType;
void Visit([[maybe_unused]] AZStd::string_view path, [[maybe_unused]] AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type type, ValueType value) override
{
@@ -482,6 +486,7 @@ namespace SettingsRegistryTests
struct : public AZ::SettingsRegistryInterface::Visitor
{
using AZ::SettingsRegistryInterface::Visitor::Visit;
void Visit([[maybe_unused]] AZStd::string_view path, [[maybe_unused]] AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type type, AZ::s64 value) override
{
EXPECT_EQ(AZ::SettingsRegistryInterface::Type::Integer, type);
@@ -517,6 +522,8 @@ namespace SettingsRegistryTests
EXPECT_TRUE(path.ends_with(valueName));
return AZ::SettingsRegistryInterface::VisitResponse::Continue;
}
using AZ::SettingsRegistryInterface::Visitor::Visit;
void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type , AZStd::string_view)override
{
EXPECT_TRUE(path.ends_with(valueName));
@@ -1510,7 +1517,7 @@ namespace SettingsRegistryTests
m_testFolder->push_back(AZ_CORRECT_DATABASE_SEPARATOR);
*m_testFolder += AZ::SettingsRegistryInterface::RegistryFolder;
bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {}, nullptr);
bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {});
EXPECT_TRUE(result);
EXPECT_EQ(4, counter);
@@ -1552,7 +1559,7 @@ namespace SettingsRegistryTests
m_testFolder->push_back(AZ_CORRECT_DATABASE_SEPARATOR);
*m_testFolder += AZ::SettingsRegistryInterface::RegistryFolder;
bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, "Special", nullptr);
bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, "Special");
EXPECT_TRUE(result);
EXPECT_EQ(6, counter);
@@ -1591,7 +1598,7 @@ namespace SettingsRegistryTests
m_testFolder->push_back(AZ_CORRECT_DATABASE_SEPARATOR);
*m_testFolder += AZ::SettingsRegistryInterface::RegistryFolder;
bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {}, nullptr);
bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {});
EXPECT_TRUE(result);
EXPECT_EQ(4, counter);
@@ -1632,7 +1639,7 @@ namespace SettingsRegistryTests
m_testFolder->push_back(AZ_CORRECT_DATABASE_SEPARATOR);
*m_testFolder += AZ::SettingsRegistryInterface::RegistryFolder;
bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {}, nullptr);
bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {});
EXPECT_TRUE(result);
EXPECT_EQ(4, counter);
@@ -1665,7 +1672,7 @@ namespace SettingsRegistryTests
m_testFolder->push_back(AZ_CORRECT_DATABASE_SEPARATOR);
*m_testFolder += AZ::SettingsRegistryInterface::RegistryFolder;
bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, "Special", nullptr);
bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, "Special");
EXPECT_TRUE(result);
EXPECT_EQ(1, counter);
@@ -1715,7 +1722,7 @@ namespace SettingsRegistryTests
TEST_F(SettingsRegistryTest, MergeSettingsFolder_EmptyFolder_ReportsSuccessButNothingAdded)
{
bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {}, nullptr);
bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {});
EXPECT_TRUE(result);
EXPECT_EQ(AZ::SettingsRegistryInterface::Type::Object, m_registry->GetType(AZ_SETTINGS_REGISTRY_HISTORY_KEY "/0")); // Folder and specialization settings.
@@ -1727,7 +1734,7 @@ namespace SettingsRegistryTests
constexpr AZStd::fixed_string<AZ::IO::MaxPathLength + 1> path(AZ::IO::MaxPathLength + 1, 'a');
AZ_TEST_START_TRACE_SUPPRESSION;
bool result = m_registry->MergeSettingsFolder(path, { "editor", "test" }, {}, nullptr);
bool result = m_registry->MergeSettingsFolder(path, { "editor", "test" }, {});
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
EXPECT_FALSE(result);
@@ -1744,7 +1751,7 @@ namespace SettingsRegistryTests
AZ_TEST_START_TRACE_SUPPRESSION;
m_testFolder->push_back(AZ_CORRECT_DATABASE_SEPARATOR);
*m_testFolder += AZ::SettingsRegistryInterface::RegistryFolder;
bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {}, nullptr);
bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {});
EXPECT_GT(::UnitTest::TestRunner::Instance().StopAssertTests(), 0);
EXPECT_FALSE(result);
+21 -3
View File
@@ -551,19 +551,37 @@ namespace Benchmark
{
class TaskGraphBenchmarkFixture : public ::benchmark::Fixture
{
public:
void SetUp(benchmark::State&) override
void internalSetUp()
{
executor = new TaskExecutor;
graph = new TaskGraph;
}
void TearDown(benchmark::State&) override
void internalTearDown()
{
delete graph;
delete executor;
}
public:
void SetUp(const benchmark::State&) override
{
internalSetUp();
}
void SetUp(benchmark::State&) override
{
internalSetUp();
}
void TearDown(const benchmark::State&) override
{
internalTearDown();
}
void TearDown(benchmark::State&) override
{
internalTearDown();
}
TaskDescriptor descriptors[4] = { { "critical", "benchmark", TaskPriority::CRITICAL },
{ "high", "benchmark", TaskPriority::HIGH },
{ "medium", "benchmark", TaskPriority::MEDIUM },
@@ -37,6 +37,7 @@ set(FILES
FileIOBaseTestTypes.h
Geometry2DUtils.cpp
Interface.cpp
IO/FileReaderTests.cpp
IO/Path/PathTests.cpp
IPC.cpp
Jobs.cpp
@@ -81,71 +81,6 @@ namespace AzFramework
static constexpr const char s_prefabSystemKey[] = "/Amazon/Preferences/EnablePrefabSystem";
static constexpr const char s_prefabWipSystemKey[] = "/Amazon/Preferences/EnablePrefabSystemWipFeatures";
static constexpr const char s_legacySlicesAssertKey[] = "/Amazon/Preferences/ShouldAssertForLegacySlicesUsage";
// A Helper function that can load an app descriptor from file.
AZ::Outcome<AZStd::unique_ptr<AZ::ComponentApplication::Descriptor>, AZStd::string> LoadDescriptorFromFilePath(const char* appDescriptorFilePath, AZ::SerializeContext& serializeContext)
{
AZStd::unique_ptr<AZ::ComponentApplication::Descriptor> loadedDescriptor;
AZ::IO::SystemFile appDescriptorFile;
if (!appDescriptorFile.Open(appDescriptorFilePath, AZ::IO::SystemFile::SF_OPEN_READ_ONLY))
{
return AZ::Failure(AZStd::string::format("Failed to open file: %s", appDescriptorFilePath));
}
AZ::IO::SystemFileStream appDescriptorFileStream(&appDescriptorFile, true);
if (!appDescriptorFileStream.IsOpen())
{
return AZ::Failure(AZStd::string::format("Failed to stream file: %s", appDescriptorFilePath));
}
// Callback function for allocating the root elements in the file.
AZ::ObjectStream::InplaceLoadRootInfoCB inplaceLoadCb =
[](void** rootAddress, const AZ::SerializeContext::ClassData**, const AZ::Uuid& classId, AZ::SerializeContext*)
{
if (rootAddress && classId == azrtti_typeid<AZ::ComponentApplication::Descriptor>())
{
// ComponentApplication::Descriptor is normally a singleton.
// Force a unique instance to be created.
*rootAddress = aznew AZ::ComponentApplication::Descriptor();
}
};
// Callback function for saving the root elements in the file.
AZ::ObjectStream::ClassReadyCB classReadyCb =
[&loadedDescriptor](void* classPtr, const AZ::Uuid& classId, AZ::SerializeContext* context)
{
// Save descriptor, delete anything else loaded from file.
if (classId == azrtti_typeid<AZ::ComponentApplication::Descriptor>())
{
loadedDescriptor.reset(static_cast<AZ::ComponentApplication::Descriptor*>(classPtr));
}
else if (const AZ::SerializeContext::ClassData* classData = context->FindClassData(classId))
{
classData->m_factory->Destroy(classPtr);
}
else
{
AZ_Error("Application", false, "Unexpected type %s found in application descriptor file. This memory will leak.",
classId.ToString<AZStd::string>().c_str());
}
};
// There's other stuff in the file we may not recognize (system components), but we're not interested in that stuff.
AZ::ObjectStream::FilterDescriptor loadFilter(&AZ::Data::AssetFilterNoAssetLoading, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES);
if (!AZ::ObjectStream::LoadBlocking(&appDescriptorFileStream, serializeContext, classReadyCb, loadFilter, inplaceLoadCb))
{
return AZ::Failure(AZStd::string::format("Failed to load objects from file: %s", appDescriptorFilePath));
}
if (!loadedDescriptor)
{
return AZ::Failure(AZStd::string::format("Failed to find descriptor object in file: %s", appDescriptorFilePath));
}
return AZ::Success(AZStd::move(loadedDescriptor));
}
}
Application::Application()
File diff suppressed because it is too large Load Diff
@@ -19,6 +19,7 @@
#include <AzCore/IO/CompressionBus.h>
#include <AzCore/Outcome/Outcome.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/std/containers/set.h>
#include <AzCore/std/parallel/mutex.h>
#include <AzCore/std/parallel/lock.h>
#include <AzCore/std/parallel/thread.h>
@@ -26,7 +27,6 @@
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzCore/std/string/fixed_string.h>
#include <AzCore/std/string/osstring.h>
#include <AzFramework/Archive/IArchive.h>
#include <AzFramework/Archive/ZipDirCache.h>
@@ -115,12 +115,12 @@ namespace AZ::IO
struct PackDesc
{
AZ::IO::Path m_pathBindRoot; // the zip binding root
AZStd::string strFileName; // the zip file name (with path) - very useful for debugging so please don't remove
AZ::IO::Path m_strFileName; // the zip file name (with path) - very useful for debugging so please don't remove
// [LYN-2376] Remove once legacy slice support is removed
bool m_containsLevelPak = false; // indicates whether this archive has level.pak inside it or not
const char* GetFullPath() const { return pZip->GetFilePath(); }
AZ::IO::PathView GetFullPath() const { return pZip->GetFilePath(); }
AZStd::intrusive_ptr<INestedArchive> pArchive;
ZipDir::CachePtr pZip;
@@ -129,10 +129,7 @@ namespace AZ::IO
// ArchiveFindDataSet entire purpose is to keep a reference to the intrusive_ptr of ArchiveFindData
// so that it doesn't go out of scope
using ArchiveFindDataSet = AZStd::set<AZStd::intrusive_ptr<AZ::IO::FindData>, AZ::OSStdAllocator>;
// given the source relative path, constructs the full path to the file according to the flags
const char* AdjustFileName(AZStd::string_view src, char* dst, size_t dstSize, uint32_t nFlags, bool skipMods = false) override;
using ArchiveFindDataSet = AZStd::set<AZStd::intrusive_ptr<AZ::IO::FindData>>;
/**
@@ -154,29 +151,17 @@ namespace AZ::IO
//! CompressionBus Handler implementation.
void FindCompressionInfo(bool& found, AZ::IO::CompressionInfo& info, const AZStd::string_view filename) override;
//! Processes an alias command line containing multiple aliases.
void ParseAliases(AZStd::string_view szCommandLine) override;
//! adds or removes an alias from the list - if bAdd set to false will remove it
void SetAlias(AZStd::string_view szName, AZStd::string_view szAlias, bool bAdd) override;
//! gets an alias from the list, if any exist.
//! if bReturnSame==true, it will return the input name if an alias doesn't exist. Otherwise returns nullptr
const char* GetAlias(AZStd::string_view szName, bool bReturnSame = true) override;
// Set the localization folder
void SetLocalizationFolder(AZStd::string_view sLocalizationFolder) override;
const char* GetLocalizationFolder() const override { return m_sLocalizationFolder.c_str(); }
const char* GetLocalizationRoot() const override { return m_sLocalizationRoot.c_str(); }
// lock all the operations
void Lock() override;
void Unlock() override;
// open the physical archive file - creates if it doesn't exist
// returns nullptr if it's invalid or can't open the file
AZStd::intrusive_ptr<INestedArchive> OpenArchive(AZStd::string_view szPath, AZStd::string_view bindRoot = {}, uint32_t nFlags = 0, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pData = nullptr) override;
AZStd::intrusive_ptr<INestedArchive> OpenArchive(AZStd::string_view szPath, AZStd::string_view bindRoot = {}, uint32_t nArchiveFlags = 0, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pData = nullptr) override;
// returns the path to the archive in which the file was opened
const char* GetFileArchivePath(AZ::IO::HandleType fileHandle) override;
AZ::IO::PathView GetFileArchivePath(AZ::IO::HandleType fileHandle) override;
//////////////////////////////////////////////////////////////////////////
@@ -192,40 +177,31 @@ namespace AZ::IO
void RegisterFileAccessSink(IArchiveFileAccessSink* pSink) override;
void UnregisterFileAccessSink(IArchiveFileAccessSink* pSink) override;
bool Init(AZStd::string_view szBasePath) override;
void Release() override;
bool IsInstalledToHDD(AZStd::string_view acFilePath = 0) const override;
// [LYN-2376] Remove 'addLevels' parameter once legacy slice support is removed
bool OpenPack(AZStd::string_view pName, uint32_t nFlags = 0, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pData = nullptr, AZ::IO::FixedMaxPathString* pFullPath = nullptr, bool addLevels = true) override;
bool OpenPack(AZStd::string_view szBindRoot, AZStd::string_view pName, uint32_t nFlags = 0, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pData = nullptr, AZ::IO::FixedMaxPathString* pFullPath = nullptr, bool addLevels = true) override;
bool OpenPack(AZStd::string_view pName, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pData = nullptr, AZ::IO::FixedMaxPathString* pFullPath = nullptr, bool addLevels = true) override;
bool OpenPack(AZStd::string_view szBindRoot, AZStd::string_view pName, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pData = nullptr, AZ::IO::FixedMaxPathString* pFullPath = nullptr, bool addLevels = true) override;
// after this call, the file will be unlocked and closed, and its contents won't be used to search for files
bool ClosePack(AZStd::string_view pName, uint32_t nFlags = 0) override;
bool OpenPacks(AZStd::string_view pWildcard, uint32_t nFlags = 0, AZStd::vector<AZ::IO::FixedMaxPathString>* pFullPaths = nullptr) override;
bool OpenPacks(AZStd::string_view szBindRoot, AZStd::string_view pWildcard, uint32_t nFlags = 0, AZStd::vector<AZ::IO::FixedMaxPathString>* pFullPaths = nullptr) override;
bool ClosePack(AZStd::string_view pName) override;
bool OpenPacks(AZStd::string_view pWildcard, AZStd::vector<AZ::IO::FixedMaxPathString>* pFullPaths = nullptr) override;
bool OpenPacks(AZStd::string_view szBindRoot, AZStd::string_view pWildcard, AZStd::vector<AZ::IO::FixedMaxPathString>* pFullPaths = nullptr) override;
// closes pack files by the path and wildcard
bool ClosePacks(AZStd::string_view pWildcard, uint32_t nFlags = 0) override;
bool ClosePacks(AZStd::string_view pWildcard) override;
//returns if a archive exists matching the wildcard
bool FindPacks(AZStd::string_view pWildcardIn) override;
// prevent access to specific archive files
bool SetPacksAccessible(bool bAccessible, AZStd::string_view pWildcard, uint32_t nFlags = 0) override;
bool SetPackAccessible(bool bAccessible, AZStd::string_view pName, uint32_t nFlags = 0) override;
bool SetPacksAccessible(bool bAccessible, AZStd::string_view pWildcard) override;
bool SetPackAccessible(bool bAccessible, AZStd::string_view pName) override;
// returns the file modification time
uint64_t GetModificationTime(AZ::IO::HandleType fileHandle) override;
bool LoadPakToMemory(AZStd::string_view pName, EInMemoryArchiveLocation nLoadArchiveToMemory, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pMemoryBlock = nullptr) override;
void LoadPaksToMemory(int nMaxArchiveSize, bool bLoadToMemory) override;
AZ::IO::HandleType FOpen(AZStd::string_view pName, const char* mode, uint32_t nPathFlags = 0) override;
size_t FReadRaw(void* data, size_t length, size_t elems, AZ::IO::HandleType handle) override;
size_t FReadRawAll(void* data, size_t nFileSize, AZ::IO::HandleType handle) override;
AZ::IO::HandleType FOpen(AZStd::string_view pName, const char* mode) override;
size_t FRead(void* data, size_t bytesToRead, AZ::IO::HandleType handle) override;
void* FGetCachedFileData(AZ::IO::HandleType handle, size_t& nFileSize) override;
size_t FWrite(const void* data, size_t length, size_t elems, AZ::IO::HandleType handle) override;
size_t FWrite(const void* data, size_t bytesToWrite, AZ::IO::HandleType handle) override;
size_t FSeek(AZ::IO::HandleType handle, uint64_t seek, int mode) override;
uint64_t FTell(AZ::IO::HandleType handle) override;
int FFlush(AZ::IO::HandleType handle) override;
@@ -234,9 +210,7 @@ namespace AZ::IO
AZ::IO::ArchiveFileIterator FindNext(AZ::IO::ArchiveFileIterator fileIterator) override;
bool FindClose(AZ::IO::ArchiveFileIterator fileIterator) override;
int FEof(AZ::IO::HandleType handle) override;
char* FGets(char*, int, AZ::IO::HandleType) override;
int Getc(AZ::IO::HandleType) override;
int FPrintf(AZ::IO::HandleType handle, const char* format, ...) override;
size_t FGetSize(AZ::IO::HandleType fileHandle) override;
size_t FGetSize(AZStd::string_view sFilename, bool bAllowUseFileSystem = false) override;
bool IsInPak(AZ::IO::HandleType handle) override;
@@ -248,9 +222,6 @@ namespace AZ::IO
bool IsFolder(AZStd::string_view sPath) override;
IArchive::SignedFileSize GetFileSizeOnDisk(AZStd::string_view filename) override;
// creates a directory
bool MakeDir(AZStd::string_view szPath) override;
// compresses the raw data into raw data. The buffer for compressed data itself with the heap passed. Uses method 8 (deflate)
// returns one of the Z_* errors (Z_OK upon success)
// MT-safe
@@ -275,22 +246,12 @@ namespace AZ::IO
IResourceList* GetResourceList(ERecordFileOpenList eList) override;
void SetResourceList(ERecordFileOpenList eList, IResourceList* pResourceList) override;
uint32_t ComputeCRC(AZStd::string_view szPath, uint32_t nFileOpenFlags = 0) override;
bool ComputeMD5(AZStd::string_view szPath, uint8_t* md5, uint32_t nFileOpenFlags = 0, bool useDirectFileAccess = false) override;
void DisableRuntimeFileAccess(bool status) override
{
m_disableRuntimeFileAccess[0] = status;
m_disableRuntimeFileAccess[1] = status;
m_disableRuntimeFileAccess = status;
}
bool DisableRuntimeFileAccess(bool status, AZStd::thread_id threadId) override;
bool CheckFileAccessDisabled(AZStd::string_view name, const char* mode) override;
void SetRenderThreadId(AZStd::thread_id renderThreadId) override
{
m_renderThreadId = renderThreadId;
}
// gets the current archive priority
ArchiveLocationPriority GetPakPriority() const override;
@@ -307,11 +268,11 @@ namespace AZ::IO
// Return cached file data for entries inside archive file.
CCachedFileDataPtr GetOpenedFileDataInZip(AZ::IO::HandleType file);
ZipDir::FileEntry* FindPakFileEntry(AZStd::string_view szPath, uint32_t& nArchiveFlags,
ZipDir::CachePtr* pZip = {}, bool bSkipInMemoryArchives = {}) const;
ZipDir::CachePtr* pZip = {}) const;
private:
bool OpenPackCommon(AZStd::string_view szBindRoot, AZStd::string_view pName, uint32_t nArchiveFlags, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pData = nullptr, bool addLevels = true);
bool OpenPacksCommon(AZStd::string_view szDir, AZStd::string_view pWildcardIn, uint32_t nArchiveFlags, AZStd::vector<AZ::IO::FixedMaxPathString>* pFullPaths = nullptr, bool addLevels = true);
bool OpenPackCommon(AZStd::string_view szBindRoot, AZStd::string_view pName, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pData = nullptr, bool addLevels = true);
bool OpenPacksCommon(AZStd::string_view szDir, AZStd::string_view pWildcardIn, AZStd::vector<AZ::IO::FixedMaxPathString>* pFullPaths = nullptr, bool addLevels = true);
ZipDir::FileEntry* FindPakFileEntry(AZStd::string_view szPath) const;
@@ -346,9 +307,6 @@ namespace AZ::IO
AZStd::mutex m_cachedFileRawDataMutex;
// For m_pCachedFileRawDataSet
using RawDataCacheLockGuard = AZStd::scoped_lock<decltype(m_cachedFileRawDataMutex)>;
// The F* emulation functions critical section: protects all F* functions
// that don't have a chance to be called recursively (to avoid deadlocks)
AZStd::mutex m_csMain;
mutable AZStd::shared_mutex m_archiveMutex;
ArchiveArray m_arrArchives;
@@ -360,8 +318,6 @@ namespace AZ::IO
//////////////////////////////////////////////////////////////////////////
IArchive::ERecordFileOpenList m_eRecordFileOpenList = RFOM_Disabled;
using RecordedFilesSet = AZStd::set<AZ::OSString, AZ::IO::AZStdStringLessCaseInsensitive, AZ::OSStdAllocator>;
RecordedFilesSet m_recordedFilesSet;
AZStd::intrusive_ptr<IResourceList> m_pEngineStartupResourceList;
@@ -372,28 +328,16 @@ namespace AZ::IO
float m_fFileAccessTime{}; // Time used to perform file operations
AZStd::vector<IArchiveFileAccessSink*, AZ::OSStdAllocator> m_FileAccessSinks; // useful for gathering file access statistics
bool m_disableRuntimeFileAccess[2]{};
bool m_disableRuntimeFileAccess{};
//threads which we don't want to access files from during the game
AZStd::thread_id m_mainThreadId{};
AZStd::thread_id m_renderThreadId{};
AZStd::fixed_string<128> m_sLocalizationFolder;
AZStd::fixed_string<128> m_sLocalizationRoot;
AZStd::set<uint32_t, AZStd::less<>, AZ::OSStdAllocator> m_filesCachedOnHDD;
// [LYN-2376] Remove once legacy slice support is removed
LevelPackOpenEvent m_levelOpenEvent;
LevelPackCloseEvent m_levelCloseEvent;
};
}
namespace AZ::IO::ArchiveInternal
{
// Utility function to de-alias archive file opening and file-within-archive opening
// if the file specified was an absolute path but it points at one of the aliases, de-alias it and replace it with that alias.
// this works around problems where the level editor is in control but still mounts asset packs (ie, level.pak mounted as @assets@)
AZStd::optional<AZ::IO::FixedMaxPath> ConvertAbsolutePathToAliasedPath(AZStd::string_view sourcePath,
AZStd::string_view aliasToLookFor = "@devassets@", AZStd::string_view aliasToReplaceWith = "@assets@");
}
@@ -5,10 +5,9 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/IO/SystemFile.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/std/parallel/lock.h>
#include <AzCore/std/functional.h> // for function<> in the find files callback.
#include <AzCore/StringFunc/StringFunc.h>
#include <AzFramework/Archive/ArchiveFileIO.h>
#include <AzFramework/Archive/IArchive.h>
@@ -188,7 +187,7 @@ namespace AZ::IO
return IO::ResultCode::Error;
}
size_t result = m_archive->FReadRaw(buffer, 1, size, fileHandle);
size_t result = m_archive->FRead(buffer, size, fileHandle);
if (bytesRead)
{
*bytesRead = static_cast<AZ::u64>(result);
@@ -213,7 +212,7 @@ namespace AZ::IO
return IO::ResultCode::Error;
}
size_t result = m_archive->FWrite(buffer, 1, size, fileHandle);
size_t result = m_archive->FWrite(buffer, size, fileHandle);
if (bytesWritten)
{
*bytesWritten = static_cast<AZ::u64>(result);
@@ -357,14 +356,8 @@ namespace AZ::IO
return IO::ResultCode::Error;
}
// avoid using AZStd::string if possible - use OSString instead of StringFunc
AZ::OSString destPath(destinationFilePath);
IO::Path destPath(IO::PathView(destinationFilePath).ParentPath());
AZ::OSString::size_type pos = destPath.find_last_of(AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR);
if (pos != AZ::OSString::npos)
{
destPath.resize(pos);
}
CreatePath(destPath.c_str());
if (!Open(destinationFilePath, IO::OpenMode::ModeWrite | IO::OpenMode::ModeBinary, destinationFile))
@@ -466,31 +459,25 @@ namespace AZ::IO
return IO::ResultCode::Error;
}
AZStd::fixed_string<AZ_MAX_PATH_LEN> total = filePath;
AZ::IO::FixedMaxPath total = filePath;
if (total.empty())
{
return IO::ResultCode::Error;
}
if (!total.ends_with(AZ_CORRECT_FILESYSTEM_SEPARATOR) && !total.ends_with(AZ_WRONG_FILESYSTEM_SEPARATOR))
{
total.append(AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING);
}
total.append(filter);
total /= filter;
AZ::IO::ArchiveFileIterator fileIterator = m_archive->FindFirst(total.c_str());
if (!fileIterator)
{
return IO::ResultCode::Success; // its not an actual fatal error to not find anything.
}
for (;fileIterator; fileIterator = m_archive->FindNext(fileIterator))
for (; fileIterator; fileIterator = m_archive->FindNext(fileIterator))
{
total = AZStd::fixed_string<AZ_MAX_PATH_LEN>::format("%s/%.*s", filePath, aznumeric_cast<int>(fileIterator.m_filename.size()), fileIterator.m_filename.data());
AZStd::optional resolvedAliasLength = ConvertToAlias(total.data(), total.capacity());
if (resolvedAliasLength)
total = filePath;
total /= fileIterator.m_filename;
if (ConvertToAlias(total, total))
{
total.resize_no_construct(*resolvedAliasLength);
if (!callback(total.c_str()))
{
break;
@@ -510,8 +497,13 @@ namespace AZ::IO
const auto fileIt = m_trackedFiles.find(fileHandle);
if (fileIt != m_trackedFiles.end())
{
AZ_Assert(filenameSize >= fileIt->second.length(), "Filename size %" PRIu64 " is larger than the size of the tracked file %s:%zu", fileIt->second.c_str(), fileIt->second.size());
azstrncpy(filename, filenameSize, fileIt->second.c_str(), fileIt->second.length());
const AZStd::string_view trackedFileView = fileIt->second.Native();
if (filenameSize <= trackedFileView.size())
{
return false;
}
size_t trackedFileViewLength = trackedFileView.copy(filename, trackedFileView.size());
filename[trackedFileViewLength] = '\0';
return true;
}
@@ -13,7 +13,6 @@
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/containers/fixed_vector.h>
#include <AzCore/std/parallel/mutex.h>
#include <AzCore/std/string/osstring.h>
namespace AZ::IO
@@ -65,7 +64,7 @@ namespace AZ::IO
void SetAlias(const char* alias, const char* path) override;
void ClearAlias(const char* alias) override;
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override;
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const;
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override;
using FileIOBase::ConvertToAlias;
const char* GetAlias(const char* alias) const override;
bool ResolvePath(const char* path, char* resolvedPath, AZ::u64 resolvedPathSize) const override;
@@ -78,7 +77,7 @@ namespace AZ::IO
protected:
// we keep a list of file names ever opened so that we can easily return it.
mutable AZStd::recursive_mutex m_operationGuard;
AZStd::unordered_map<IO::HandleType, AZ::OSString, AZStd::hash<IO::HandleType>, AZStd::equal_to<IO::HandleType>, AZ::OSStdAllocator> m_trackedFiles;
AZStd::unordered_map<IO::HandleType, AZ::IO::Path> m_trackedFiles;
AZStd::fixed_vector<char, ArchiveFileIoMaxBuffersize> m_copyBuffer;
IArchive* m_archive;
};
@@ -15,34 +15,6 @@
namespace AZ::IO
{
size_t ArchiveFileIteratorHash::operator()(const AZ::IO::ArchiveFileIterator& iter) const
{
return iter.GetHash();
}
bool AZStdStringLessCaseInsensitive::operator()(AZStd::string_view left, AZStd::string_view right) const
{
// If one or both strings are 0-length, return true if the left side is smaller, false if they're equal or left is larger.
size_t compareLength = (AZStd::min)(left.size(), right.size());
if (compareLength == 0)
{
return left.size() < right.size();
}
// They're both non-zero, so compare the strings up until the length of the shorter string.
int compareResult = azstrnicmp(left.data(), right.data(), compareLength);
// If both strings are equal for the number of characters compared, return true if the left side is shorter, false if
// they're equal or left is longer.
if (compareResult == 0)
{
return left.size() < right.size();
}
// Return true if the left side should come first alphabetically, false if the right side should.
return compareResult < 0;
}
FileDesc::FileDesc(Attribute fileAttribute, uint64_t fileSize, time_t accessTime, time_t creationTime, time_t writeTime)
: nAttrib{ fileAttribute }
, nSize{ fileSize }
@@ -52,10 +24,9 @@ namespace AZ::IO
{
}
ArchiveFileIterator::ArchiveFileIterator(FindData* findData, AZStd::string_view filename, const FileDesc& fileDesc)
// ArchiveFileIterator
ArchiveFileIterator::ArchiveFileIterator(FindData* findData)
: m_findData{ findData }
, m_filename{ filename }
, m_fileDesc{ fileDesc }
{
}
@@ -73,21 +44,36 @@ namespace AZ::IO
return operator++();
}
bool ArchiveFileIterator::operator==(const AZ::IO::ArchiveFileIterator& rhs) const
{
return GetHash() == rhs.GetHash();
}
ArchiveFileIterator::operator bool() const
{
return m_findData && m_lastFetchValid;
}
size_t ArchiveFileIterator::GetHash() const
// FindData::ArchiveFile
FindData::ArchiveFile::ArchiveFile() = default;
FindData::ArchiveFile::ArchiveFile(AZStd::string_view filename, const FileDesc& fileDesc)
: m_filename(filename)
, m_fileDesc(fileDesc)
{
}
size_t FindData::ArchiveFile::GetHash() const
{
return AZStd::hash<AZ::IO::PathView>{}(m_filename.c_str());
}
bool FindData::ArchiveFile::operator==(const ArchiveFile& rhs) const
{
return GetHash() == rhs.GetHash();
}
// FindData::ArchiveFilehash
size_t FindData::ArchiveFileHash::operator()(const ArchiveFile& archiveFile) const
{
return archiveFile.GetHash();
}
// FindData
void FindData::Scan(IArchive* archive, AZStd::string_view szDir, bool bAllowUseFS, bool bScanZips)
{
// get the priority into local variable to avoid it changing in the course of
@@ -119,40 +105,37 @@ namespace AZ::IO
void FindData::ScanFS([[maybe_unused]] IArchive* archive, AZStd::string_view szDirIn)
{
AZStd::string searchDirectory;
AZStd::string pattern;
AZ::IO::PathView directory{ szDirIn };
AZ::IO::FixedMaxPath searchDirectory = directory.ParentPath();
AZ::IO::FixedMaxPath pattern = directory.Filename();
auto ScanFileSystem = [this](const char* filePath) -> bool
{
AZ::IO::PathString directory{ szDirIn };
AZ::StringFunc::Path::GetFullPath(directory.c_str(), searchDirectory);
AZ::StringFunc::Path::GetFullFileName(directory.c_str(), pattern);
}
AZ::IO::FileIOBase::GetDirectInstance()->FindFiles(searchDirectory.c_str(), pattern.c_str(), [&](const char* filePath) -> bool
{
AZ::IO::ArchiveFileIterator fileIterator{ nullptr, AZ::IO::PathView(filePath).Filename().Native(), {} };
ArchiveFile archiveFile{ AZ::IO::PathView(filePath).Filename().Native(), {} };
if (AZ::IO::FileIOBase::GetDirectInstance()->IsDirectory(filePath))
{
fileIterator.m_fileDesc.nAttrib = fileIterator.m_fileDesc.nAttrib | AZ::IO::FileDesc::Attribute::Subdirectory;
m_fileSet.emplace(AZStd::move(fileIterator));
archiveFile.m_fileDesc.nAttrib = archiveFile.m_fileDesc.nAttrib | AZ::IO::FileDesc::Attribute::Subdirectory;
m_fileSet.emplace(AZStd::move(archiveFile));
}
else
{
if (AZ::IO::FileIOBase::GetDirectInstance()->IsReadOnly(filePath))
{
fileIterator.m_fileDesc.nAttrib = fileIterator.m_fileDesc.nAttrib | AZ::IO::FileDesc::Attribute::ReadOnly;
archiveFile.m_fileDesc.nAttrib = archiveFile.m_fileDesc.nAttrib | AZ::IO::FileDesc::Attribute::ReadOnly;
}
AZ::u64 fileSize = 0;
AZ::IO::FileIOBase::GetDirectInstance()->Size(filePath, fileSize);
fileIterator.m_fileDesc.nSize = fileSize;
fileIterator.m_fileDesc.tWrite = AZ::IO::FileIOBase::GetDirectInstance()->ModificationTime(filePath);
archiveFile.m_fileDesc.nSize = fileSize;
archiveFile.m_fileDesc.tWrite = AZ::IO::FileIOBase::GetDirectInstance()->ModificationTime(filePath);
// These times are not supported by our file interface
fileIterator.m_fileDesc.tAccess = fileIterator.m_fileDesc.tWrite;
fileIterator.m_fileDesc.tCreate = fileIterator.m_fileDesc.tWrite;
m_fileSet.emplace(AZStd::move(fileIterator));
archiveFile.m_fileDesc.tAccess = archiveFile.m_fileDesc.tWrite;
archiveFile.m_fileDesc.tCreate = archiveFile.m_fileDesc.tWrite;
m_fileSet.emplace(AZStd::move(archiveFile));
}
return true;
});
};
AZ::IO::FileIOBase::GetDirectInstance()->FindFiles(searchDirectory.c_str(), pattern.c_str(), ScanFileSystem);
}
//////////////////////////////////////////////////////////////////////////
@@ -180,7 +163,7 @@ namespace AZ::IO
fileDesc.nAttrib = AZ::IO::FileDesc::Attribute::ReadOnly | AZ::IO::FileDesc::Attribute::Archive;
fileDesc.nSize = fileEntry->desc.lSizeUncompressed;
fileDesc.tWrite = fileEntry->GetModificationTime();
m_fileSet.emplace(AZ::IO::ArchiveFileIterator{ this, fname, fileDesc });
m_fileSet.emplace(fname, fileDesc);
}
ZipDir::FindDir findDirectoryEntry(zipCache);
@@ -193,7 +176,7 @@ namespace AZ::IO
}
AZ::IO::FileDesc fileDesc;
fileDesc.nAttrib = AZ::IO::FileDesc::Attribute::ReadOnly | AZ::IO::FileDesc::Attribute::Archive | AZ::IO::FileDesc::Attribute::Subdirectory;
m_fileSet.emplace(AZ::IO::ArchiveFileIterator{ this, fname, fileDesc });
m_fileSet.emplace(fname, fileDesc);
}
};
@@ -208,30 +191,16 @@ namespace AZ::IO
// so there's really no way to filter out opening the pack and looking at the files inside.
// however, the bind root is not part of the inner zip entry name either
// and the ZipDir::FindFile actually expects just the chopped off piece.
// we have to find whats in common between them and check that:
// we have to find the common path segments between them and check that:
auto resolvedBindRoot = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(it->m_pathBindRoot);
if (!resolvedBindRoot)
AZ::IO::FixedMaxPath bindRoot;
if (!AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(bindRoot, it->m_pathBindRoot))
{
AZ_Assert(false, "Unable to resolve Path for archive %s bind root %s", it->GetFullPath(), it->m_pathBindRoot.c_str());
return;
}
AZ::IO::FixedMaxPath bindRoot{ *resolvedBindRoot };
auto [bindRootIter, sourcePathIter] = AZStd::mismatch(AZStd::begin(bindRoot), AZStd::end(bindRoot),
AZStd::begin(sourcePath), AZStd::end(sourcePath));
if (sourcePathIter == AZStd::begin(sourcePath))
{
// The path has no characters in common , early out the search as filepath is not part of the iterated zip
continue;
}
AZ::IO::FixedMaxPath sourcePathRemainder;
for (; sourcePathIter != AZStd::end(sourcePath); ++sourcePathIter)
{
sourcePathRemainder /= *sourcePathIter;
}
// Example:
// "@assets@\\levels\\*" <--- szDir
// "@assets@\\" <--- mount point
@@ -256,18 +225,26 @@ namespace AZ::IO
// then it means that the pack's mount point itself might be a return value, not the files inside the pack
// in that case, we compare the mount point remainder itself with the search filter
auto [bindRootIter, sourcePathIter] = AZStd::mismatch(bindRoot.begin(), bindRoot.end(),
sourcePath.begin(), sourcePath.end());
if (bindRootIter != bindRoot.end())
{
AZ::IO::FixedMaxPath sourcePathRemainder;
for (; sourcePathIter != sourcePath.end(); ++sourcePathIter)
{
sourcePathRemainder /= *sourcePathIter;
}
// Retrieve next path component of the mount point remainder
if (!bindRootIter->empty() && AZStd::wildcard_match(sourcePathRemainder.Native(), bindRootIter->Native()))
if (!bindRootIter->empty() && bindRootIter->Match(sourcePathRemainder.Native()))
{
AZ::IO::FileDesc fileDesc{ AZ::IO::FileDesc::Attribute::ReadOnly | AZ::IO::FileDesc::Attribute::Archive | AZ::IO::FileDesc::Attribute::Subdirectory };
m_fileSet.emplace(AZ::IO::ArchiveFileIterator{ this, bindRootIter->Native(), fileDesc });
m_fileSet.emplace(AZStd::move(bindRootIter->Native()), fileDesc);
}
}
else
{
AZ::IO::FixedMaxPath sourcePathRemainder = sourcePath.LexicallyRelative(bindRoot);
// if we get here, it means that the search pattern's root and the mount point for this pack are identical
// which means we may search inside the pack.
ScanInZip(it->pZip.get(), sourcePathRemainder.Native());
@@ -280,17 +257,17 @@ namespace AZ::IO
{
if (m_fileSet.empty())
{
AZ::IO::ArchiveFileIterator emptyFileIterator;
emptyFileIterator.m_lastFetchValid = false;
emptyFileIterator.m_findData = this;
return emptyFileIterator;
return {};
}
// Remove Fetched item from the FindData map so that the iteration continues
AZ::IO::ArchiveFileIterator fileIterator{ *m_fileSet.begin() };
AZ::IO::ArchiveFileIterator fileIterator;
auto archiveFileIt = m_fileSet.begin();
fileIterator.m_filename = archiveFileIt->m_filename;
fileIterator.m_fileDesc = archiveFileIt->m_fileDesc;
fileIterator.m_lastFetchValid = true;
fileIterator.m_findData = this;
m_fileSet.erase(m_fileSet.begin());
m_fileSet.erase(archiveFileIt);
return fileIterator;
}
}
@@ -36,56 +36,72 @@ namespace AZ::IO
AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::IO::FileDesc::Attribute);
inline constexpr size_t ArchiveFilenameMaxLength = 256;
using ArchiveFileString = AZStd::fixed_string<ArchiveFilenameMaxLength>;
class FindData;
//! This is not really an iterator, but a handle
//! that extends ownership of any found filenames from an archive file or the file system
struct ArchiveFileIterator
{
ArchiveFileIterator() = default;
ArchiveFileIterator(FindData* findData, AZStd::string_view filename, const FileDesc& fileDesc);
explicit ArchiveFileIterator(FindData* findData);
ArchiveFileIterator operator++();
ArchiveFileIterator operator++(int);
bool operator==(const AZ::IO::ArchiveFileIterator& rhs) const;
explicit operator bool() const;
size_t GetHash() const;
inline static constexpr size_t FilenameMaxLength = 256;
AZStd::fixed_string<FilenameMaxLength> m_filename;
ArchiveFileString m_filename;
FileDesc m_fileDesc;
AZStd::intrusive_ptr<FindData> m_findData{};
private:
friend class FindData;
friend class Archive;
AZStd::intrusive_ptr<FindData> m_findData;
bool m_lastFetchValid{};
};
struct ArchiveFileIteratorHash
{
size_t operator()(const AZ::IO::ArchiveFileIterator& iter) const;
};
struct AZStdStringLessCaseInsensitive
{
bool operator()(AZStd::string_view left, AZStd::string_view right) const;
using is_transparent = void;
};
class FindData
: public AZStd::intrusive_base
{
public:
AZ_CLASS_ALLOCATOR(FindData, AZ::SystemAllocator, 0);
FindData() = default;
AZ::IO::ArchiveFileIterator Fetch();
ArchiveFileIterator Fetch();
void Scan(IArchive* archive, AZStd::string_view path, bool bAllowUseFS = false, bool bScanZips = true);
protected:
void ScanFS(IArchive* archive, AZStd::string_view path);
// Populates the FileSet with files within the that match the path pattern that is
// if it refers to a file within a bound archive root or returns the archive root
// path if the path pattern matches it.
void ScanZips(IArchive* archive, AZStd::string_view path);
using FileSet = AZStd::unordered_set<ArchiveFileIterator, ArchiveFileIteratorHash>;
class ArchiveFile
{
public:
friend class FindData;
ArchiveFile();
ArchiveFile(AZStd::string_view filename, const FileDesc& fileDesc);
size_t GetHash() const;
bool operator==(const ArchiveFile& rhs) const;
private:
ArchiveFileString m_filename;
FileDesc m_fileDesc;
};
struct ArchiveFileHash
{
size_t operator()(const ArchiveFile& archiveFile) const;
};
using FileSet = AZStd::unordered_set<ArchiveFile, ArchiveFileHash>;
FileSet m_fileSet;
};
}
@@ -12,12 +12,10 @@
#include <AzCore/EBus/Event.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/std/containers/map.h>
#include <AzCore/std/smart_ptr/intrusive_base.h>
#include <AzCore/std/smart_ptr/intrusive_ptr.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzCore/std/string/fixed_string.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <AzFramework/Archive/ArchiveFindData.h>
@@ -106,66 +104,6 @@ namespace AZ::IO
{
AZ_RTTI(IArchive, "{764A2260-FF8A-4C86-B958-EBB0B69D9DFA}");
using FileTime = uint64_t;
// Flags used in file path resolution rules
enum EPathResolutionRules
{
// If used, the source path will be treated as the destination path
// and no transformations will be done. Pass this flag when the path is to be the actual
// path on the disk/in the packs and doesn't need adjustment (or after it has come through adjustments already)
// if this is set, AdjustFileName will not map the input path into the folder (Ex: Shaders will not be converted to Game\Shaders)
FLAGS_PATH_REAL = 1 << 16,
// AdjustFileName will always copy the file path to the destination path:
// regardless of the returned value, szDestpath can be used
FLAGS_COPY_DEST_ALWAYS = 1 << 17,
// Adds trailing slash to the path
FLAGS_ADD_TRAILING_SLASH = 1L << 18,
// if this is set, AdjustFileName will not make relative paths into full paths
FLAGS_NO_FULL_PATH = 1 << 21,
// if this is set, AdjustFileName will redirect path to disc
FLAGS_REDIRECT_TO_DISC = 1 << 22,
// if this is set, AdjustFileName will not adjust path for writing files
FLAGS_FOR_WRITING = 1 << 23,
// if this is set, the archive would be stored in memory (gpu)
FLAGS_PAK_IN_MEMORY = 1 << 25,
// Store all file names as crc32 in a flat directory structure.
FLAGS_FILENAMES_AS_CRC32 = 1 << 26,
// if this is set, AdjustFileName will try to find the file under any mod paths we know about
FLAGS_CHECK_MOD_PATHS = 1 << 27,
// if this is set, AdjustFileName will always check the filesystem/disk and not check inside open archives
FLAGS_NEVER_IN_PAK = 1 << 28,
// returns existing file name from the local data or existing cache file name
// used by the resource compiler to pass the real file name
FLAGS_RESOLVE_TO_CACHE = 1 << 29,
// if this is set, the archive would be stored in memory (cpu)
FLAGS_PAK_IN_MEMORY_CPU = 1 << 30,
// if this is set, the level pak is inside another archive
FLAGS_LEVEL_PAK_INSIDE_PAK = 1 << 31,
};
// Used for widening FOpen functionality. They're ignored for the regular File System files.
enum EFOpenFlags
{
// If possible, will prevent the file from being read from memory.
FOPEN_HINT_DIRECT_OPERATION = 1,
// Will prevent a "missing file" warnings to be created.
FOPEN_HINT_QUIET = 1 << 1,
// File should be on disk
FOPEN_ONDISK = 1 << 2,
// Open is done by the streaming thread.
FOPEN_FORSTREAMING = 1 << 3,
};
//
enum ERecordFileOpenList
@@ -175,8 +113,6 @@ namespace AZ::IO
RFOM_Level, // during level loading till export2game -> resourcelist.txt, used to generate the list for level2level loading
RFOM_NextLevel // used for level2level loading
};
// the size of the buffer that receives the full path to the file
inline static constexpr size_t MaxPath = 1024;
//file location enum used in isFileExist to control where the archive system looks for the file.
enum EFileSearchLocation
@@ -205,63 +141,31 @@ namespace AZ::IO
virtual ~IArchive() = default;
/**
* Deprecated: Use the AZ::IO::FileIOBase::ResolvePath function below that doesn't accept the nFlags or skipMods parameters
* given the source relative path, constructs the full path to the file according to the flags
* returns the pointer to the constructed path (can be either szSourcePath, or szDestPath, or NULL in case of error
*/
//
virtual const char* AdjustFileName(AZStd::string_view src, char* dst, size_t dstSize, uint32_t nFlags, bool skipMods = false) = 0;
virtual bool Init(AZStd::string_view szBasePath) = 0;
virtual void Release() = 0;
// Summary:
// Returns true if given archivepath is installed to HDD
// If no file path is given it will return true if whole application is installed to HDD
virtual bool IsInstalledToHDD(AZStd::string_view acFilePath = 0) const = 0;
// after this call, the archive file will be searched for files when they aren't on the OS file system
// Arguments:
// pName - must not be 0
virtual bool OpenPack(AZStd::string_view pName, uint32_t nFlags = FLAGS_PATH_REAL, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pData = {},
virtual bool OpenPack(AZStd::string_view pName, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pData = {},
AZ::IO::FixedMaxPathString* pFullPath = nullptr, bool addLevels = true) = 0;
// after this call, the archive file will be searched for files when they aren't on the OS file system
virtual bool OpenPack(AZStd::string_view pBindingRoot, AZStd::string_view pName, uint32_t nFlags = FLAGS_PATH_REAL,
virtual bool OpenPack(AZStd::string_view pBindingRoot, AZStd::string_view pName,
AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pData = {}, AZ::IO::FixedMaxPathString* pFullPath = nullptr, bool addLevels = true) = 0;
// after this call, the file will be unlocked and closed, and its contents won't be used to search for files
virtual bool ClosePack(AZStd::string_view pName, uint32_t nFlags = FLAGS_PATH_REAL) = 0;
virtual bool ClosePack(AZStd::string_view pName) = 0;
// opens pack files by the path and wildcard
virtual bool OpenPacks(AZStd::string_view pWildcard, uint32_t nFlags = FLAGS_PATH_REAL, AZStd::vector<AZ::IO::FixedMaxPathString>* pFullPaths = nullptr) = 0;
virtual bool OpenPacks(AZStd::string_view pWildcard, AZStd::vector<AZ::IO::FixedMaxPathString>* pFullPaths = nullptr) = 0;
// opens pack files by the path and wildcard
virtual bool OpenPacks(AZStd::string_view pBindingRoot, AZStd::string_view pWildcard, uint32_t nFlags = FLAGS_PATH_REAL,
virtual bool OpenPacks(AZStd::string_view pBindingRoot, AZStd::string_view pWildcard,
AZStd::vector<AZ::IO::FixedMaxPathString>* pFullPaths = nullptr) = 0;
// closes pack files by the path and wildcard
virtual bool ClosePacks(AZStd::string_view pWildcard, uint32_t nFlags = FLAGS_PATH_REAL) = 0;
virtual bool ClosePacks(AZStd::string_view pWildcard) = 0;
//returns if a archive exists matching the wildcard
virtual bool FindPacks(AZStd::string_view pWildcardIn) = 0;
// Set access status of a archive files with a wildcard
virtual bool SetPacksAccessible(bool bAccessible, AZStd::string_view pWildcard, uint32_t nFlags = FLAGS_PATH_REAL) = 0;
virtual bool SetPacksAccessible(bool bAccessible, AZStd::string_view pWildcard) = 0;
// Set access status of a pack file
virtual bool SetPackAccessible(bool bAccessible, AZStd::string_view pName, uint32_t nFlags = FLAGS_PATH_REAL) = 0;
// Load or unload archive file completely to memory.
virtual bool LoadPakToMemory(AZStd::string_view pName, EInMemoryArchiveLocation eLoadToMemory, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pMemoryBlock = nullptr) = 0;
virtual void LoadPaksToMemory(int nMaxArchiveSize, bool bLoadToMemory) = 0;
// Processes an alias command line containing multiple aliases.
virtual void ParseAliases(AZStd::string_view szCommandLine) = 0;
// adds or removes an alias from the list
virtual void SetAlias(AZStd::string_view szName, AZStd::string_view szAlias, bool bAdd) = 0;
// gets an alias from the list, if any exist.
// if bReturnSame==true, it will return the input name if an alias doesn't exist. Otherwise returns NULL
virtual const char* GetAlias(AZStd::string_view szName, bool bReturnSame = true) = 0;
// lock all the operations
virtual void Lock() = 0;
virtual void Unlock() = 0;
virtual bool SetPackAccessible(bool bAccessible, AZStd::string_view pName) = 0;
// Set and Get the localization folder name (Languages, Localization, ...)
virtual void SetLocalizationFolder(AZStd::string_view sLocalizationFolder) = 0;
@@ -273,28 +177,19 @@ namespace AZ::IO
// ex: AZ::IO::HandleType fileHandle = FOpen( "test.txt","rbx" );
// mode x is a direct access mode, when used file reads will go directly into the low level file system without any internal data caching.
// Text mode is not supported for files in Archives.
// for nFlags @see IArchive::EFOpenFlags
virtual AZ::IO::HandleType FOpen(AZStd::string_view pName, const char* mode, uint32_t nFlags = 0) = 0;
// Read raw data from file, no endian conversion.
virtual size_t FReadRaw(void* data, size_t length, size_t elems, AZ::IO::HandleType fileHandle) = 0;
// Read all file contents into the provided memory, nSizeOfFile must be the same as returned by GetFileSize(handle)
// Current seek pointer is ignored and reseted to 0.
// no endian conversion.
virtual size_t FReadRawAll(void* data, size_t nFileSize, AZ::IO::HandleType fileHandle) = 0;
virtual AZ::IO::HandleType FOpen(AZStd::string_view pName, const char* mode) = 0;
// Get pointer to the internally cached, loaded data of the file.
// WARNING! The returned pointer is only valid while the fileHandle has not been closed.
virtual void* FGetCachedFileData(AZ::IO::HandleType fileHandle, size_t& nFileSize) = 0;
// Write file data, cannot be used for writing into the Archive.
// Use INestedArchive interface for writing into the archivefiles.
virtual size_t FWrite(const void* data, size_t length, size_t elems, AZ::IO::HandleType fileHandle) = 0;
// Read raw data from file, no endian conversion.
virtual size_t FRead(void* data, size_t bytesToRead, AZ::IO::HandleType fileHandle) = 0;
// Write file data, cannot be used for writing into the Archive.
// Use INestedArchive interface for writing into the archive files.
virtual size_t FWrite(const void* data, size_t bytesToWrite, AZ::IO::HandleType fileHandle) = 0;
virtual int FPrintf(AZ::IO::HandleType fileHandle, const char* format, ...) = 0;
virtual char* FGets(char*, int, AZ::IO::HandleType) = 0;
virtual int Getc(AZ::IO::HandleType) = 0;
virtual size_t FGetSize(AZ::IO::HandleType fileHandle) = 0;
virtual size_t FGetSize(AZStd::string_view pName, bool bAllowUseFileSystem = false) = 0;
virtual bool IsInPak(AZ::IO::HandleType fileHandle) = 0;
@@ -318,7 +213,6 @@ namespace AZ::IO
virtual AZStd::intrusive_ptr<AZ::IO::MemoryBlock> PoolAllocMemoryBlock(size_t nSize, const char* sUsage, size_t nAlign = 1) = 0;
// Arguments:
// nFlags is a combination of EPathResolutionRules flags.
virtual ArchiveFileIterator FindFirst(AZStd::string_view pDir, EFileSearchType searchType = eFileSearchType_AllowInZipsOnly) = 0;
virtual ArchiveFileIterator FindNext(AZ::IO::ArchiveFileIterator handle) = 0;
virtual bool FindClose(AZ::IO::ArchiveFileIterator handle) = 0;
@@ -334,9 +228,6 @@ namespace AZ::IO
virtual IArchive::SignedFileSize GetFileSizeOnDisk(AZStd::string_view filename) = 0;
// creates a directory
virtual bool MakeDir(AZStd::string_view szPath) = 0;
// open the physical archive file - creates if it doesn't exist
// returns NULL if it's invalid or can't open the file
// nFlags is a combination of flags from EArchiveFlags enum.
@@ -344,8 +235,8 @@ namespace AZ::IO
AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pData = nullptr) = 0;
// returns the path to the archive in which the file was opened
// returns NULL if the file is a physical file, and "" if the path to archive is unknown (shouldn't ever happen)
virtual const char* GetFileArchivePath(AZ::IO::HandleType fileHandle) = 0;
// returns empty path view if the file is a physical file
virtual AZ::IO::PathView GetFileArchivePath(AZ::IO::HandleType fileHandle) = 0;
// compresses the raw data into raw data. The buffer for compressed data itself with the heap passed. Uses method 8 (deflate)
// returns one of the Z_* errors (Z_OK upon success)
@@ -378,25 +269,7 @@ namespace AZ::IO
// get the current mode, can be set by RecordFileOpen()
virtual IArchive::ERecordFileOpenList GetRecordFileOpenList() = 0;
// computes CRC (zip compatible) for a file
// useful if a huge uncompressed file is generation in non continuous way
// good for big files - low memory overhead (1MB)
// Arguments:
// szPath - must not be 0
// Returns:
// error code
virtual uint32_t ComputeCRC(AZStd::string_view szPath, uint32_t nFileOpenFlags = 0) = 0;
// computes MD5 checksum for a file
// good for big files - low memory overhead (1MB)
// Arguments:
// szPath - must not be 0
// md5 - destination array of uint8_t [16]
// Returns:
// true if success, false on failure
virtual bool ComputeMD5(AZStd::string_view szPath, uint8_t* md5, uint32_t nFileOpenFlags = 0, bool useDirectFileAccess = false) = 0;
// useful for gathering file access statistics, assert if it was inserted already but then it does not become insersted
// useful for gathering file access statistics, assert if it was inserted already but then it does not become inserted
// Arguments:
// pSink - must not be 0
virtual void RegisterFileAccessSink(IArchiveFileAccessSink* pSink) = 0;
@@ -408,8 +281,6 @@ namespace AZ::IO
// When enabled, files accessed at runtime will be tracked
virtual void DisableRuntimeFileAccess(bool status) = 0;
virtual bool DisableRuntimeFileAccess(bool status, AZStd::thread_id threadId) = 0;
virtual bool CheckFileAccessDisabled(AZStd::string_view name, const char* mode) = 0;
virtual void SetRenderThreadId(AZStd::thread_id renderThreadId) = 0;
// gets the current pak priority
virtual ArchiveLocationPriority GetPakPriority() const = 0;
@@ -431,21 +302,6 @@ namespace AZ::IO
using LevelPackCloseEvent = AZ::Event<AZStd::string_view>;
virtual auto GetLevelPackCloseEvent()->LevelPackCloseEvent* = 0;
// Type-safe endian conversion read.
template<class T>
size_t FRead(T* data, size_t elems, AZ::IO::HandleType fileHandle, bool bSwapEndian = false)
{
size_t count = FReadRaw(data, sizeof(T), elems, fileHandle);
SwapEndian(data, count, bSwapEndian);
return count;
}
// Type-independent Write.
template<class T>
void FWrite(T* data, size_t elems, AZ::IO::HandleType fileHandle)
{
FWrite((void*)data, sizeof(T), elems, fileHandle);
}
inline static constexpr IArchive::SignedFileSize FILE_NOT_PRESENT = -1;
};
@@ -9,9 +9,9 @@
#pragma once
#include <AzCore/IO/Path/Path_fwd.h>
#include <AzCore/Math/Crc.h>
#include <AzCore/std/smart_ptr/intrusive_base.h>
#include <AzCore/std/string/string_view.h>
#include <AzFramework/Archive/Codec.h>
namespace AZ::IO
@@ -71,28 +71,10 @@ namespace AZ::IO
// multiple times
FLAGS_DONT_COMPACT = 1 << 5,
// flag is set when complete pak has been loaded into memory
FLAGS_IN_MEMORY = 1 << 6,
FLAGS_IN_MEMORY_CPU = 1 << 7,
FLAGS_IN_MEMORY_MASK = FLAGS_IN_MEMORY | FLAGS_IN_MEMORY_CPU,
// Store all file names as crc32 in a flat directory structure.
FLAGS_FILENAMES_AS_CRC32 = 1 << 8,
// flag is set when pak is stored on HDD
FLAGS_ON_HDD = 1 << 9,
//Override pak - paks opened with this flag go at the end of the list and contents will be found before other paks
//Used for patching
FLAGS_OVERRIDE_PAK = 1 << 10,
// Disable a pak file without unloading it, this flag is used in combination with patches and multiplayer
// to ensure that specific paks stay in the position(to keep the same priority) but beeing disabled
// to ensure that specific paks stay in the position(to keep the same priority) but being disabled
// when running multiplayer
FLAGS_DISABLE_PAK = 1 << 11,
// flag is set when pak is inside another pak
FLAGS_INSIDE_PAK = 1 << 12,
};
using Handle = void*;
@@ -122,7 +104,7 @@ namespace AZ::IO
virtual int StartContinuousFileUpdate(AZStd::string_view szRelativePath, uint64_t nSize) = 0;
// Summary:
// Adds a new file to the zip or update an existing's segment if it is not compressed - just stored
// Adds a new file to the zip or update an existing segment if it is not compressed - just stored
// adds a directory (creates several nested directories if needed)
// ( name might be misleading as if nOverwriteSeekPos is used the update is not continuous )
// Arguments:
@@ -164,7 +146,7 @@ namespace AZ::IO
// Summary:
// Get the full path to the archive file.
virtual const char* GetFullPath() const = 0;
virtual AZ::IO::PathView GetFullPath() const = 0;
// Summary:
// Get the flags of this object.
@@ -174,7 +174,7 @@ namespace AZ::IO
return m_pCache->ReadFile(reinterpret_cast<ZipDir::FileEntry*>(fileHandle), nullptr, pBuffer);
}
const char* NestedArchive::GetFullPath() const
AZ::IO::PathView NestedArchive::GetFullPath() const
{
return m_pCache->GetFilePath();
}
@@ -193,19 +193,9 @@ namespace AZ::IO
if (nFlagsToSet & FLAGS_RELATIVE_PATHS_ONLY)
{
m_nFlags |= FLAGS_RELATIVE_PATHS_ONLY;
}
if (nFlagsToSet & FLAGS_ON_HDD)
{
m_nFlags |= FLAGS_ON_HDD;
}
if (nFlagsToSet & FLAGS_RELATIVE_PATHS_ONLY ||
nFlagsToSet & FLAGS_ON_HDD)
{
// we don't support changing of any other flags
return true;
}
return false;
}
@@ -252,20 +242,12 @@ namespace AZ::IO
return AZ::IO::FixedMaxPathString{ szRelativePath };
}
if ((szRelativePath.size() > 1 && szRelativePath[1] == ':') || (m_nFlags & FLAGS_ABSOLUTE_PATHS))
if ((m_nFlags & FLAGS_ABSOLUTE_PATHS) == FLAGS_ABSOLUTE_PATHS)
{
// make the normalized full path and try to match it against the binding root of this object
auto resolvedPath = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(szRelativePath);
// Make sure the resolve path is longer than the bind root and that it starts with the bind root
if (!resolvedPath || resolvedPath->Native().size() <= m_strBindRoot.size() || azstrnicmp(resolvedPath->c_str(), m_strBindRoot.c_str(), m_strBindRoot.size()) != 0)
{
return {};
}
// Remove the bind root prefix from the resolved path
resolvedPath->Native().erase(0, m_strBindRoot.size() + 1);
return resolvedPath->Native();
AZ::IO::FixedMaxPath resolvedPath;
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(resolvedPath, szRelativePath);
return resolvedPath.LexicallyProximate(m_strBindRoot).Native();
}
return AZ::IO::FixedMaxPathString{ szRelativePath };
@@ -19,15 +19,15 @@ namespace AZ::IO
{
bool operator()(const INestedArchive* left, const INestedArchive* right) const
{
return azstricmp(left->GetFullPath(), right->GetFullPath()) < 0;
return left->GetFullPath() < right->GetFullPath();
}
bool operator()(AZStd::string_view left, const INestedArchive* right) const
{
return azstrnicmp(left.data(), right->GetFullPath(), left.size()) < 0;
return AZ::IO::PathView(left) < right->GetFullPath();
}
bool operator()(const INestedArchive* left, AZStd::string_view right) const
{
return azstrnicmp(left->GetFullPath(), right.data(), right.size()) < 0;
return left->GetFullPath() < AZ::IO::PathView(right);
}
};
@@ -40,7 +40,7 @@ namespace AZ::IO
NestedArchive(IArchive* pArchive, AZStd::string_view strBindRoot, ZipDir::CachePtr pCache, uint32_t nFlags = 0);
~NestedArchive() override;
auto GetRootFolderHandle() -> Handle;
auto GetRootFolderHandle() -> Handle override;
// Adds a new file to the zip or update an existing one
// adds a directory (creates several nested directories if needed)
@@ -66,26 +66,26 @@ namespace AZ::IO
int RemoveDir(AZStd::string_view szRelativePath) override;
// deletes all files from the archive
int RemoveAll();
int RemoveAll() override;
// finds the file; you don't have to close the returned handle
Handle FindFile(AZStd::string_view szRelativePath);
Handle FindFile(AZStd::string_view szRelativePath) override;
// returns the size of the file (unpacked) by the handle
uint64_t GetFileSize(Handle fileHandle);
uint64_t GetFileSize(Handle fileHandle) override;
// reads the file into the preallocated buffer (must be at least the size of GetFileSize())
int ReadFile(Handle fileHandle, void* pBuffer);
int ReadFile(Handle fileHandle, void* pBuffer) override;
// returns the full path to the archive file
const char* GetFullPath() const;
AZ::IO::PathView GetFullPath() const override;
ZipDir::Cache* GetCache();
uint32_t GetFlags() const;
bool SetFlags(uint32_t nFlagsToSet);
bool ResetFlags(uint32_t nFlagsToReset);
uint32_t GetFlags() const override;
bool SetFlags(uint32_t nFlagsToSet) override;
bool ResetFlags(uint32_t nFlagsToReset) override;
bool SetPackAccessible(bool bAccessible);
bool SetPackAccessible(bool bAccessible) override;
protected:
// returns the pointer to the relative file path to be passed
@@ -95,7 +95,7 @@ namespace AZ::IO
ZipDir::CachePtr m_pCache;
// the binding root may be empty string - in this case, the absolute path binding won't work
AZStd::string m_strBindRoot;
AZ::IO::Path m_strBindRoot;
IArchive* m_archive{};
uint32_t m_nFlags{};
};
@@ -9,7 +9,6 @@
#include <AzCore/Console/Console.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/std/string/conversions.h>
#include <AzFramework/Archive/ZipFileFormat.h>
@@ -104,24 +103,21 @@ namespace AZ::IO::ZipDir
: m_pCache(pCache)
, m_bCommitted(false)
{
AZ::IO::PathString normalizedPath{ szRelativePath };
AZ::StringFunc::Path::Normalize(normalizedPath);
AZStd::to_lower(AZStd::begin(normalizedPath), AZStd::end(normalizedPath));
// Update the cache string pool with the relative path to the file
auto pathIt = m_pCache->m_relativePathPool.emplace(normalizedPath);
auto pathIt = m_pCache->m_relativePathPool.emplace(AZ::IO::PathView(szRelativePath).LexicallyNormal());
m_szRelativePath = *pathIt.first;
// this is the name of the directory - create it or find it
m_pFileEntry = m_pCache->GetRoot()->Add(m_szRelativePath);
m_pFileEntry = m_pCache->GetRoot()->Add(m_szRelativePath.Native());
if (m_pFileEntry && az_archive_zip_directory_cache_verbosity)
{
AZ_TracePrintf("Archive", R"(File "%s" has been added to archive at root "%s")", normalizedPath.c_str(), pCache->GetFilePath());
AZ_TracePrintf("Archive", R"(File "%s" has been added to archive at root "%s")", pathIt.first->c_str(), pCache->GetFilePath());
}
}
~FileEntryTransactionAdd()
{
if (m_pFileEntry && !m_bCommitted)
{
m_pCache->RemoveFile(m_szRelativePath);
m_pCache->RemoveFile(m_szRelativePath.Native());
m_pCache->m_relativePathPool.erase(m_szRelativePath);
}
}
@@ -131,11 +127,11 @@ namespace AZ::IO::ZipDir
}
AZStd::string_view GetRelativePath() const
{
return m_szRelativePath;
return m_szRelativePath.Native();
}
private:
Cache* m_pCache;
AZStd::string_view m_szRelativePath;
AZ::IO::PathView m_szRelativePath;
FileEntry* m_pFileEntry;
bool m_bCommitted;
};
@@ -587,34 +583,27 @@ namespace AZ::IO::ZipDir
// deletes the file from the archive
ErrorEnum Cache::RemoveFile(AZStd::string_view szRelativePathSrc)
{
// Normalize and lower case the relative path
AZ::IO::PathString szRelativePath{ szRelativePathSrc };
AZ::StringFunc::Path::Normalize(szRelativePath);
AZStd::to_lower(AZStd::begin(szRelativePath), AZStd::end(szRelativePath));
AZStd::string_view normalizedRelativePath = szRelativePath;
// find the last slash in the path
size_t slashOffset = normalizedRelativePath.find_last_of(AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR);
AZ::IO::PathView szRelativePath{ szRelativePathSrc };
AZStd::string_view fileName; // the name of the file to delete
FileEntryTree* pDir; // the dir from which the subdir will be deleted
if (slashOffset != AZStd::string_view::npos)
if (szRelativePath.HasParentPath())
{
FindDir fd(GetRoot());
// the directory to remove
pDir = fd.FindExact(normalizedRelativePath.substr(0, slashOffset));
pDir = fd.FindExact(szRelativePath.ParentPath());
if (!pDir)
{
return ZD_ERROR_DIR_NOT_FOUND;// there is no such directory
}
fileName = normalizedRelativePath.substr(slashOffset + 1);
fileName = szRelativePath.Filename().Native();
}
else
{
pDir = GetRoot();
fileName = normalizedRelativePath;
fileName = szRelativePath.Native();
}
ErrorEnum e = pDir->RemoveFile(fileName);
@@ -625,7 +614,7 @@ namespace AZ::IO::ZipDir
if (az_archive_zip_directory_cache_verbosity)
{
AZ_TracePrintf("Archive", R"(File "%.*s" has been remove from archive at root "%s")",
aznumeric_cast<int>(fileName.size()), fileName.data(), GetFilePath());
AZ_STRING_ARG(szRelativePath.Native()), GetFilePath());
}
}
return e;
@@ -635,45 +624,38 @@ namespace AZ::IO::ZipDir
// deletes the directory, with all its descendants (files and subdirs)
ErrorEnum Cache::RemoveDir(AZStd::string_view szRelativePathSrc)
{
// Normalize and lower case the relative path
AZ::IO::PathString szRelativePath{ szRelativePathSrc };
AZ::StringFunc::Path::Normalize(szRelativePath);
AZStd::to_lower(AZStd::begin(szRelativePath), AZStd::end(szRelativePath));
AZStd::string_view normalizedRelativePath = szRelativePath;
// find the last slash in the path
size_t slashOffset = normalizedRelativePath.find_last_of(AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR);
AZ::IO::PathView szRelativePath{ szRelativePathSrc };
AZStd::string_view dirName; // the name of the dir to delete
FileEntryTree* pDir; // the dir from which the subdir will be deleted
if (slashOffset != AZStd::string_view::npos)
if (szRelativePath.HasParentPath())
{
FindDir fd(GetRoot());
// the directory to remove
pDir = fd.FindExact(normalizedRelativePath.substr(0, slashOffset));
pDir = fd.FindExact(szRelativePath.ParentPath());
if (!pDir)
{
return ZD_ERROR_DIR_NOT_FOUND;// there is no such directory
}
dirName = normalizedRelativePath.substr(slashOffset + 1);
dirName = szRelativePath.Filename().Native();
}
else
{
pDir = GetRoot();
dirName = normalizedRelativePath;
dirName = szRelativePath.Native();
}
ErrorEnum e = pDir->RemoveDir(normalizedRelativePath);
ErrorEnum e = pDir->RemoveDir(dirName);
if (e == ZD_ERROR_SUCCESS)
{
m_nFlags |= FLAGS_UNCOMPACTED | FLAGS_CDR_DIRTY;
if (az_archive_zip_directory_cache_verbosity)
{
AZ_TracePrintf("Archive", R"(File "%.*s" has been remove from archive at root "%s")",
aznumeric_cast<int>(normalizedRelativePath.size()), normalizedRelativePath.data(), GetFilePath());
AZ_TracePrintf("Archive", R"(Directory "%.*s" has been remove from archive at root "%s")",
AZ_STRING_ARG(szRelativePath.Native()), GetFilePath());
}
}
return e;
@@ -769,9 +751,7 @@ namespace AZ::IO::ZipDir
// finds the file by exact path
FileEntry* Cache::FindFile(AZStd::string_view szPathSrc, [[maybe_unused]] bool bFullInfo)
{
AZ::IO::PathString szPath{ szPathSrc };
AZ::StringFunc::Path::Normalize(szPath);
AZStd::to_lower(AZStd::begin(szPath), AZStd::end(szPath));
AZ::IO::PathView szPath{ szPathSrc };
ZipDir::FindFile fd(GetRoot());
FileEntry* fileEntry = fd.FindExact(szPath);
@@ -779,19 +759,13 @@ namespace AZ::IO::ZipDir
{
if (az_archive_zip_directory_cache_verbosity)
{
AZ_TracePrintf("Archive", "FindExact failed to find file %s at root %s", szPath.c_str(), GetFilePath());
AZ_TracePrintf("Archive", "FindExact failed to find file %.*s at root %s", AZ_STRING_ARG(szPath.Native()), GetFilePath());
}
return {};
}
return fileEntry;
}
// returns the size of memory occupied by the instance referred to by this cache
size_t Cache::GetSize() const
{
return sizeof(*this) + m_strFilePath.capacity() + m_treeDir.GetSize() - sizeof(m_treeDir);
}
// refreshes information about the given file entry into this file entry
ErrorEnum Cache::Refresh(FileEntryBase* pFileEntry)
{
@@ -800,7 +774,7 @@ namespace AZ::IO::ZipDir
return ZD_ERROR_INVALID_CALL;
}
if (pFileEntry->nFileDataOffset != pFileEntry->INVALID_DATA_OFFSET)
if (pFileEntry->nFileDataOffset != FileEntryBase::INVALID_DATA_OFFSET)
{
return ZD_ERROR_SUCCESS; // the data offset has been successfully read..
}

Some files were not shown because too many files have changed in this diff Show More