More red code (#732)
Remove: - Code/CryEngine/CryCommon/Platform - Some unused Code/CryEngine/CryCommon/Mock files - Code/Tools/CryXML and almost all of Code/Tools/CryCommonTools - Code/Tools/TestBed/ResourceCompilerImage - Tools/DeepBandwidthToExcel - Various .p4ignore files
This commit is contained in:
@@ -1,6 +0,0 @@
|
||||
#Ignore these directories
|
||||
SDKs
|
||||
|
||||
#ColinB (8/26)- I know there are depot files that this will ignore... But these files should not be
|
||||
#here, they should all be in 3rdParty... so we will ignore them until I can move them, it should
|
||||
#be OK for now because they shouldn't change at all anyway.
|
||||
@@ -9,23 +9,15 @@
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME})
|
||||
ly_get_pal_tool_dirs(pal_tool_dirs ${CMAKE_CURRENT_LIST_DIR}/Platform)
|
||||
|
||||
ly_add_target(
|
||||
NAME CryCommon STATIC
|
||||
NAMESPACE Legacy
|
||||
FILES_CMAKE
|
||||
crycommon_files.cmake
|
||||
${pal_dir}/crycommon_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
|
||||
PLATFORM_INCLUDE_FILES
|
||||
${pal_dir}/crycommon_${PAL_PLATFORM_NAME_LOWERCASE}.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PUBLIC
|
||||
. # Lots of code without CryCommon/
|
||||
.. # Dangerous since exports CryEngine's path (client code can do CrySystem/ without depending on that target)
|
||||
${pal_dir}
|
||||
${pal_tool_dirs}
|
||||
BUILD_DEPENDENCIES
|
||||
PUBLIC
|
||||
AZ::AzCore
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include <CryMemoryManager.h>
|
||||
|
||||
class MemoryManagerMock
|
||||
: public IMemoryManager
|
||||
{
|
||||
public:
|
||||
MOCK_METHOD1(GetProcessMemInfo,
|
||||
bool(SProcessMemInfo& minfo));
|
||||
MOCK_METHOD3(TraceDefineHeap,
|
||||
HeapHandle(const char* heapName, size_t size, const void* pBase));
|
||||
MOCK_METHOD6(TraceHeapAlloc,
|
||||
void(HeapHandle heap, void* mem, size_t size, size_t blockSize, const char* sUsage, const char* sNameHint));
|
||||
MOCK_METHOD3(TraceHeapFree,
|
||||
void(HeapHandle heap, void* mem, size_t blockSize));
|
||||
MOCK_METHOD1(TraceHeapSetColor,
|
||||
void(uint32 color));
|
||||
MOCK_METHOD0(TraceHeapGetColor,
|
||||
uint32());
|
||||
MOCK_METHOD1(TraceHeapSetLabel,
|
||||
void(const char* sLabel));
|
||||
MOCK_METHOD1(CreateCustomMemoryHeapInstance,
|
||||
ICustomMemoryHeap* const (EAllocPolicy const eAllocPolicy));
|
||||
MOCK_METHOD3(CreateGeneralExpandingMemoryHeap,
|
||||
IGeneralMemoryHeap* (size_t upperLimit, size_t reserveSize, const char* sUsage));
|
||||
MOCK_METHOD3(CreateGeneralMemoryHeap,
|
||||
IGeneralMemoryHeap* (void* base, size_t sz, const char* sUsage));
|
||||
MOCK_METHOD2(ReserveAddressRange,
|
||||
IMemoryAddressRange* (size_t capacity, const char* sName));
|
||||
MOCK_METHOD2(CreatePageMappingHeap,
|
||||
IPageMappingHeap* (size_t addressSpace, const char* sName));
|
||||
};
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct NetworkMock : public INetwork
|
||||
{
|
||||
NetworkMock() : m_gridMate(nullptr)
|
||||
{
|
||||
}
|
||||
GridMate::IGridMate* m_gridMate;
|
||||
|
||||
void Release() override {}
|
||||
void GetMemoryStatistics([[maybe_unused]] ICrySizer* pSizer) override {}
|
||||
void GetBandwidthStatistics([[maybe_unused]] SBandwidthStats* const pStats) override {}
|
||||
void GetPerformanceStatistics([[maybe_unused]] SNetworkPerformance* pSizer) override {}
|
||||
void GetProfilingStatistics([[maybe_unused]] SNetworkProfilingStats* const pStats) override {}
|
||||
void SyncWithGame([[maybe_unused]] ENetworkGameSync syncType) override {}
|
||||
const char* GetHostName() override { return "testhostname"; }
|
||||
GridMate::IGridMate* GetGridMate() override
|
||||
{
|
||||
return m_gridMate;
|
||||
}
|
||||
ChannelId GetChannelIdForSessionMember([[maybe_unused]] GridMate::GridMember* member) const override { return ChannelId(); }
|
||||
ChannelId GetServerChannelId() const override { return ChannelId(); }
|
||||
ChannelId GetLocalChannelId() const override { return ChannelId(); }
|
||||
CTimeValue GetSessionTime() override { return CTimeValue(); }
|
||||
void ChangedAspects([[maybe_unused]] EntityId id, [[maybe_unused]] NetworkAspectType aspectBits) override {}
|
||||
void SetDelegatableAspectMask([[maybe_unused]] NetworkAspectType aspectBits) override {}
|
||||
void SetObjectDelegatedAspectMask([[maybe_unused]] EntityId entityId, [[maybe_unused]] NetworkAspectType aspects, [[maybe_unused]] bool set) override {}
|
||||
void DelegateAuthorityToClient([[maybe_unused]] EntityId entityId, [[maybe_unused]] ChannelId clientChannelId) override {}
|
||||
void InvokeActorRMI([[maybe_unused]] EntityId entityId, [[maybe_unused]] uint8 actorExtensionId, [[maybe_unused]] ChannelId targetChannelFilter, [[maybe_unused]] IActorRMIRep& rep) override {}
|
||||
void InvokeScriptRMI([[maybe_unused]] ISerializable* serializable, [[maybe_unused]] bool isServerRMI, [[maybe_unused]] ChannelId toChannelId = kInvalidChannelId, [[maybe_unused]] ChannelId avoidChannelId = kInvalidChannelId) override {}
|
||||
void RegisterActorRMI([[maybe_unused]] IActorRMIRep* rep) override {}
|
||||
void UnregisterActorRMI([[maybe_unused]] IActorRMIRep* rep) override {}
|
||||
EntityId LocalEntityIdToServerEntityId([[maybe_unused]] EntityId localId) const override { return EntityId(); }
|
||||
EntityId ServerEntityIdToLocalEntityId([[maybe_unused]] EntityId serverId, [[maybe_unused]] bool allowForcedEstablishment = false) const override { return EntityId(); }
|
||||
};
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzTest/AzTest.h>
|
||||
|
||||
#include <CGFContent.h>
|
||||
|
||||
class MockIAssetWriter
|
||||
: public IAssetWriter
|
||||
{
|
||||
public:
|
||||
~MockIAssetWriter() override = default;
|
||||
MOCK_METHOD1(WriteCGF,
|
||||
bool(CContentCGF* content));
|
||||
MOCK_METHOD2(WriteCHR,
|
||||
bool(CContentCGF* content, IConvertContext* convertContext));
|
||||
MOCK_METHOD3(WriteSKIN,
|
||||
bool(CContentCGF* content, IConvertContext* convertContext, bool exportMorphTargets));
|
||||
};
|
||||
@@ -1,11 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../../WinBase.cpp
|
||||
)
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
)
|
||||
@@ -1,11 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
)
|
||||
@@ -1,11 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../../WinBase.cpp
|
||||
)
|
||||
@@ -1,11 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../../WinBase.cpp
|
||||
)
|
||||
@@ -1,11 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
)
|
||||
@@ -1,13 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
)
|
||||
@@ -1,11 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../../WinBase.cpp
|
||||
)
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
class Viewport2D
|
||||
{
|
||||
public:
|
||||
int m_topLeftX = 0;
|
||||
int m_topLeftY = 0;
|
||||
int m_width = 0;
|
||||
int m_height = 0;
|
||||
|
||||
Viewport2D() = default;
|
||||
Viewport2D(const Viewport2D&) = default;
|
||||
Viewport2D& operator=(const Viewport2D&) = default;
|
||||
|
||||
Viewport2D(int topLeftX, int topLeftY, int width, int height)
|
||||
: m_topLeftX(topLeftX)
|
||||
, m_topLeftY(topLeftY)
|
||||
, m_width(width)
|
||||
, m_height(height)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// External height map data requests
|
||||
class HeightmapDataRequestInfo
|
||||
{
|
||||
public:
|
||||
HeightmapDataRequestInfo() = default;
|
||||
HeightmapDataRequestInfo(const HeightmapDataRequestInfo& rhs) = default;
|
||||
HeightmapDataRequestInfo& operator=(const HeightmapDataRequestInfo& rhs) = default;
|
||||
|
||||
HeightmapDataRequestInfo(int viewportTopLeftX, int viewportTopLeftY, int viewportWidth, int viewportHeight, float metersPerPixel, AZ::Vector2 worldMin, AZ::Vector2 worldMax)
|
||||
: m_viewport(viewportTopLeftX, viewportTopLeftY, viewportWidth, viewportHeight)
|
||||
, m_metersPerPixel(metersPerPixel)
|
||||
, m_worldMin(worldMin)
|
||||
, m_worldMax(worldMax)
|
||||
{
|
||||
}
|
||||
|
||||
float GetMetersPerPixel() const
|
||||
{
|
||||
return m_metersPerPixel;
|
||||
}
|
||||
|
||||
AZ::Vector2 GetWorldMin() const
|
||||
{
|
||||
return m_worldMin;
|
||||
}
|
||||
|
||||
AZ::Vector2 GetWorldMax() const
|
||||
{
|
||||
return m_worldMax;
|
||||
}
|
||||
|
||||
AZ::Vector2 GetWorldWidth() const
|
||||
{
|
||||
return (m_worldMax - m_worldMin);
|
||||
}
|
||||
|
||||
Viewport2D GetViewport() const
|
||||
{
|
||||
return m_viewport;
|
||||
}
|
||||
|
||||
private:
|
||||
Viewport2D m_viewport;
|
||||
AZ::Vector2 m_worldMin = AZ::Vector2(0.0f, 0.0f);
|
||||
AZ::Vector2 m_worldMax = AZ::Vector2(0.0f, 0.0f);
|
||||
float m_metersPerPixel = 1.0f;
|
||||
};
|
||||
|
||||
class HeightmapDataNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void OnTerrainHeightDataChanged(const AZ::Aabb& dirtyRegion) = 0;
|
||||
};
|
||||
using HeightmapDataNotificationBus = AZ::EBus<HeightmapDataNotifications>;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
|
||||
class CShader;
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
class TerrainDataRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual float GetHeightSynchronous(float x, float y) = 0;
|
||||
virtual AZ::Vector3 GetNormalSynchronous(float x, float y) = 0;
|
||||
|
||||
virtual CShader* GetTerrainHeightGeneratorShader() const = 0;
|
||||
virtual CShader* GetTerrainMaterialCompositingShader() const = 0;
|
||||
};
|
||||
using TerrainDataRequestBus = AZ::EBus<TerrainDataRequests>;
|
||||
|
||||
class TerrainShaderRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void RefreshShader(const AZStd::string_view name, CShader* shader) = 0;
|
||||
virtual void ReleaseShader(CShader* shader) const = 0;
|
||||
};
|
||||
using TerrainShaderRequestBus = AZ::EBus<TerrainShaderRequests>;
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Math/Vector2.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
#include <AzCore/std/smart_ptr/shared_ptr.h>
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
#include "HeightmapDataBus.h"
|
||||
|
||||
class CShader;
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
// This interface defines how the renderer can access the terrain system to set up state and gather information before rendering height maps
|
||||
class TerrainProviderRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//! allows multiple threads to call
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// world properties
|
||||
virtual AZ::Vector3 GetWorldSize() = 0;
|
||||
virtual AZ::Vector3 GetRegionSize() = 0;
|
||||
virtual AZ::Vector3 GetWorldOrigin() = 0;
|
||||
virtual AZ::Vector2 GetHeightRange() = 0;
|
||||
|
||||
// utility
|
||||
virtual void GetRegionIndex(const AZ::Vector2& worldMin, const AZ::Vector2& worldMax, int& regionIndexX, int& regionIndexY) = 0;
|
||||
|
||||
virtual float GetHeightAtIndexedPosition([[maybe_unused]] int ix, [[maybe_unused]] int iy) { return 64.0f; }
|
||||
virtual float GetHeightAtWorldPosition([[maybe_unused]] float fx, [[maybe_unused]] float fy) { return 64.0f; }
|
||||
virtual unsigned char GetSurfaceTypeAtIndexedPosition([[maybe_unused]] int ix, [[maybe_unused]] int iy) { return 0; }
|
||||
};
|
||||
using TerrainProviderRequestBus = AZ::EBus<TerrainProviderRequests>;
|
||||
|
||||
// This class exists for the terrain system to inject data into the renderer for generating the GPU-side terrain height map
|
||||
struct CRETerrainContext
|
||||
{
|
||||
// Tract map
|
||||
virtual void OnTractVersionUpdate() = 0;
|
||||
|
||||
CShader* m_currentShader = nullptr;
|
||||
};
|
||||
|
||||
class TerrainProviderNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//! allows multiple threads to call
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// interface to be implemented by the game, invoked by the terrain render element
|
||||
|
||||
// pull settings from the world cache, so the next accessors are accurate
|
||||
virtual void SynchronizeSettings(CRETerrainContext* context) = 0;
|
||||
};
|
||||
using TerrainProviderNotificationBus = AZ::EBus<TerrainProviderNotifications>;
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
class TerrainRendererRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! allows multiple threads to call
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
|
||||
// Query state of the terrain renderer
|
||||
// Returns true once the terrain renderer has fulfilled most data requests and is ready for rendering
|
||||
virtual bool IsReady() = 0;
|
||||
};
|
||||
using TerrainRendererRequestBus = AZ::EBus<TerrainRendererRequests>;
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/containers/fixed_vector.h>
|
||||
|
||||
struct IMaterial;
|
||||
class ITexture;
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
struct MacroMaterial
|
||||
{
|
||||
// Textures
|
||||
_smart_ptr<ITexture> m_macroColorMap = nullptr;
|
||||
_smart_ptr<ITexture> m_macroGlossMap = nullptr;
|
||||
_smart_ptr<ITexture> m_macroNormalMap = nullptr;
|
||||
|
||||
// Material Params
|
||||
AZ::Color m_macroColorMapColor;
|
||||
float m_macroGlossMapScale = 1.0f;
|
||||
float m_macroNormalMapScale = 1.0f;
|
||||
float m_macroSpecReflectance = 0.03f;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
m_macroColorMap = nullptr;
|
||||
m_macroGlossMap = nullptr;
|
||||
m_macroNormalMap = nullptr;
|
||||
|
||||
m_macroColorMapColor = AZ::Color(1.0f);
|
||||
m_macroGlossMapScale = 1.0f;
|
||||
m_macroNormalMapScale = 1.0f;
|
||||
m_macroSpecReflectance = 0.03f;
|
||||
}
|
||||
};
|
||||
|
||||
struct TerrainMaterialLayer
|
||||
{
|
||||
_smart_ptr<IMaterial> m_material = nullptr;
|
||||
_smart_ptr<ITexture> m_splatTexture = nullptr;
|
||||
|
||||
TerrainMaterialLayer(_smart_ptr<IMaterial> material, _smart_ptr<ITexture> splatTexture)
|
||||
: m_material(material)
|
||||
, m_splatTexture(splatTexture)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct RegionMaterials
|
||||
{
|
||||
MacroMaterial m_macroMaterial;
|
||||
|
||||
AZStd::vector<TerrainMaterialLayer> m_materialLayers;
|
||||
_smart_ptr<IMaterial> m_defaultMaterial = nullptr;
|
||||
|
||||
RegionMaterials& operator=(const RegionMaterials& rhs) = default;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
m_materialLayers.clear();
|
||||
m_defaultMaterial = nullptr;
|
||||
m_macroMaterial.Clear();
|
||||
}
|
||||
};
|
||||
|
||||
const AZ::u32 kMaxRegionsPerTerrainMaterialRequest = 16;
|
||||
typedef AZStd::pair<int, int> RegionIndex;
|
||||
typedef AZStd::fixed_vector<RegionIndex, kMaxRegionsPerTerrainMaterialRequest> RegionIndexVector;
|
||||
typedef AZStd::fixed_vector<RegionMaterials, kMaxRegionsPerTerrainMaterialRequest> RegionMaterialVector;
|
||||
|
||||
enum class RequestResult
|
||||
{
|
||||
NoAssetsForRegion,
|
||||
Loading,
|
||||
Success
|
||||
};
|
||||
|
||||
class WorldMaterialRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! allows multiple threads to call
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
|
||||
virtual void LoadWorld(const AZStd::string& worldName, int regionSize) = 0;
|
||||
|
||||
virtual RequestResult RequestRegionMaterials(const RegionIndexVector& regions, RegionMaterialVector& outRegionMaterials) = 0;
|
||||
|
||||
// Parameters:
|
||||
// int tileX, tileY : Region tile indices
|
||||
// Returns:
|
||||
// bool : If true, region material data is loaded and exists. outMacroMaterial will be modified with the respective macro material data
|
||||
// If false, no region material data has been loaded or exists for the given tile (may still have invalid material layers).
|
||||
virtual RequestResult GetMacroMaterial(int tileX, int tileY, MacroMaterial& outMacroMaterial) = 0;
|
||||
|
||||
virtual void GetTerrainPOMParameters(float& pomHeightBias, float& pomDisplacement, float& selfShadowStrength) = 0;
|
||||
|
||||
//Get the surface type at a given position. If not loaded yet, returns "loadingMaterial".
|
||||
virtual AZStd::string_view GetSurfaceTypeAtPosition(AZ::Vector2 position) = 0;
|
||||
};
|
||||
using WorldMaterialRequestBus = AZ::EBus<WorldMaterialRequests>;
|
||||
} // namespace Terrain
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
// Description : Linux/Mac port support for Win32API calls
|
||||
#if !defined(WIN32)
|
||||
|
||||
#include "platform.h" // Note: This should be first to get consistent debugging definitions
|
||||
|
||||
@@ -1667,3 +1668,5 @@ __finddata64_t::~__finddata64_t()
|
||||
}
|
||||
}
|
||||
#endif //defined(APPLE) || defined(LINUX)
|
||||
|
||||
#endif // !defined(WIN32)
|
||||
|
||||
@@ -249,7 +249,6 @@ set(FILES
|
||||
platform_impl.cpp
|
||||
Win32specific.h
|
||||
Win64specific.h
|
||||
stl/STLAlignedAlloc.h
|
||||
LyShine/IDraw2d.h
|
||||
LyShine/ILyShine.h
|
||||
LyShine/ISprite.h
|
||||
@@ -341,11 +340,7 @@ set(FILES
|
||||
Maestro/Types/AssetBlendKey.h
|
||||
Maestro/Types/AssetBlends.h
|
||||
Maestro/Types/SequenceType.h
|
||||
Terrain/Bus/WorldMaterialRequestsBus.h
|
||||
Terrain/Bus/TerrainBus.h
|
||||
Terrain/Bus/TerrainRendererBus.h
|
||||
Terrain/Bus/HeightmapDataBus.h
|
||||
Terrain/Bus/TerrainProviderBus.h
|
||||
StaticInstance.h
|
||||
Pak/CryPakUtils.h
|
||||
WinBase.cpp
|
||||
)
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
)
|
||||
@@ -14,12 +14,10 @@ set(FILES
|
||||
Mocks/IConsoleMock.h
|
||||
Mocks/ICryPakMock.h
|
||||
Mocks/ILogMock.h
|
||||
Mocks/IMemoryManagerMock.h
|
||||
Mocks/ISystemMock.h
|
||||
Mocks/ITimerMock.h
|
||||
Mocks/ICVarMock.h
|
||||
Mocks/IRendererMock.h
|
||||
Mocks/ITextureMock.h
|
||||
Mocks/IRemoteConsoleMock.h
|
||||
Mocks/MockCGFContent.h
|
||||
)
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
// Description : Implements an aligned allocator for STL
|
||||
// based on the Mallocator (http://blogs.msdn.com/b/vcblog/archive/2008/08/28/the-mallocator.aspx)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // Required for size_t and ptrdiff_t and NULL
|
||||
|
||||
#include <AzCore/Memory/AllocatorBase.h>
|
||||
|
||||
namespace stl
|
||||
{
|
||||
template <size_t Alignment>
|
||||
class AlignedAllocator
|
||||
: public AZ::SimpleSchemaAllocator<AZ::ChildAllocatorSchema<AZ::LegacyAllocator>>
|
||||
{
|
||||
public:
|
||||
AZ_TYPE_INFO(AlignedAllocator, "{DF152D8A-36ED-4A2A-9FA6-734F212716C6}");
|
||||
using Base = AZ::SimpleSchemaAllocator<AZ::ChildAllocatorSchema<AZ::LegacyAllocator>>;
|
||||
using Descriptor = Base::Descriptor;
|
||||
using Schema = AZ::ChildAllocatorSchema<AZ::LegacyAllocator>;
|
||||
|
||||
AlignedAllocator()
|
||||
: Base("AlignedAllocator", "Legacy Cry Aligned Allocator")
|
||||
{
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return Base::Allocate(byteSize, Alignment, flags, name, fileName, lineNum, suppressStackRecord);
|
||||
}
|
||||
|
||||
void DeAllocate(pointer_type ptr, size_type byteSize, [[maybe_unused]] size_type alignment) override
|
||||
{
|
||||
return Base::DeAllocate(ptr, byteSize, Alignment);
|
||||
}
|
||||
|
||||
pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type /*newAlignment*/) override
|
||||
{
|
||||
return Base::ReAllocate(ptr, newSize, Alignment);
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t Alignment>
|
||||
using aligned_alloc = AZ::AZStdAlloc<AlignedAllocator<Alignment>>;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Defines aligned vector type
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, int AlignSize>
|
||||
class aligned_vector
|
||||
: public AZStd::vector<T, aligned_alloc<AlignSize> >
|
||||
{
|
||||
public:
|
||||
typedef aligned_alloc<AlignSize> MyAlloc;
|
||||
typedef AZStd::vector<T, MyAlloc> MySuperClass;
|
||||
typedef aligned_vector<T, AlignSize> MySelf;
|
||||
typedef size_t size_type;
|
||||
|
||||
aligned_vector() {}
|
||||
explicit aligned_vector(const MyAlloc& _Al)
|
||||
: MySuperClass(_Al) {}
|
||||
explicit aligned_vector(size_type _Count)
|
||||
: MySuperClass(_Count) {};
|
||||
aligned_vector(size_type _Count, const T& _Val)
|
||||
: MySuperClass(_Count, _Val) {}
|
||||
aligned_vector(size_type _Count, const T& _Val, const MyAlloc& _Al)
|
||||
: MySuperClass(_Count, _Val) {}
|
||||
aligned_vector(const MySelf& _Right)
|
||||
: MySuperClass(_Right) {};
|
||||
|
||||
|
||||
template<class _Iter>
|
||||
aligned_vector(_Iter _First, _Iter _Last)
|
||||
: MySuperClass(_First, _Last) {};
|
||||
|
||||
template<class _Iter>
|
||||
aligned_vector(_Iter _First, _Iter _Last, const MyAlloc& _Al)
|
||||
: MySuperClass(_First, _Last, _Al) {};
|
||||
};
|
||||
|
||||
template <class Vec>
|
||||
inline size_t size_of_aligned_vector(const Vec& c)
|
||||
{
|
||||
if (!c.empty())
|
||||
{
|
||||
// Not really correct as not taking alignment into the account
|
||||
return c.capacity() * sizeof(typename Vec::value_type);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} // namespace stl
|
||||
|
||||
// Specialize for the AlignedAllocator to provide one per module that does not use the
|
||||
// environment for its storage. Since this allocator just uses LegacyAllocator
|
||||
// to do the real work, it's fine if there is one of these per cry module
|
||||
namespace AZ
|
||||
{
|
||||
template <size_t Alignment>
|
||||
class AllocatorInstance<stl::AlignedAllocator<Alignment>> : public Internal::AllocatorInstanceBase<stl::AlignedAllocator<Alignment>, AllocatorStorage::ModuleStoragePolicy<stl::AlignedAllocator<Alignment>>>
|
||||
{
|
||||
};
|
||||
}
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "CrySystem_precompiled.h"
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <AzCore/Memory/AllocatorScope.h>
|
||||
#include <CryCommon/stl/STLAlignedAlloc.h>
|
||||
|
||||
TEST(StringTests, CUT_Strings)
|
||||
{
|
||||
@@ -424,21 +423,6 @@ TEST_F(CryPrimitives, CUT_FixedString)
|
||||
EXPECT_EQ("0123", str5);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Unit Testing of aligned_vector
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
TEST_F(CryPrimitives, CUT_AlignedVector)
|
||||
{
|
||||
stl::aligned_vector<int, 16> vec;
|
||||
|
||||
vec.push_back(1);
|
||||
vec.push_back(2);
|
||||
vec.push_back(3);
|
||||
|
||||
EXPECT_TRUE(vec.size() == 3);
|
||||
EXPECT_TRUE(((INT_PTR)(&vec[0]) % 16) == 0);
|
||||
}
|
||||
|
||||
TEST_F(CryPrimitives, CUT_DynArray)
|
||||
{
|
||||
LegacyDynArray<int> a;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
*.xml
|
||||
@@ -1 +0,0 @@
|
||||
*.xml
|
||||
@@ -1,5 +0,0 @@
|
||||
#Ignore these directories
|
||||
SDKs
|
||||
|
||||
#ignore these files
|
||||
*.user
|
||||
@@ -15,7 +15,6 @@ add_subdirectory(AWSNativeSDKInit)
|
||||
add_subdirectory(AzTestRunner)
|
||||
add_subdirectory(CrashHandler)
|
||||
add_subdirectory(CryCommonTools)
|
||||
add_subdirectory(CryXML)
|
||||
add_subdirectory(News)
|
||||
add_subdirectory(PythonBindingsExample)
|
||||
add_subdirectory(RemoteConsole)
|
||||
|
||||
@@ -13,44 +13,18 @@ if (NOT PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
return()
|
||||
endif()
|
||||
|
||||
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME})
|
||||
|
||||
ly_add_target(
|
||||
NAME CryCommonTools STATIC
|
||||
NAMESPACE Legacy
|
||||
FILES_CMAKE
|
||||
crycommontools_files.cmake
|
||||
${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PUBLIC
|
||||
.
|
||||
${pal_dir}
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::lz4
|
||||
3rdParty::zlib
|
||||
3rdParty::zstd
|
||||
AZ::AzCore
|
||||
PUBLIC
|
||||
Legacy::CryCommon
|
||||
AZ::AzFramework
|
||||
)
|
||||
|
||||
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
ly_add_target(
|
||||
NAME CryCommonTools.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
|
||||
NAMESPACE Legacy
|
||||
FILES_CMAKE
|
||||
crycommontools_tests_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PUBLIC
|
||||
UnitTests
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
Legacy::CryCommonTools
|
||||
AZ::AzTest
|
||||
)
|
||||
ly_add_googletest(
|
||||
NAME Legacy::CryCommonTools.Tests
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_COLLADASHARED_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_COLLADASHARED_H
|
||||
#pragma once
|
||||
|
||||
static const char* g_LumberyardExportNodeTag = "LumberyardExportNode";
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_COLLADASHARED_H
|
||||
@@ -1,514 +0,0 @@
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
// Taken from http://tog.acm.org/GraphicsGems/gemsiv/polar_decomp/Decompose.c
|
||||
|
||||
/**** Decompose.c ****/
|
||||
/* Ken Shoemake, 1993 */
|
||||
#include <math.h>
|
||||
#include "Decompose.h"
|
||||
|
||||
#pragma warning(disable:4244) // conversion from 'double' to 'float', possible loss of data
|
||||
#pragma warning(disable:4305) // 'initializing' : truncation from 'double' to 'float'
|
||||
|
||||
namespace decomp {
|
||||
|
||||
/******* Matrix Preliminaries *******/
|
||||
|
||||
/** Fill out 3x3 matrix to 4x4 **/
|
||||
#define mat_pad(A) (A[W][X]=A[X][W]=A[W][Y]=A[Y][W]=A[W][Z]=A[Z][W]=0,A[W][W]=1)
|
||||
|
||||
/** Copy nxn matrix A to C using "gets" for assignment **/
|
||||
#define mat_copy(C,gets,A,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\
|
||||
C[i][j] gets (A[i][j]);}
|
||||
|
||||
/** Copy transpose of nxn matrix A to C using "gets" for assignment **/
|
||||
#define mat_tpose(AT,gets,A,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\
|
||||
AT[i][j] gets (A[j][i]);}
|
||||
|
||||
/** Assign nxn matrix C the element-wise combination of A and B using "op" **/
|
||||
#define mat_binop(C,gets,A,op,B,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\
|
||||
C[i][j] gets (A[i][j]) op (B[i][j]);}
|
||||
|
||||
/** Multiply the upper left 3x3 parts of A and B to get AB **/
|
||||
void mat_mult(HMatrix A, HMatrix B, HMatrix AB)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < 3; i++) for (j = 0; j < 3; j++)
|
||||
AB[i][j] = A[i][0] * B[0][j] + A[i][1] * B[1][j] + A[i][2] * B[2][j];
|
||||
}
|
||||
|
||||
/** Return dot product of length 3 vectors va and vb **/
|
||||
float vdot(float* va, float* vb)
|
||||
{
|
||||
return (va[0] * vb[0] + va[1] * vb[1] + va[2] * vb[2]);
|
||||
}
|
||||
|
||||
/** Set v to cross product of length 3 vectors va and vb **/
|
||||
void vcross(float* va, float* vb, float* v)
|
||||
{
|
||||
v[0] = va[1] * vb[2] - va[2] * vb[1];
|
||||
v[1] = va[2] * vb[0] - va[0] * vb[2];
|
||||
v[2] = va[0] * vb[1] - va[1] * vb[0];
|
||||
}
|
||||
|
||||
/** Set MadjT to transpose of inverse of M times determinant of M **/
|
||||
void adjoint_transpose(HMatrix M, HMatrix MadjT)
|
||||
{
|
||||
vcross(M[1], M[2], MadjT[0]);
|
||||
vcross(M[2], M[0], MadjT[1]);
|
||||
vcross(M[0], M[1], MadjT[2]);
|
||||
}
|
||||
|
||||
/******* Quaternion Preliminaries *******/
|
||||
|
||||
/* Construct a (possibly non-unit) quaternion from real components. */
|
||||
Quat Qt_(float x, float y, float z, float w)
|
||||
{
|
||||
Quat qq;
|
||||
qq.x = x; qq.y = y; qq.z = z; qq.w = w;
|
||||
return (qq);
|
||||
}
|
||||
|
||||
/* Return conjugate of quaternion. */
|
||||
Quat Qt_Conj(Quat q)
|
||||
{
|
||||
Quat qq;
|
||||
qq.x = -q.x; qq.y = -q.y; qq.z = -q.z; qq.w = q.w;
|
||||
return (qq);
|
||||
}
|
||||
|
||||
/* Return quaternion product qL * qR. Note: order is important!
|
||||
* To combine rotations, use the product Mul(qSecond, qFirst),
|
||||
* which gives the effect of rotating by qFirst then qSecond. */
|
||||
Quat Qt_Mul(Quat qL, Quat qR)
|
||||
{
|
||||
Quat qq;
|
||||
qq.w = qL.w * qR.w - qL.x * qR.x - qL.y * qR.y - qL.z * qR.z;
|
||||
qq.x = qL.w * qR.x + qL.x * qR.w + qL.y * qR.z - qL.z * qR.y;
|
||||
qq.y = qL.w * qR.y + qL.y * qR.w + qL.z * qR.x - qL.x * qR.z;
|
||||
qq.z = qL.w * qR.z + qL.z * qR.w + qL.x * qR.y - qL.y * qR.x;
|
||||
return (qq);
|
||||
}
|
||||
|
||||
/* Return product of quaternion q by scalar w. */
|
||||
Quat Qt_Scale(Quat q, float w)
|
||||
{
|
||||
Quat qq;
|
||||
qq.w = q.w * w; qq.x = q.x * w; qq.y = q.y * w; qq.z = q.z * w;
|
||||
return (qq);
|
||||
}
|
||||
|
||||
/* Construct a unit quaternion from rotation matrix. Assumes matrix is
|
||||
* used to multiply column vector on the left: vnew = mat vold. Works
|
||||
* correctly for right-handed coordinate system and right-handed rotations.
|
||||
* Translation and perspective components ignored. */
|
||||
Quat Qt_FromMatrix(HMatrix mat)
|
||||
{
|
||||
/* This algorithm avoids near-zero divides by looking for a large component
|
||||
* - first w, then x, y, or z. When the trace is greater than zero,
|
||||
* |w| is greater than 1/2, which is as small as a largest component can be.
|
||||
* Otherwise, the largest diagonal entry corresponds to the largest of |x|,
|
||||
* |y|, or |z|, one of which must be larger than |w|, and at least 1/2. */
|
||||
Quat qu;
|
||||
double tr, s;
|
||||
|
||||
tr = mat[X][X] + mat[Y][Y] + mat[Z][Z];
|
||||
if (tr >= 0.0) {
|
||||
s = sqrt(tr + mat[W][W]);
|
||||
qu.w = s * 0.5;
|
||||
s = 0.5 / s;
|
||||
qu.x = (mat[Z][Y] - mat[Y][Z]) * s;
|
||||
qu.y = (mat[X][Z] - mat[Z][X]) * s;
|
||||
qu.z = (mat[Y][X] - mat[X][Y]) * s;
|
||||
} else {
|
||||
int h = X;
|
||||
if (mat[Y][Y] > mat[X][X]) h = Y;
|
||||
if (mat[Z][Z] > mat[h][h]) h = Z;
|
||||
switch (h) {
|
||||
#define caseMacro(i,j,k,I,J,K) \
|
||||
case I:\
|
||||
s = sqrt( (mat[I][I] - (mat[J][J]+mat[K][K])) + mat[W][W] );\
|
||||
qu.i = s*0.5;\
|
||||
s = 0.5 / s;\
|
||||
qu.j = (mat[I][J] + mat[J][I]) * s;\
|
||||
qu.k = (mat[K][I] + mat[I][K]) * s;\
|
||||
qu.w = (mat[K][J] - mat[J][K]) * s;\
|
||||
break
|
||||
caseMacro(x, y, z, X, Y, Z);
|
||||
caseMacro(y, z, x, Y, Z, X);
|
||||
caseMacro(z, x, y, Z, X, Y);
|
||||
}
|
||||
}
|
||||
if (mat[W][W] != 1.0) qu = Qt_Scale(qu, 1 / sqrt(mat[W][W]));
|
||||
return (qu);
|
||||
}
|
||||
/******* Decomp Auxiliaries *******/
|
||||
|
||||
static HMatrix mat_id = { {1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1} };
|
||||
|
||||
/** Compute either the 1 or infinity norm of M, depending on tpose **/
|
||||
float mat_norm(HMatrix M, int tpose)
|
||||
{
|
||||
int i;
|
||||
float sum, max;
|
||||
max = 0.0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (tpose) sum = fabs(M[0][i]) + fabs(M[1][i]) + fabs(M[2][i]);
|
||||
else sum = fabs(M[i][0]) + fabs(M[i][1]) + fabs(M[i][2]);
|
||||
if (max < sum) max = sum;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
float norm_inf(HMatrix M) { return mat_norm(M, 0); }
|
||||
float norm_one(HMatrix M) { return mat_norm(M, 1); }
|
||||
|
||||
/** Return index of column of M containing maximum abs entry, or -1 if M=0 **/
|
||||
int find_max_col(HMatrix M)
|
||||
{
|
||||
float abs, max;
|
||||
int i, j, col;
|
||||
max = 0.0; col = -1;
|
||||
for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) {
|
||||
abs = M[i][j]; if (abs < 0.0) abs = -abs;
|
||||
if (abs > max) { max = abs; col = j; }
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
||||
/** Setup u for Household reflection to zero all v components but first **/
|
||||
void make_reflector(float* v, float* u)
|
||||
{
|
||||
float s = sqrt(vdot(v, v));
|
||||
u[0] = v[0]; u[1] = v[1];
|
||||
u[2] = v[2] + ((v[2] < 0.0) ? -s : s);
|
||||
s = sqrt(2.0 / vdot(u, u));
|
||||
u[0] = u[0] * s; u[1] = u[1] * s; u[2] = u[2] * s;
|
||||
}
|
||||
|
||||
/** Apply Householder reflection represented by u to column vectors of M **/
|
||||
void reflect_cols(HMatrix M, float* u)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < 3; i++) {
|
||||
float s = u[0] * M[0][i] + u[1] * M[1][i] + u[2] * M[2][i];
|
||||
for (j = 0; j < 3; j++) M[j][i] -= u[j] * s;
|
||||
}
|
||||
}
|
||||
/** Apply Householder reflection represented by u to row vectors of M **/
|
||||
void reflect_rows(HMatrix M, float* u)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < 3; i++) {
|
||||
float s = vdot(u, M[i]);
|
||||
for (j = 0; j < 3; j++) M[i][j] -= u[j] * s;
|
||||
}
|
||||
}
|
||||
|
||||
/** Find orthogonal factor Q of rank 1 (or less) M **/
|
||||
void do_rank1(HMatrix M, HMatrix Q)
|
||||
{
|
||||
float v1[3], v2[3], s;
|
||||
int col;
|
||||
mat_copy(Q, =, mat_id, 4);
|
||||
/* If rank(M) is 1, we should find a non-zero column in M */
|
||||
col = find_max_col(M);
|
||||
if (col < 0) return; /* Rank is 0 */
|
||||
v1[0] = M[0][col]; v1[1] = M[1][col]; v1[2] = M[2][col];
|
||||
make_reflector(v1, v1); reflect_cols(M, v1);
|
||||
v2[0] = M[2][0]; v2[1] = M[2][1]; v2[2] = M[2][2];
|
||||
make_reflector(v2, v2); reflect_rows(M, v2);
|
||||
s = M[2][2];
|
||||
if (s < 0.0) Q[2][2] = -1.0;
|
||||
reflect_cols(Q, v1); reflect_rows(Q, v2);
|
||||
}
|
||||
|
||||
/** Find orthogonal factor Q of rank 2 (or less) M using adjoint transpose **/
|
||||
void do_rank2(HMatrix M, HMatrix MadjT, HMatrix Q)
|
||||
{
|
||||
float v1[3], v2[3];
|
||||
float w, x, y, z, c, s, d;
|
||||
int col;
|
||||
/* If rank(M) is 2, we should find a non-zero column in MadjT */
|
||||
col = find_max_col(MadjT);
|
||||
if (col < 0) { do_rank1(M, Q); return; } /* Rank<2 */
|
||||
v1[0] = MadjT[0][col]; v1[1] = MadjT[1][col]; v1[2] = MadjT[2][col];
|
||||
make_reflector(v1, v1); reflect_cols(M, v1);
|
||||
vcross(M[0], M[1], v2);
|
||||
make_reflector(v2, v2); reflect_rows(M, v2);
|
||||
w = M[0][0]; x = M[0][1]; y = M[1][0]; z = M[1][1];
|
||||
if (w * z > x* y) {
|
||||
c = z + w; s = y - x; d = sqrt(c * c + s * s); c = c / d; s = s / d;
|
||||
Q[0][0] = Q[1][1] = c; Q[0][1] = -(Q[1][0] = s);
|
||||
} else {
|
||||
c = z - w; s = y + x; d = sqrt(c * c + s * s); c = c / d; s = s / d;
|
||||
Q[0][0] = -(Q[1][1] = c); Q[0][1] = Q[1][0] = s;
|
||||
}
|
||||
Q[0][2] = Q[2][0] = Q[1][2] = Q[2][1] = 0.0; Q[2][2] = 1.0;
|
||||
reflect_cols(Q, v1); reflect_rows(Q, v2);
|
||||
}
|
||||
|
||||
|
||||
/******* Polar Decomposition *******/
|
||||
|
||||
/* Polar Decomposition of 3x3 matrix in 4x4,
|
||||
* M = QS. See Nicholas Higham and Robert S. Schreiber,
|
||||
* Fast Polar Decomposition of An Arbitrary Matrix,
|
||||
* Technical Report 88-942, October 1988,
|
||||
* Department of Computer Science, Cornell University.
|
||||
*/
|
||||
float polar_decomp(HMatrix M, HMatrix Q, HMatrix S)
|
||||
{
|
||||
#define TOL 1.0e-6
|
||||
HMatrix Mk, MadjTk, Ek;
|
||||
float det, M_one, M_inf, MadjT_one, MadjT_inf, E_one, gamma, g1, g2;
|
||||
int i, j;
|
||||
mat_tpose(Mk, =, M, 3);
|
||||
M_one = norm_one(Mk); M_inf = norm_inf(Mk);
|
||||
do {
|
||||
adjoint_transpose(Mk, MadjTk);
|
||||
det = vdot(Mk[0], MadjTk[0]);
|
||||
if (det == 0.0) { do_rank2(Mk, MadjTk, Mk); break; }
|
||||
MadjT_one = norm_one(MadjTk); MadjT_inf = norm_inf(MadjTk);
|
||||
gamma = sqrt(sqrt((MadjT_one * MadjT_inf) / (M_one * M_inf)) / fabs(det));
|
||||
g1 = gamma * 0.5;
|
||||
g2 = 0.5 / (gamma * det);
|
||||
mat_copy(Ek, =, Mk, 3);
|
||||
mat_binop(Mk, =, g1 * Mk, +, g2 * MadjTk, 3);
|
||||
mat_copy(Ek, -=, Mk, 3);
|
||||
E_one = norm_one(Ek);
|
||||
M_one = norm_one(Mk); M_inf = norm_inf(Mk);
|
||||
} while (E_one > (M_one * TOL));
|
||||
mat_tpose(Q, =, Mk, 3); mat_pad(Q);
|
||||
mat_mult(Mk, M, S); mat_pad(S);
|
||||
for (i = 0; i < 3; i++) for (j = i; j < 3; j++)
|
||||
S[i][j] = S[j][i] = 0.5 * (S[i][j] + S[j][i]);
|
||||
return (det);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/******* Spectral Decomposition *******/
|
||||
|
||||
/* Compute the spectral decomposition of symmetric positive semi-definite S.
|
||||
* Returns rotation in U and scale factors in result, so that if K is a diagonal
|
||||
* matrix of the scale factors, then S = U K (U transpose). Uses Jacobi method.
|
||||
* See Gene H. Golub and Charles F. Van Loan. Matrix Computations. Hopkins 1983.
|
||||
*/
|
||||
HVect spect_decomp(HMatrix S, HMatrix U)
|
||||
{
|
||||
HVect kv;
|
||||
double Diag[3], OffD[3]; /* OffD is off-diag (by omitted index) */
|
||||
double g, h, fabsh, fabsOffDi, t, theta, c, s, tau, ta, OffDq, a, b;
|
||||
static char nxt[] = { Y,Z,X };
|
||||
int sweep, i, j;
|
||||
mat_copy(U, =, mat_id, 4);
|
||||
Diag[X] = S[X][X]; Diag[Y] = S[Y][Y]; Diag[Z] = S[Z][Z];
|
||||
OffD[X] = S[Y][Z]; OffD[Y] = S[Z][X]; OffD[Z] = S[X][Y];
|
||||
for (sweep = 20; sweep > 0; sweep--) {
|
||||
float sm = fabs(OffD[X]) + fabs(OffD[Y]) + fabs(OffD[Z]);
|
||||
if (sm == 0.0) break;
|
||||
for (i = Z; i >= X; i--) {
|
||||
int p = nxt[i]; int q = nxt[p];
|
||||
fabsOffDi = fabs(OffD[i]);
|
||||
g = 100.0 * fabsOffDi;
|
||||
if (fabsOffDi > 0.0) {
|
||||
h = Diag[q] - Diag[p];
|
||||
fabsh = fabs(h);
|
||||
if (fabsh + g == fabsh) {
|
||||
t = OffD[i] / h;
|
||||
} else {
|
||||
theta = 0.5 * h / OffD[i];
|
||||
t = 1.0 / (fabs(theta) + sqrt(theta * theta + 1.0));
|
||||
if (theta < 0.0) t = -t;
|
||||
}
|
||||
c = 1.0 / sqrt(t * t + 1.0); s = t * c;
|
||||
tau = s / (c + 1.0);
|
||||
ta = t * OffD[i]; OffD[i] = 0.0;
|
||||
Diag[p] -= ta; Diag[q] += ta;
|
||||
OffDq = OffD[q];
|
||||
OffD[q] -= s * (OffD[p] + tau * OffD[q]);
|
||||
OffD[p] += s * (OffDq - tau * OffD[p]);
|
||||
for (j = Z; j >= X; j--) {
|
||||
a = U[j][p]; b = U[j][q];
|
||||
U[j][p] -= s * (b + tau * a);
|
||||
U[j][q] += s * (a - tau * b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
kv.x = Diag[X]; kv.y = Diag[Y]; kv.z = Diag[Z]; kv.w = 1.0;
|
||||
return (kv);
|
||||
}
|
||||
|
||||
/******* Spectral Axis Adjustment *******/
|
||||
|
||||
/* Given a unit quaternion, q, and a scale vector, k, find a unit quaternion, p,
|
||||
* which permutes the axes and turns freely in the plane of duplicate scale
|
||||
* factors, such that q p has the largest possible w component, i.e. the
|
||||
* smallest possible angle. Permutes k's components to go with q p instead of q.
|
||||
* See Ken Shoemake and Tom Duff. Matrix Animation and Polar Decomposition.
|
||||
* Proceedings of Graphics Interface 1992. Details on p. 262-263.
|
||||
*/
|
||||
Quat snuggle(Quat q, HVect* k)
|
||||
{
|
||||
#define SQRTHALF (0.7071067811865475244f)
|
||||
#define sgn(n,v) ((n)?-(v):(v))
|
||||
#define swap(a,i,j) {a[3]=a[i]; a[i]=a[j]; a[j]=a[3];}
|
||||
#define cycle(a,p) if (p) {a[3]=a[0]; a[0]=a[1]; a[1]=a[2]; a[2]=a[3];}\
|
||||
else {a[3]=a[2]; a[2]=a[1]; a[1]=a[0]; a[0]=a[3];}
|
||||
Quat p;
|
||||
float ka[4];
|
||||
int i, turn = -1;
|
||||
ka[X] = k->x; ka[Y] = k->y; ka[Z] = k->z;
|
||||
if (ka[X] == ka[Y]) { if (ka[X] == ka[Z]) turn = W; else turn = Z; }
|
||||
else { if (ka[X] == ka[Z]) turn = Y; else if (ka[Y] == ka[Z]) turn = X; }
|
||||
if (turn >= 0) {
|
||||
Quat qtoz, qp;
|
||||
unsigned neg[3], win;
|
||||
double mag[3], t;
|
||||
static Quat qxtoz = { 0,SQRTHALF,0,SQRTHALF };
|
||||
static Quat qytoz = { SQRTHALF,0,0,SQRTHALF };
|
||||
static Quat qppmm = { 0.5, 0.5,-0.5,-0.5 };
|
||||
static Quat qpppp = { 0.5, 0.5, 0.5, 0.5 };
|
||||
static Quat qmpmm = { -0.5, 0.5,-0.5,-0.5 };
|
||||
static Quat qpppm = { 0.5, 0.5, 0.5,-0.5 };
|
||||
static Quat q0001 = { 0.0, 0.0, 0.0, 1.0 };
|
||||
static Quat q1000 = { 1.0, 0.0, 0.0, 0.0 };
|
||||
switch (turn) {
|
||||
default: return (Qt_Conj(q));
|
||||
case X: q = Qt_Mul(q, qtoz = qxtoz); swap(ka, X, Z) break;
|
||||
case Y: q = Qt_Mul(q, qtoz = qytoz); swap(ka, Y, Z) break;
|
||||
case Z: qtoz = q0001; break;
|
||||
}
|
||||
q = Qt_Conj(q);
|
||||
mag[0] = (double)q.z * q.z + (double)q.w * q.w - 0.5;
|
||||
mag[1] = (double)q.x * q.z - (double)q.y * q.w;
|
||||
mag[2] = (double)q.y * q.z + (double)q.x * q.w;
|
||||
for (i = 0; i < 3; i++) if (neg[i] = (mag[i] < 0.0)) mag[i] = -mag[i];
|
||||
if (mag[0] > mag[1]) { if (mag[0] > mag[2]) win = 0; else win = 2; }
|
||||
else { if (mag[1] > mag[2]) win = 1; else win = 2; }
|
||||
switch (win) {
|
||||
case 0: if (neg[0]) p = q1000; else p = q0001; break;
|
||||
case 1: if (neg[1]) p = qppmm; else p = qpppp; cycle(ka, 0) break;
|
||||
case 2: if (neg[2]) p = qmpmm; else p = qpppm; cycle(ka, 1) break;
|
||||
}
|
||||
qp = Qt_Mul(q, p);
|
||||
t = sqrt(mag[win] + 0.5);
|
||||
p = Qt_Mul(p, Qt_(0.0, 0.0, -qp.z / t, qp.w / t));
|
||||
p = Qt_Mul(qtoz, Qt_Conj(p));
|
||||
} else {
|
||||
float qa[4], pa[4];
|
||||
unsigned lo, hi, neg[4], par = 0;
|
||||
double all, big, two;
|
||||
qa[0] = q.x; qa[1] = q.y; qa[2] = q.z; qa[3] = q.w;
|
||||
for (i = 0; i < 4; i++) {
|
||||
pa[i] = 0.0;
|
||||
if (neg[i] = (qa[i] < 0.0)) qa[i] = -qa[i];
|
||||
par ^= neg[i];
|
||||
}
|
||||
/* Find two largest components, indices in hi and lo */
|
||||
if (qa[0] > qa[1]) lo = 0; else lo = 1;
|
||||
if (qa[2] > qa[3]) hi = 2; else hi = 3;
|
||||
if (qa[lo] > qa[hi]) {
|
||||
if (qa[lo ^ 1] > qa[hi]) { hi = lo; lo ^= 1; }
|
||||
else { hi ^= lo; lo ^= hi; hi ^= lo; }
|
||||
} else {if (qa[hi^1]>qa[lo]) lo = hi^1;}
|
||||
all = (qa[0] + qa[1] + qa[2] + qa[3]) * 0.5;
|
||||
two = (qa[hi] + qa[lo]) * SQRTHALF;
|
||||
big = qa[hi];
|
||||
if (all > two) {
|
||||
if (all > big) {/*all*/
|
||||
{int i; for (i = 0; i < 4; i++) pa[i] = sgn(neg[i], 0.5); }
|
||||
cycle(ka, par)
|
||||
} else {/*big*/ pa[hi] = sgn(neg[hi],1.0);}
|
||||
} else {
|
||||
if (two > big) {/*two*/
|
||||
pa[hi] = sgn(neg[hi], SQRTHALF); pa[lo] = sgn(neg[lo], SQRTHALF);
|
||||
if (lo > hi) { hi ^= lo; lo ^= hi; hi ^= lo; }
|
||||
if (hi == W) { hi = "\001\002\000"[lo]; lo = 3 - hi - lo; }
|
||||
swap(ka, hi, lo)
|
||||
} else {/*big*/ pa[hi] = sgn(neg[hi],1.0);}
|
||||
}
|
||||
p.x = -pa[0]; p.y = -pa[1]; p.z = -pa[2]; p.w = pa[3];
|
||||
}
|
||||
k->x = ka[X]; k->y = ka[Y]; k->z = ka[Z];
|
||||
return (p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/******* Decompose Affine Matrix *******/
|
||||
|
||||
/* Decompose 4x4 affine matrix A as TFRUK(U transpose), where t contains the
|
||||
* translation components, q contains the rotation R, u contains U, k contains
|
||||
* scale factors, and f contains the sign of the determinant.
|
||||
* Assumes A transforms column vectors in right-handed coordinates.
|
||||
* See Ken Shoemake and Tom Duff. Matrix Animation and Polar Decomposition.
|
||||
* Proceedings of Graphics Interface 1992.
|
||||
*/
|
||||
void decomp_affine(HMatrix A, AffineParts* parts)
|
||||
{
|
||||
HMatrix Q, S, U;
|
||||
Quat p;
|
||||
float det;
|
||||
parts->t = Qt_(A[X][W], A[Y][W], A[Z][W], 0);
|
||||
det = polar_decomp(A, Q, S);
|
||||
if (det < 0.0) {
|
||||
mat_copy(Q, =, -Q, 3);
|
||||
parts->f = -1;
|
||||
} else parts->f = 1;
|
||||
parts->q = Qt_FromMatrix(Q);
|
||||
parts->k = spect_decomp(S, U);
|
||||
parts->u = Qt_FromMatrix(U);
|
||||
p = snuggle(parts->u, &parts->k);
|
||||
parts->u = Qt_Mul(parts->u, p);
|
||||
}
|
||||
|
||||
/******* Invert Affine Decomposition *******/
|
||||
|
||||
/* Compute inverse of affine decomposition.
|
||||
*/
|
||||
void invert_affine(AffineParts* parts, AffineParts* inverse)
|
||||
{
|
||||
Quat t, p;
|
||||
inverse->f = parts->f;
|
||||
inverse->q = Qt_Conj(parts->q);
|
||||
inverse->u = Qt_Mul(parts->q, parts->u);
|
||||
inverse->k.x = (parts->k.x == 0.0) ? 0.0 : 1.0 / parts->k.x;
|
||||
inverse->k.y = (parts->k.y == 0.0) ? 0.0 : 1.0 / parts->k.y;
|
||||
inverse->k.z = (parts->k.z == 0.0) ? 0.0 : 1.0 / parts->k.z;
|
||||
inverse->k.w = parts->k.w;
|
||||
t = Qt_(-parts->t.x, -parts->t.y, -parts->t.z, 0);
|
||||
t = Qt_Mul(Qt_Conj(inverse->u), Qt_Mul(t, inverse->u));
|
||||
t = Qt_(inverse->k.x * t.x, inverse->k.y * t.y, inverse->k.z * t.z, 0);
|
||||
p = Qt_Mul(inverse->q, inverse->u);
|
||||
t = Qt_Mul(p, Qt_Mul(t, Qt_Conj(p)));
|
||||
inverse->t = (inverse->f > 0.0) ? t : Qt_(-t.x, -t.y, -t.z, 0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
namespace decomp {
|
||||
// Taken from http://tog.acm.org/GraphicsGems/gemsiv/polar_decomp/Decompose.h
|
||||
|
||||
/**** Decompose.h - Basic declarations ****/
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_DECOMPOSE_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_DECOMPOSE_H
|
||||
#pragma once
|
||||
|
||||
typedef struct {float x, y, z, w;} Quat; /* Quaternion */
|
||||
enum QuatPart {X, Y, Z, W};
|
||||
typedef Quat HVect; /* Homogeneous 3D vector */
|
||||
typedef float HMatrix[4][4]; /* Right-handed, for column vectors */
|
||||
typedef struct {
|
||||
HVect t; /* Translation components */
|
||||
Quat q; /* Essential rotation */
|
||||
Quat u; /* Stretch rotation */
|
||||
HVect k; /* Stretch factors */
|
||||
float f; /* Sign of determinant */
|
||||
} AffineParts;
|
||||
float polar_decomp(HMatrix M, HMatrix Q, HMatrix S);
|
||||
HVect spect_decomp(HMatrix S, HMatrix U);
|
||||
Quat snuggle(Quat q, HVect *k);
|
||||
void decomp_affine(HMatrix A, AffineParts *parts);
|
||||
void invert_affine(AffineParts *parts, AffineParts *inverse);
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_DECOMPOSE_H
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_EXCEPTIONS_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_EXCEPTIONS_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
class BaseException
|
||||
: public std::exception
|
||||
{
|
||||
public:
|
||||
BaseException(const string& msg)
|
||||
: msg(msg) {}
|
||||
virtual const char* what() const throw () {return msg.c_str(); }
|
||||
|
||||
private:
|
||||
string msg;
|
||||
};
|
||||
|
||||
template <typename Tag>
|
||||
class Exception
|
||||
: public BaseException
|
||||
{
|
||||
public:
|
||||
Exception(const string& msg)
|
||||
: BaseException(msg) {}
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_EXCEPTIONS_H
|
||||
@@ -1,175 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include <platform.h>
|
||||
#include "FileUtil.h"
|
||||
#include "PathHelpers.h"
|
||||
#include "StringHelpers.h"
|
||||
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// returns true if 'dir' is a subdirectory of 'baseDir' or same directory as 'baseDir'
|
||||
// note: returns false in case of wrong names passed
|
||||
static bool IsSubdirOrSameDir(const char* dir, const char* baseDir)
|
||||
{
|
||||
|
||||
AZ::IO::LocalFileIO localFileIO;
|
||||
|
||||
char szFullPathDir[AZ_MAX_PATH_LEN];
|
||||
if(!localFileIO.ConvertToAbsolutePath(dir, szFullPathDir, sizeof(szFullPathDir)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char szFullPathBaseDir[2 * 1024];
|
||||
if(!localFileIO.ConvertToAbsolutePath(baseDir, szFullPathBaseDir, sizeof(szFullPathBaseDir)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* p = szFullPathDir;
|
||||
const char* q = szFullPathBaseDir;
|
||||
for (;; ++p, ++q)
|
||||
{
|
||||
if (tolower(*p) == tolower(*q))
|
||||
{
|
||||
if (*p == 0)
|
||||
{
|
||||
// dir is exactly same as baseDir
|
||||
return true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((*p == '/' || *p == '\\') && (*q == '/' || *q == '\\'))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*p == 0)
|
||||
{
|
||||
// dir length is shorter than baseDir length. so it's not a subdir
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*q == 0)
|
||||
{
|
||||
// baseDir is shorter than dir. so may be it's a subdir.
|
||||
const bool isSubdir = (*p == '/' || *p == '\\');
|
||||
return isSubdir;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// the paths must have trailing slash
|
||||
static bool ScanDirectoryRecursive(const string& root, const string& path, const string& file, std::vector<string>& files, bool recursive, const string& dirToIgnore)
|
||||
{
|
||||
bool anyFound = false;
|
||||
if (!dirToIgnore.empty())
|
||||
{
|
||||
if (IsSubdirOrSameDir(root.c_str(), dirToIgnore.c_str()))
|
||||
{
|
||||
return anyFound;
|
||||
}
|
||||
}
|
||||
|
||||
AZ::IO::LocalFileIO localFileIO;
|
||||
localFileIO.FindFiles(root.c_str(), file.c_str(), [&](const char* filePath) -> bool
|
||||
{
|
||||
bool isDir = localFileIO.IsDirectory(filePath);
|
||||
if (!isDir)
|
||||
{
|
||||
const string foundFilename(filePath);
|
||||
if (StringHelpers::MatchesWildcardsIgnoreCase(foundFilename, file))
|
||||
{
|
||||
anyFound = true;
|
||||
files.push_back(PathHelpers::Join(path, PathHelpers::GetFilename(filePath)));
|
||||
}
|
||||
}
|
||||
|
||||
return true; // Keep iterating
|
||||
});
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
localFileIO.FindFiles(root.c_str(), "*", [&](const char* filePath) -> bool
|
||||
{
|
||||
bool isDir = localFileIO.IsDirectory(filePath);
|
||||
// If recursive.
|
||||
if (isDir && strcmp(filePath, ".") && strcmp(filePath, ".."))
|
||||
{
|
||||
if (ScanDirectoryRecursive(filePath, PathHelpers::Join(path, PathHelpers::GetFilename(filePath)), file, files, recursive, dirToIgnore))
|
||||
{
|
||||
anyFound = true;
|
||||
}
|
||||
}
|
||||
return true; // Keep iterating
|
||||
});
|
||||
}
|
||||
|
||||
return anyFound;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool FileUtil::ScanDirectory(const string& path, const string& file, std::vector<string>& files, bool recursive, const string& dirToIgnore)
|
||||
{
|
||||
return ScanDirectoryRecursive(path, "", file, files, recursive, dirToIgnore);
|
||||
}
|
||||
|
||||
|
||||
bool FileUtil::EnsureDirectoryExists(const char* szPathIn)
|
||||
{
|
||||
if (!szPathIn || !szPathIn[0])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (DirectoryExists(szPathIn))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<char> path(szPathIn, szPathIn + strlen(szPathIn) + 1);
|
||||
char* p = &path[0];
|
||||
|
||||
// Skip '/' and '//' in the beginning
|
||||
while (*p == '/' || *p == '\\')
|
||||
{
|
||||
++p;
|
||||
}
|
||||
|
||||
for (;; )
|
||||
{
|
||||
while (*p != '/' && *p != '\\' && *p)
|
||||
{
|
||||
++p;
|
||||
}
|
||||
const char saved = *p;
|
||||
*p = 0;
|
||||
AZ::IO::LocalFileIO().CreatePath(&path[0]);
|
||||
*p++ = saved;
|
||||
if (saved == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return DirectoryExists(szPathIn);
|
||||
}
|
||||
@@ -1,311 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_FILEUTIL_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_FILEUTIL_H
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
|
||||
#if AZ_TRAIT_OS_PLATFORM_APPLE || defined(AZ_PLATFORM_LINUX)
|
||||
#include <utime.h>
|
||||
#endif
|
||||
#if defined(AZ_PLATFORM_LINUX)
|
||||
#include "Linux64Specific.h"
|
||||
#endif // defined(AZ_PLATFORM_LINUX)
|
||||
|
||||
#include <platform.h>
|
||||
#include <vector>
|
||||
|
||||
namespace FileUtil
|
||||
{
|
||||
// Magic number explanation:
|
||||
// Both epochs are Gregorian. 1970 - 1601 = 369. Assuming a leap
|
||||
// year every four years, 369 / 4 = 92. However, 1700, 1800, and 1900
|
||||
// were NOT leap years, so 89 leap years, 280 non-leap years.
|
||||
// 89 * 366 + 280 * 365 = 134744 days between epochs. Of course
|
||||
// 60 * 60 * 24 = 86400 seconds per day, so 134744 * 86400 =
|
||||
// 11644473600 = SECS_BETWEEN_EPOCHS.
|
||||
//
|
||||
// This result is also confirmed in the MSDN documentation on how
|
||||
// to convert a time_t value to a win32 FILETIME.
|
||||
#define SECS_BETWEEN_EPOCHS 11644473600ll
|
||||
/* 10^7 */
|
||||
#define SECS_TO_100NS 10000000ll
|
||||
|
||||
// Find all files matching filespec.
|
||||
bool ScanDirectory(const string& path, const string& filespec, std::vector<string>& files, bool recursive, const string& dirToIgnore);
|
||||
|
||||
// Ensures that directory specified by szPathIn exists by creating all needed (sub-)directories.
|
||||
// Returns false in case of a failure.
|
||||
// Example: "c:\temp\test" ("c:\temp\test\" also works) - ensures that "c:\temp\test" exists.
|
||||
bool EnsureDirectoryExists(const char* szPathIn);
|
||||
|
||||
// converts the FILETIME to the C Timestamp (compatible with dbghelp.dll)
|
||||
inline DWORD FiletimeToUnixTime(const FILETIME& ft)
|
||||
{
|
||||
return (DWORD)((((int64&)ft) / SECS_TO_100NS) - SECS_BETWEEN_EPOCHS);
|
||||
}
|
||||
|
||||
// converts the FILETIME to 64bit C timestamp
|
||||
inline AZ::u64 FiletimeTo64BitUnixTime(const FILETIME& fileTime)
|
||||
{
|
||||
const AZ::u64 time = static_cast<AZ::u64>(fileTime.dwHighDateTime) << 32 | fileTime.dwLowDateTime;
|
||||
return ((time / SECS_TO_100NS) - SECS_BETWEEN_EPOCHS);
|
||||
}
|
||||
|
||||
// converts the C Timestamp (compatible with dbghelp.dll) to FILETIME
|
||||
inline FILETIME UnixTimeToFiletime(DWORD nCTime)
|
||||
{
|
||||
const int64 time = (nCTime + SECS_BETWEEN_EPOCHS) * SECS_TO_100NS;
|
||||
return (FILETIME&)time;
|
||||
}
|
||||
|
||||
//converts the 64 bit C Timestamp to FILETIME
|
||||
inline void UnixTime64BitToFiletime(AZ::u64 nCTime, FILETIME& fileTime)
|
||||
{
|
||||
const AZ::u64 time = (nCTime + SECS_BETWEEN_EPOCHS) * SECS_TO_100NS;
|
||||
fileTime.dwLowDateTime = static_cast<DWORD>(time);
|
||||
fileTime.dwHighDateTime = static_cast<DWORD>(time >> 32);
|
||||
}
|
||||
|
||||
inline FILETIME GetInvalidFileTime()
|
||||
{
|
||||
FILETIME fileTime;
|
||||
fileTime.dwLowDateTime = 0;
|
||||
fileTime.dwHighDateTime = 0;
|
||||
return fileTime;
|
||||
}
|
||||
|
||||
// returns file time stamps
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
inline bool GetFileTimes(const char* filename, FILETIME* ftimeCreate = nullptr, FILETIME* ftimeAccess = nullptr, FILETIME* ftimeModify = nullptr)
|
||||
{
|
||||
WIN32_FIND_DATAA FindFileData;
|
||||
const HANDLE hFind = FindFirstFileA(filename, &FindFileData);
|
||||
if (hFind == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ftimeModify == nullptr && ftimeCreate == nullptr && ftimeAccess == nullptr)
|
||||
{
|
||||
FindClose(hFind);
|
||||
return true;
|
||||
}
|
||||
|
||||
FindClose(hFind);
|
||||
if (ftimeCreate)
|
||||
{
|
||||
ftimeCreate->dwLowDateTime = FindFileData.ftCreationTime.dwLowDateTime;
|
||||
ftimeCreate->dwHighDateTime = FindFileData.ftCreationTime.dwHighDateTime;
|
||||
}
|
||||
if (ftimeModify)
|
||||
{
|
||||
ftimeModify->dwLowDateTime = FindFileData.ftLastWriteTime.dwLowDateTime;
|
||||
ftimeModify->dwHighDateTime = FindFileData.ftLastWriteTime.dwHighDateTime;
|
||||
}
|
||||
if (ftimeAccess)
|
||||
{
|
||||
ftimeAccess->dwLowDateTime = FindFileData.ftLastAccessTime.dwLowDateTime;
|
||||
ftimeAccess->dwHighDateTime = FindFileData.ftCreationTime.dwHighDateTime;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
inline bool GetFileTimes(const char* filename, AZ::u64* timeCreate = nullptr, AZ::u64* timeAccess = nullptr, AZ::u64* timeModify = nullptr)
|
||||
{
|
||||
|
||||
struct stat statResult;
|
||||
if (stat(filename, &statResult) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (timeCreate)
|
||||
{
|
||||
*timeCreate =static_cast<AZ::u64>(statResult.st_ctime);
|
||||
}
|
||||
if (timeModify)
|
||||
{
|
||||
*timeModify =static_cast<AZ::u64>(statResult.st_mtime);
|
||||
}
|
||||
if (timeAccess)
|
||||
{
|
||||
*timeAccess =static_cast<AZ::u64>(statResult.st_atime);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
inline FILETIME GetLastWriteFileTime(const char* filename)
|
||||
{
|
||||
FILETIME timeModify = GetInvalidFileTime();
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
GetFileTimes(filename, nullptr, nullptr, &timeModify);
|
||||
#else
|
||||
AZ::u64 modTime = 0;
|
||||
GetFileTimes(filename, nullptr, nullptr, &modTime);
|
||||
if(modTime != 0)
|
||||
{
|
||||
UnixTime64BitToFiletime(modTime, timeModify);
|
||||
}
|
||||
#endif
|
||||
return timeModify;
|
||||
}
|
||||
|
||||
inline bool FileTimesAreEqual(const FILETIME& fileTime0, const FILETIME& fileTime1)
|
||||
{
|
||||
return
|
||||
(fileTime0.dwLowDateTime == fileTime1.dwLowDateTime) &&
|
||||
(fileTime0.dwHighDateTime == fileTime1.dwHighDateTime);
|
||||
}
|
||||
|
||||
inline bool FileTimesAreEqual(const char* const srcfilename, const char* const targetfilename)
|
||||
{
|
||||
FILETIME ftSource = FileUtil::GetLastWriteFileTime(srcfilename);
|
||||
FILETIME ftTarget = FileUtil::GetLastWriteFileTime(targetfilename);
|
||||
return FileTimesAreEqual(ftSource, ftTarget);
|
||||
}
|
||||
|
||||
inline bool FileTimeIsValid(const FILETIME& fileTime)
|
||||
{
|
||||
return !FileTimesAreEqual(GetInvalidFileTime(), fileTime);
|
||||
}
|
||||
|
||||
inline bool SetFileTimes(const char* const filename, const FILETIME& creationFileTime, const FILETIME& accessFileTime, const FILETIME& modifcationFileTime)
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
const HANDLE hf = CreateFileA(filename, FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
|
||||
if (hf != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (SetFileTime(hf, &creationFileTime, &accessFileTime, &modifcationFileTime))
|
||||
{
|
||||
if (CloseHandle(hf))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(hf);
|
||||
}
|
||||
#else
|
||||
AZ::u64 creationTime = FiletimeTo64BitUnixTime(creationFileTime);
|
||||
AZ::u64 modificationTime = FiletimeTo64BitUnixTime(modifcationFileTime);
|
||||
|
||||
struct utimbuf puttime;
|
||||
puttime.modtime = modificationTime;
|
||||
puttime.actime = creationTime;
|
||||
|
||||
if (utime(filename, &puttime) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool SetFileTimes(const char* const filename, const FILETIME& fileTime)
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
const HANDLE hf = CreateFileA(filename, FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
|
||||
if (hf != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (SetFileTime(hf, &fileTime, &fileTime, &fileTime))
|
||||
{
|
||||
if (CloseHandle(hf))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(hf);
|
||||
}
|
||||
#else
|
||||
|
||||
AZ::u64 newTime = FiletimeTo64BitUnixTime(fileTime);
|
||||
|
||||
struct utimbuf puttime;
|
||||
puttime.modtime = newTime;
|
||||
puttime.actime = newTime;
|
||||
|
||||
if (utime(filename, &puttime) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool SetFileTimes(const char* const srcfilename, const char* const targetfilename)
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
FILETIME creationFileTime, accessFileTime, modifcationFileTime;
|
||||
if (GetFileTimes(srcfilename, &creationFileTime, &accessFileTime, &modifcationFileTime))
|
||||
{
|
||||
const HANDLE hf = CreateFileA(targetfilename, FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
|
||||
if (hf != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (SetFileTime(hf, &creationFileTime, &accessFileTime, &modifcationFileTime))
|
||||
{
|
||||
if (CloseHandle(hf))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(hf);
|
||||
}
|
||||
}
|
||||
#else
|
||||
AZ::u64 creationFileTime, accessFileTime, modifcationFileTime;
|
||||
if (GetFileTimes(srcfilename, &creationFileTime, &accessFileTime, &modifcationFileTime))
|
||||
{
|
||||
struct utimbuf puttime;
|
||||
puttime.modtime = modifcationFileTime;
|
||||
puttime.actime = accessFileTime;
|
||||
|
||||
if (utime(targetfilename, &puttime) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
inline uint64 GetFileSize(const char* const filename)
|
||||
{
|
||||
AZ::u64 fileSize = AZ::IO::SystemFile::Length(filename);
|
||||
return fileSize >= 0? fileSize : -1;
|
||||
|
||||
}
|
||||
|
||||
inline bool FileExists(const char* szPath)
|
||||
{
|
||||
return AZ::IO::LocalFileIO().Exists(szPath);
|
||||
}
|
||||
|
||||
inline bool DirectoryExists(const char* szPath)
|
||||
{
|
||||
return AZ::IO::LocalFileIO().IsDirectory(szPath);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_FILEUTIL_H
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_FILEXMLBUFFERSOURCE_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_FILEXMLBUFFERSOURCE_H
|
||||
#pragma once
|
||||
|
||||
|
||||
class FileXmlBufferSource
|
||||
: public IXmlBufferSource
|
||||
{
|
||||
public:
|
||||
FileXmlBufferSource(const char* path)
|
||||
{
|
||||
file = std::fopen(path, "r");
|
||||
}
|
||||
~FileXmlBufferSource()
|
||||
{
|
||||
if (file)
|
||||
{
|
||||
std::fclose(file);
|
||||
}
|
||||
}
|
||||
|
||||
virtual int Read(void* buffer, int size) const
|
||||
{
|
||||
if (!file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return std::fread(buffer, 1, size, file);
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::FILE* file;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_FILEXMLBUFFERSOURCE_H
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_ILOGGER_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_ILOGGER_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
class ILogger
|
||||
{
|
||||
public:
|
||||
enum ESeverity
|
||||
{
|
||||
eSeverity_Debug,
|
||||
eSeverity_Info,
|
||||
eSeverity_Warning,
|
||||
eSeverity_Error
|
||||
};
|
||||
|
||||
virtual ~ILogger()
|
||||
{
|
||||
}
|
||||
|
||||
void Log(ESeverity eSeverity, const char* const format, ...)
|
||||
{
|
||||
char buffer[2048];
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
_vsnprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
LogImpl(eSeverity, buffer);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void LogImpl(ESeverity eSeverity, const char* text) = 0;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_ILOGGER_H
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_IPAKSYSTEM_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_IPAKSYSTEM_H
|
||||
#pragma once
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
struct PakSystemFile;
|
||||
struct PakSystemArchive;
|
||||
struct IPakSystem
|
||||
{
|
||||
virtual PakSystemFile* Open(const char* filename, const char* mode) = 0;
|
||||
virtual bool ExtractNoOverwrite(const char* filename, const char* extractToFile = 0) = 0;
|
||||
virtual void Close(PakSystemFile* file) = 0;
|
||||
virtual int GetLength(PakSystemFile* file) const = 0;
|
||||
virtual int Read(PakSystemFile* file, void* buffer, int size) = 0;
|
||||
virtual bool EoF(PakSystemFile* file) = 0;
|
||||
|
||||
virtual PakSystemArchive* OpenArchive(const char* path, size_t fileAlignment = 1, bool encrypted = false, const uint32 encryptionKey[4] = 0) = 0;
|
||||
virtual void CloseArchive(PakSystemArchive* archive) = 0;
|
||||
|
||||
// Summary:
|
||||
// Adds a new file to the pak or update an existing one.
|
||||
// Adds a directory (creates several nested directories if needed)
|
||||
// Arguments:
|
||||
// path - relative path inside archive
|
||||
// data, size - file content
|
||||
// modTime - modification timestamp of the file
|
||||
// compressionLevel - level of compression (correnponds to zlib-levels):
|
||||
// -1 or [0-9] where -1=default compression, 0=no compression, 9=best compression
|
||||
virtual void AddToArchive(PakSystemArchive* archive, const char* path, void* data, int size, int64 modTime, int compressionLevel = -1) = 0;
|
||||
|
||||
virtual bool DeleteFromArchive(PakSystemArchive* archive, const char* path) = 0;
|
||||
virtual bool CheckIfFileExist(PakSystemArchive* archive, const char* path, int64 modTime) = 0;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_IPAKSYSTEM_H
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_ISETTINGS_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_ISETTINGS_H
|
||||
#pragma once
|
||||
|
||||
|
||||
class ISettings
|
||||
{
|
||||
public:
|
||||
virtual bool GetSettingString(char* buffer, int bufferSizeInBytes, const char* key) = 0;
|
||||
virtual bool GetSettingInt(int& value, const char* key) = 0;
|
||||
};
|
||||
|
||||
inline bool GetSettingByRef(ISettings* settings, const string& key, string& value)
|
||||
{
|
||||
char buffer[1024];
|
||||
bool success = false;
|
||||
if (settings)
|
||||
{
|
||||
success = settings->GetSettingString(buffer, sizeof(buffer), key.c_str());
|
||||
}
|
||||
if (success)
|
||||
{
|
||||
value = buffer;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
inline bool GetSettingByRef(ISettings* settings, const string& key, int& value)
|
||||
{
|
||||
return settings->GetSettingInt(value, key.c_str());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T GetSetting(ISettings* settings, const string& key, const T& dflt)
|
||||
{
|
||||
T value;
|
||||
if (!GetSettingByRef(settings, key, value))
|
||||
{
|
||||
value = dflt;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_ISETTINGS_H
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include <platform.h>
|
||||
#include "LocaleChanger.h"
|
||||
#include <locale.h>
|
||||
|
||||
LocaleChanger::LocaleChanger(int category, const char* newLocale)
|
||||
{
|
||||
m_category = category;
|
||||
m_oldLocale = setlocale(category, newLocale);
|
||||
}
|
||||
|
||||
LocaleChanger::~LocaleChanger()
|
||||
{
|
||||
setlocale(m_category, m_oldLocale.c_str());
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_LOCALECHANGER_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_LOCALECHANGER_H
|
||||
#pragma once
|
||||
|
||||
|
||||
class LocaleChanger
|
||||
{
|
||||
public:
|
||||
LocaleChanger(int category, const char* newLocale);
|
||||
~LocaleChanger();
|
||||
|
||||
private:
|
||||
int m_category;
|
||||
string m_oldLocale;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_LOCALECHANGER_H
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include <platform.h>
|
||||
#include "LogFile.h"
|
||||
|
||||
LogFile::LogFile(const char* const filename)
|
||||
: m_file(0)
|
||||
, m_hasWarnings(false)
|
||||
, m_hasErrors(false)
|
||||
{
|
||||
m_file = std::fopen(filename, "w");
|
||||
}
|
||||
|
||||
LogFile::~LogFile()
|
||||
{
|
||||
if (m_file)
|
||||
{
|
||||
fclose(m_file);
|
||||
}
|
||||
}
|
||||
|
||||
bool LogFile::IsOpen() const
|
||||
{
|
||||
return m_file != 0;
|
||||
}
|
||||
|
||||
bool LogFile::HasWarningsOrErrors() const
|
||||
{
|
||||
return m_hasWarnings || m_hasErrors;
|
||||
}
|
||||
|
||||
void LogFile::LogImpl(ESeverity eSeverity, const char* const text)
|
||||
{
|
||||
const char* severityMessage = 0;
|
||||
switch (eSeverity)
|
||||
{
|
||||
case eSeverity_Debug:
|
||||
severityMessage = " ";
|
||||
break;
|
||||
case eSeverity_Info:
|
||||
severityMessage = " ";
|
||||
break;
|
||||
case eSeverity_Warning:
|
||||
severityMessage = "W: ";
|
||||
break;
|
||||
case eSeverity_Error:
|
||||
severityMessage = "E: ";
|
||||
break;
|
||||
default:
|
||||
severityMessage = "?: ";
|
||||
break;
|
||||
}
|
||||
|
||||
if (eSeverity == eSeverity_Warning)
|
||||
{
|
||||
m_hasWarnings = true;
|
||||
}
|
||||
if (eSeverity == eSeverity_Error)
|
||||
{
|
||||
m_hasErrors = true;
|
||||
}
|
||||
|
||||
if (m_file)
|
||||
{
|
||||
fprintf(m_file, "%s%s\n", severityMessage, text);
|
||||
fflush(m_file);
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_LOGFILE_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_LOGFILE_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "ILogger.h"
|
||||
|
||||
class LogFile
|
||||
: public ILogger
|
||||
{
|
||||
public:
|
||||
LogFile(const char* filename);
|
||||
~LogFile();
|
||||
|
||||
bool IsOpen() const;
|
||||
bool HasWarningsOrErrors() const;
|
||||
|
||||
// ILogger
|
||||
virtual void LogImpl(ESeverity eSeverity, const char* message);
|
||||
|
||||
private:
|
||||
std::FILE* m_file;
|
||||
bool m_hasWarnings;
|
||||
bool m_hasErrors;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_LOGFILE_H
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_MATHHELPERS_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_MATHHELPERS_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <float.h>
|
||||
#if (_M_IX86_FP > 0)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
namespace MathHelpers
|
||||
{
|
||||
#if (_M_IX86_FP > 0)
|
||||
inline int FastRoundFloatTowardZero(float f)
|
||||
{
|
||||
return _mm_cvtt_ss2si(_mm_set_ss(f));
|
||||
}
|
||||
#else
|
||||
inline int FastRoundFloatTowardZero(float f)
|
||||
{
|
||||
return int(f);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
|
||||
inline unsigned int EnableFloatingPointExceptions(unsigned int mask)
|
||||
{
|
||||
_clearfp();
|
||||
unsigned int oldMask;
|
||||
_controlfp_s(&oldMask, 0, 0);
|
||||
unsigned int newMask;
|
||||
_controlfp_s(&newMask, ~mask, _MCW_EM);
|
||||
return ~oldMask;
|
||||
}
|
||||
|
||||
class AutoFloatingPointExceptions
|
||||
{
|
||||
public:
|
||||
AutoFloatingPointExceptions(const unsigned int mask)
|
||||
: m_mask(EnableFloatingPointExceptions(mask))
|
||||
{
|
||||
}
|
||||
|
||||
~AutoFloatingPointExceptions()
|
||||
{
|
||||
EnableFloatingPointExceptions(m_mask);
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int m_mask;
|
||||
};
|
||||
|
||||
#endif //AZ_PLATFORM_WINDOWS
|
||||
}
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_MATHHELPERS_H
|
||||
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include <platform.h>
|
||||
#include "ModuleHelpers.h"
|
||||
|
||||
HMODULE ModuleHelpers::GetCurrentModule(CurrentModuleSpecifier moduleSpecifier)
|
||||
{
|
||||
switch (moduleSpecifier)
|
||||
{
|
||||
case CurrentModuleSpecifier_Executable:
|
||||
return GetModuleHandle(0);
|
||||
|
||||
case CurrentModuleSpecifier_Library:
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
static int dummy;
|
||||
VirtualQuery(&dummy, &mbi, sizeof(mbi));
|
||||
HMODULE instance = reinterpret_cast<HMODULE>(mbi.AllocationBase);
|
||||
return instance;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::basic_string<TCHAR> ModuleHelpers::GetCurrentModulePath(CurrentModuleSpecifier moduleSpecifier)
|
||||
{
|
||||
// Here's a trick that will get you the handle of the module
|
||||
// you're running in without any a-priori knowledge:
|
||||
// http://www.dotnet247.com/247reference/msgs/13/65259.aspx
|
||||
HMODULE instance = GetCurrentModule(moduleSpecifier);
|
||||
TCHAR moduleNameBuffer[MAX_PATH];
|
||||
GetModuleFileName(instance, moduleNameBuffer, sizeof(moduleNameBuffer) / sizeof(moduleNameBuffer[0]));
|
||||
return moduleNameBuffer;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_MODULEHELPERS_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_MODULEHELPERS_H
|
||||
#pragma once
|
||||
|
||||
|
||||
namespace ModuleHelpers
|
||||
{
|
||||
enum CurrentModuleSpecifier
|
||||
{
|
||||
CurrentModuleSpecifier_Executable,
|
||||
CurrentModuleSpecifier_Library
|
||||
};
|
||||
|
||||
HMODULE GetCurrentModule(CurrentModuleSpecifier moduleSpecifier);
|
||||
std::basic_string<TCHAR> GetCurrentModulePath(CurrentModuleSpecifier moduleSpecifier);
|
||||
}
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_MODULEHELPERS_H
|
||||
@@ -1,380 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include <platform.h>
|
||||
#include "PakSystem.h"
|
||||
#include "PathHelpers.h"
|
||||
#include "StringHelpers.h"
|
||||
#include "ZipDir/ZipDir.h"
|
||||
|
||||
#include <zlib.h>
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
|
||||
|
||||
|
||||
PakSystemFile::PakSystemFile()
|
||||
{
|
||||
type = PakSystemFileType_Unknown;
|
||||
file = NULL;
|
||||
zip = NULL;
|
||||
fileEntry = NULL;
|
||||
data = NULL;
|
||||
dataPosition = 0;
|
||||
}
|
||||
|
||||
PakSystem::PakSystem()
|
||||
{
|
||||
}
|
||||
|
||||
PakSystemFile* PakSystem::Open(const char* a_path, const char* a_mode)
|
||||
{
|
||||
string normalPath = a_path;
|
||||
|
||||
string const zipExt = ".zip";
|
||||
bool bZip = StringHelpers::EndsWithIgnoreCase(normalPath, zipExt);
|
||||
|
||||
if (bZip)
|
||||
{
|
||||
// If it's a .zip file, then we'll try to look for a file without .zip extension inside of the .zip file
|
||||
normalPath.erase(normalPath.length() - zipExt.length(), zipExt.length());
|
||||
}
|
||||
|
||||
string zipPath = normalPath + zipExt;
|
||||
string filename = PathHelpers::GetFilename(normalPath);
|
||||
|
||||
if (!normalPath.empty() && normalPath[0] == '@')
|
||||
{
|
||||
// File is inside pak file.
|
||||
int splitter = normalPath.find_first_of("|;,");
|
||||
if (splitter >= 0)
|
||||
{
|
||||
zipPath = normalPath.substr(1, splitter - 1);
|
||||
filename = StringHelpers::MakeLowerCase(normalPath.substr(splitter + 1));
|
||||
bZip = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bZip)
|
||||
{
|
||||
// Try to open the file.
|
||||
FILE* f = nullptr;
|
||||
azfopen(&f, normalPath.c_str(), a_mode);
|
||||
if (f)
|
||||
{
|
||||
std::unique_ptr<PakSystemFile> file(new PakSystemFile());
|
||||
file->type = PakSystemFileType_File;
|
||||
file->file = f;
|
||||
|
||||
return file.release();
|
||||
}
|
||||
}
|
||||
|
||||
// if it's simple and read-only, it's assumed it's read-only
|
||||
unsigned const nFactoryFlags = ZipDir::CacheFactory::FLAGS_DONT_COMPACT | ZipDir::CacheFactory::FLAGS_READ_ONLY;
|
||||
|
||||
bool bFileExists = false;
|
||||
const uint32* decryptionKey = 0; // use default one
|
||||
|
||||
if (bZip)
|
||||
{
|
||||
// a caller asked to open a .zip file. check if the .zip file on disk exist
|
||||
FILE* f = nullptr;
|
||||
azfopen(&f, zipPath.c_str(), "rb");
|
||||
if (f)
|
||||
{
|
||||
fclose(f);
|
||||
bFileExists = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// a caller specified normal file. we already failed to find it on disk,
|
||||
// so the file could be within a .pak file. let's find all 'potential'
|
||||
// pak files and look within these for a matching file
|
||||
|
||||
std::vector<string> foundFileCountainer; // pak files found
|
||||
|
||||
for (string dirToSearch = normalPath;; )
|
||||
{
|
||||
dirToSearch = PathHelpers::GetDirectory(dirToSearch);
|
||||
|
||||
AZ::IO::LocalFileIO localFileIO;
|
||||
localFileIO.FindFiles(dirToSearch.c_str(), "*.pak", [&](const char* filePath) -> bool
|
||||
{
|
||||
const string foundFilename(filePath);
|
||||
if (StringHelpers::EqualsIgnoreCase(PathHelpers::FindExtension(foundFilename), "pak"))
|
||||
{
|
||||
foundFileCountainer.push_back(foundFilename);
|
||||
}
|
||||
return true; // continue iterating
|
||||
});
|
||||
|
||||
if (PathHelpers::GetFilename(dirToSearch).empty())
|
||||
{
|
||||
// We've reached the top of the path
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// iterate through found containers and look for relevant files within them
|
||||
for (int iFile = 0; iFile < foundFileCountainer.size(); ++iFile)
|
||||
{
|
||||
zipPath = foundFileCountainer[ iFile ];
|
||||
string pathToZip = PathHelpers::GetDirectory(zipPath);
|
||||
|
||||
// construct filename by removing path to zip from path to filename
|
||||
string pathToFile = PathHelpers::GetDirectory(string(normalPath));
|
||||
string pureFileName = PathHelpers::GetFilename(string(normalPath));
|
||||
if (pathToFile.length() != pathToZip.length() && pathToZip.length() > 0)
|
||||
{
|
||||
pathToFile = pathToFile.substr(pathToZip.length() + 1);
|
||||
}
|
||||
filename = pathToFile.empty()
|
||||
? pureFileName
|
||||
: pathToFile + "\\" + pureFileName;
|
||||
|
||||
ZipDir::CacheFactory factory(ZipDir::ZD_INIT_FAST, nFactoryFlags);
|
||||
ZipDir::CachePtr testZip = factory.New(zipPath.c_str(), decryptionKey);
|
||||
ZipDir::FileEntry* testFileEntry = (testZip ? testZip->FindFile(filename.c_str()) : 0);
|
||||
|
||||
// break out if we have a testFileEntry, as we've found our first (and best) candidate.
|
||||
if (testFileEntry)
|
||||
{
|
||||
bFileExists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
ZipDir::CacheFactory factory(ZipDir::ZD_INIT_FAST, nFactoryFlags);
|
||||
ZipDir::CachePtr zip = (bFileExists ? factory.New(zipPath.c_str(), decryptionKey) : 0);
|
||||
ZipDir::FileEntry* fileEntry = (zip ? zip->FindFile(filename.c_str()) : 0);
|
||||
|
||||
if (fileEntry)
|
||||
{
|
||||
std::unique_ptr<PakSystemFile> file(new PakSystemFile());
|
||||
file->type = PakSystemFileType_PakFile;
|
||||
file->zip = zip;
|
||||
file->fileEntry = fileEntry;
|
||||
file->data = zip->AllocAndReadFile(file->fileEntry);
|
||||
file->dataPosition = 0;
|
||||
return file.release();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//Extracts archived file to disk without overwriting any files
|
||||
//returns true on success, false on failure (due to potential overwrite or no file
|
||||
//in archive
|
||||
bool PakSystem::ExtractNoOverwrite(const char* fileToExtract, const char* extractToFile)
|
||||
{
|
||||
if (0 == extractToFile)
|
||||
{
|
||||
extractToFile = fileToExtract;
|
||||
}
|
||||
|
||||
//open file using pak system
|
||||
PakSystemFile* fileZip = Open(fileToExtract, "r");
|
||||
if (!fileZip)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to open a writable file
|
||||
FILE* fFileOnDisk = nullptr;
|
||||
azfopen(&fFileOnDisk, extractToFile, "wb");
|
||||
if (!fFileOnDisk)
|
||||
{
|
||||
Close(fileZip);
|
||||
return false;
|
||||
}
|
||||
|
||||
fwrite(fileZip->data, fileZip->fileEntry->desc.lSizeUncompressed, 1, fFileOnDisk);
|
||||
fclose(fFileOnDisk);
|
||||
|
||||
Close(fileZip);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PakSystem::Close(PakSystemFile* file)
|
||||
{
|
||||
if (file)
|
||||
{
|
||||
switch (file->type)
|
||||
{
|
||||
case PakSystemFileType_File:
|
||||
fclose(file->file);
|
||||
break;
|
||||
|
||||
case PakSystemFileType_PakFile:
|
||||
file->zip->Free(file->data);
|
||||
break;
|
||||
}
|
||||
delete file;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int PakSystem::GetLength(PakSystemFile* file) const
|
||||
{
|
||||
if (file)
|
||||
{
|
||||
switch (file->type)
|
||||
{
|
||||
case PakSystemFileType_File:
|
||||
{
|
||||
if (file->file)
|
||||
{
|
||||
long pos = ftell(file->file);
|
||||
fseek(file->file, 0, SEEK_END);
|
||||
int result = ftell(file->file);
|
||||
fseek(file->file, pos, SEEK_SET);
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PakSystemFileType_PakFile:
|
||||
{
|
||||
if (file->fileEntry)
|
||||
{
|
||||
return file->fileEntry->desc.lSizeUncompressed;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int PakSystem::Read(PakSystemFile* file, void* buffer, int size)
|
||||
{
|
||||
int readBytes = 0;
|
||||
|
||||
if (file)
|
||||
{
|
||||
switch (file->type)
|
||||
{
|
||||
case PakSystemFileType_File:
|
||||
{
|
||||
readBytes = fread(buffer, 1, size, file->file);
|
||||
}
|
||||
break;
|
||||
|
||||
case PakSystemFileType_PakFile:
|
||||
{
|
||||
int fileSize = file->fileEntry->desc.lSizeUncompressed;
|
||||
readBytes = (fileSize - file->dataPosition > size ? size : fileSize - file->dataPosition);
|
||||
memcpy(buffer, static_cast<char*>(file->data) + file->dataPosition, readBytes);
|
||||
file->dataPosition += readBytes;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return readBytes;
|
||||
}
|
||||
|
||||
bool PakSystem::EoF(PakSystemFile* file)
|
||||
{
|
||||
bool EoF = true;
|
||||
if (file)
|
||||
{
|
||||
switch (file->type)
|
||||
{
|
||||
case PakSystemFileType_File:
|
||||
{
|
||||
EoF = (0 != feof(file->file));
|
||||
}
|
||||
break;
|
||||
|
||||
case PakSystemFileType_PakFile:
|
||||
{
|
||||
int fileSize = file->fileEntry->desc.lSizeUncompressed;
|
||||
EoF = (file->dataPosition >= fileSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return EoF;
|
||||
}
|
||||
|
||||
PakSystemArchive* PakSystem::OpenArchive(const char* path, size_t fileAlignment, bool encrypted, const uint32 encryptionKey[4])
|
||||
{
|
||||
//unsigned nFactoryFlags = ZipDir::CacheFactory::FLAGS_DONT_COMPACT | ZipDir::CacheFactory::FLAGS_CREATE_NEW;
|
||||
unsigned nFactoryFlags = 0;
|
||||
ZipDir::CacheFactory factory(ZipDir::ZD_INIT_FAST, nFactoryFlags);
|
||||
ZipDir::CacheRWPtr cache = factory.NewRW(path, fileAlignment, encrypted, encryptionKey);
|
||||
PakSystemArchive* archive = (cache ? new PakSystemArchive() : 0);
|
||||
if (archive)
|
||||
{
|
||||
archive->zip = cache;
|
||||
}
|
||||
return archive;
|
||||
}
|
||||
|
||||
void PakSystem::CloseArchive(PakSystemArchive* archive)
|
||||
{
|
||||
if (archive)
|
||||
{
|
||||
archive->zip->Close();
|
||||
delete archive;
|
||||
}
|
||||
}
|
||||
|
||||
void PakSystem::AddToArchive(PakSystemArchive* archive, const char* path, void* data, int size, int64 modTime, int compressionLevel)
|
||||
{
|
||||
int compressionMethod = ZipFile::METHOD_DEFLATE;
|
||||
if (compressionLevel == 0)
|
||||
{
|
||||
compressionMethod = ZipFile::METHOD_STORE;
|
||||
}
|
||||
archive->zip->UpdateFile(path, data, size, compressionMethod, compressionLevel, modTime);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PakSystem::CheckIfFileExist(PakSystemArchive* archive, const char* path, int64 modTime)
|
||||
{
|
||||
assert(archive);
|
||||
|
||||
ZipDir::FileEntry* pFileEntry = archive->zip->FindFile(path);
|
||||
if (pFileEntry)
|
||||
{
|
||||
return pFileEntry->CompareFileTimeNTFS(modTime);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool PakSystem::DeleteFromArchive(PakSystemArchive* archive, const char* path)
|
||||
{
|
||||
ZipDir::ErrorEnum err = archive->zip->RemoveFile(path);
|
||||
return ZipDir::ZD_ERROR_SUCCESS == err;
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_PAKSYSTEM_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_PAKSYSTEM_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "IPakSystem.h"
|
||||
#include "ZipDir/ZipDir.h" // TODO: get rid of thid include
|
||||
|
||||
enum PakSystemFileType
|
||||
{
|
||||
PakSystemFileType_Unknown,
|
||||
PakSystemFileType_File,
|
||||
PakSystemFileType_PakFile
|
||||
};
|
||||
struct PakSystemFile
|
||||
{
|
||||
PakSystemFile();
|
||||
PakSystemFileType type;
|
||||
|
||||
// PakSystemFileType_File
|
||||
FILE* file;
|
||||
|
||||
// PakSystemFileType_PakFile
|
||||
ZipDir::CachePtr zip;
|
||||
ZipDir::FileEntry* fileEntry;
|
||||
void* data;
|
||||
int dataPosition;
|
||||
};
|
||||
|
||||
struct PakSystemArchive
|
||||
{
|
||||
ZipDir::CacheRWPtr zip;
|
||||
};
|
||||
|
||||
class PakSystem
|
||||
: public IPakSystem
|
||||
{
|
||||
public:
|
||||
PakSystem();
|
||||
|
||||
// IPakSystem
|
||||
virtual PakSystemFile* Open(const char* filename, const char* mode);
|
||||
virtual bool ExtractNoOverwrite(const char* filename, const char* extractToFile = 0);
|
||||
virtual void Close(PakSystemFile* file);
|
||||
virtual int GetLength(PakSystemFile* file) const;
|
||||
virtual int Read(PakSystemFile* file, void* buffer, int size);
|
||||
virtual bool EoF(PakSystemFile* file);
|
||||
|
||||
virtual PakSystemArchive* OpenArchive(const char* path, size_t fileAlignment, bool encrypted, const uint32 encryptionKey[4]);
|
||||
virtual void CloseArchive(PakSystemArchive* archive);
|
||||
virtual void AddToArchive(PakSystemArchive* archive, const char* path, void* data, int size, int64 modTime, int compressionLevel);
|
||||
virtual bool DeleteFromArchive(PakSystemArchive* archive, const char* path);
|
||||
virtual bool CheckIfFileExist(PakSystemArchive* archive, const char* path, int64 modTime);
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_PAKSYSTEM_H
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_PAKXMLFILEBUFFERSOURCE_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_PAKXMLFILEBUFFERSOURCE_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "../CryXML/IXMLSerializer.h"
|
||||
#include "IPakSystem.h"
|
||||
|
||||
class PakXmlFileBufferSource
|
||||
: public IXmlBufferSource
|
||||
{
|
||||
public:
|
||||
PakXmlFileBufferSource(IPakSystem* pakSystem, const char* path)
|
||||
: pakSystem(pakSystem)
|
||||
{
|
||||
file = pakSystem->Open(path, "r");
|
||||
}
|
||||
~PakXmlFileBufferSource()
|
||||
{
|
||||
if (file)
|
||||
{
|
||||
pakSystem->Close(file);
|
||||
}
|
||||
}
|
||||
|
||||
virtual int Read(void* buffer, int size) const
|
||||
{
|
||||
return pakSystem->Read(file, buffer, size);
|
||||
};
|
||||
|
||||
IPakSystem* pakSystem;
|
||||
PakSystemFile* file;
|
||||
};
|
||||
|
||||
class PakXmlBufferSource
|
||||
: public IXmlBufferSource
|
||||
{
|
||||
public:
|
||||
PakXmlBufferSource(const char* buffer, size_t length)
|
||||
: position(buffer)
|
||||
, end(buffer + length)
|
||||
{
|
||||
}
|
||||
|
||||
virtual int Read(void* output, int size) const
|
||||
{
|
||||
size_t bytesLeft = end - position;
|
||||
size_t bytesToCopy = size < bytesLeft ? size : bytesLeft;
|
||||
if (bytesToCopy > 0)
|
||||
{
|
||||
memcpy(output, position, bytesToCopy);
|
||||
position += bytesToCopy;
|
||||
}
|
||||
return bytesToCopy;
|
||||
};
|
||||
|
||||
mutable const char* position;
|
||||
const char* end;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_PAKXMLFILEBUFFERSOURCE_H
|
||||
@@ -1,621 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include <platform.h>
|
||||
#include "PathHelpers.h"
|
||||
#include "StringHelpers.h"
|
||||
#include "Util.h"
|
||||
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
|
||||
|
||||
// Returns position of last extension in last name (string::npos if not found)
|
||||
// note: returns string::npos for names starting from '.' and having no
|
||||
// '.' later (for example 'aaa/.ccc', 'a:.abc', '.rc')
|
||||
template <class TS>
|
||||
static inline size_t findExtensionPosition_Tpl(const TS& path)
|
||||
{
|
||||
const size_t dotPos = path.rfind('.');
|
||||
if (dotPos == TS::npos)
|
||||
{
|
||||
return TS::npos;
|
||||
}
|
||||
|
||||
static const typename TS::value_type separators[] = { '\\', '/', ':', 0 };
|
||||
const size_t separatorPos = path.find_last_of(separators);
|
||||
if (separatorPos != TS::npos)
|
||||
{
|
||||
if (separatorPos + 1 >= dotPos)
|
||||
{
|
||||
return TS::npos;
|
||||
}
|
||||
}
|
||||
else if (dotPos == 0)
|
||||
{
|
||||
return TS::npos;
|
||||
}
|
||||
|
||||
return dotPos + 1;
|
||||
}
|
||||
|
||||
static size_t findExtensionPosition(const string& path)
|
||||
{
|
||||
return findExtensionPosition_Tpl(path);
|
||||
}
|
||||
|
||||
static size_t findExtensionPosition(const wstring& path)
|
||||
{
|
||||
return findExtensionPosition_Tpl(path);
|
||||
}
|
||||
|
||||
|
||||
string PathHelpers::FindExtension(const string& path)
|
||||
{
|
||||
const size_t extPos = findExtensionPosition(path);
|
||||
return (extPos == string::npos) ? string() : path.substr(extPos, string::npos);
|
||||
}
|
||||
|
||||
wstring PathHelpers::FindExtension(const wstring& path)
|
||||
{
|
||||
const size_t extPos = findExtensionPosition(path);
|
||||
return (extPos == wstring::npos) ? wstring() : path.substr(extPos, wstring::npos);
|
||||
}
|
||||
|
||||
|
||||
template <class TS>
|
||||
static inline TS ReplaceExtension_Tpl(const TS& path, const TS& newExtension)
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
return TS();
|
||||
}
|
||||
|
||||
if (newExtension.empty())
|
||||
{
|
||||
return PathHelpers::RemoveExtension(path);
|
||||
}
|
||||
|
||||
const typename TS::value_type last = path[path.length() - 1];
|
||||
if ((last == '\\') || (last == '/') || (last == ':') || (last == '.'))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
const size_t extPos = findExtensionPosition(path);
|
||||
static const typename TS::value_type dot[] = { '.', 0 };
|
||||
return ((extPos == TS::npos) ? path + dot : path.substr(0, extPos)) + newExtension;
|
||||
}
|
||||
|
||||
string PathHelpers::ReplaceExtension(const string& path, const string& newExtension)
|
||||
{
|
||||
return ReplaceExtension_Tpl(path, newExtension);
|
||||
}
|
||||
|
||||
wstring PathHelpers::ReplaceExtension(const wstring& path, const wstring& newExtension)
|
||||
{
|
||||
return ReplaceExtension_Tpl(path, newExtension);
|
||||
}
|
||||
|
||||
|
||||
string PathHelpers::RemoveExtension(const string& path)
|
||||
{
|
||||
const size_t extPos = findExtensionPosition(path);
|
||||
return (extPos == string::npos) ? path : path.substr(0, extPos - 1);
|
||||
}
|
||||
|
||||
wstring PathHelpers::RemoveExtension(const wstring& path)
|
||||
{
|
||||
const size_t extPos = findExtensionPosition(path);
|
||||
return (extPos == wstring::npos) ? path : path.substr(0, extPos - 1);
|
||||
}
|
||||
|
||||
|
||||
template <class TS>
|
||||
static inline TS GetDirectory_Tpl(const TS& path)
|
||||
{
|
||||
static const typename TS::value_type separators[] = { '/', '\\', ':', 0 };
|
||||
const size_t pos = path.find_last_of(separators);
|
||||
|
||||
if (pos == TS::npos)
|
||||
{
|
||||
return TS();
|
||||
}
|
||||
|
||||
if (path[pos] == ':' || pos == 0 || path[pos - 1] == ':')
|
||||
{
|
||||
return path.substr(0, pos + 1);
|
||||
}
|
||||
|
||||
// Handle paths like "\\machine"
|
||||
if (pos == 1 && (path[0] == '/' || path[0] == '\\'))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
return path.substr(0, pos);
|
||||
}
|
||||
|
||||
string PathHelpers::GetDirectory(const string& path)
|
||||
{
|
||||
return GetDirectory_Tpl(path);
|
||||
}
|
||||
|
||||
wstring PathHelpers::GetDirectory(const wstring& path)
|
||||
{
|
||||
return GetDirectory_Tpl(path);
|
||||
}
|
||||
|
||||
|
||||
template <class TS>
|
||||
static inline TS GetFilename_Tpl(const TS& path)
|
||||
{
|
||||
static const typename TS::value_type separators[] = { '/', '\\', ':', 0 };
|
||||
const size_t pos = path.find_last_of(separators);
|
||||
|
||||
if (pos == TS::npos)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
// Handle paths like "\\machine"
|
||||
if (pos == 1 && (path[0] == '/' || path[0] == '\\'))
|
||||
{
|
||||
return TS();
|
||||
}
|
||||
|
||||
return path.substr(pos + 1, TS::npos);
|
||||
}
|
||||
|
||||
string PathHelpers::GetFilename(const string& path)
|
||||
{
|
||||
return GetFilename_Tpl(path);
|
||||
}
|
||||
|
||||
wstring PathHelpers::GetFilename(const wstring& path)
|
||||
{
|
||||
return GetFilename_Tpl(path);
|
||||
}
|
||||
|
||||
|
||||
template <class TS>
|
||||
static inline TS AddSeparator_Tpl(const TS& path)
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
return TS();
|
||||
}
|
||||
const typename TS::value_type last = path[path.length() - 1];
|
||||
if (last == '/' || last == '\\' || last == ':')
|
||||
{
|
||||
return path;
|
||||
}
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
static const typename TS::value_type separator[] = { '\\', 0 };
|
||||
#else
|
||||
static const typename TS::value_type separator[] = { '/', 0 };
|
||||
#endif
|
||||
return path + separator;
|
||||
}
|
||||
|
||||
string PathHelpers::AddSeparator(const string& path)
|
||||
{
|
||||
return AddSeparator_Tpl(path);
|
||||
}
|
||||
|
||||
wstring PathHelpers::AddSeparator(const wstring& path)
|
||||
{
|
||||
return AddSeparator_Tpl(path);
|
||||
}
|
||||
|
||||
|
||||
template <class TS>
|
||||
static inline TS RemoveSeparator_Tpl(const TS& path)
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
return TS();
|
||||
}
|
||||
const typename TS::value_type last = path[path.length() - 1];
|
||||
if ((last == '/' || last == '\\') && path.length() > 1 && path[path.length() - 2] != ':')
|
||||
{
|
||||
return path.substr(0, path.length() - 1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
string PathHelpers::RemoveSeparator(const string& path)
|
||||
{
|
||||
return RemoveSeparator_Tpl(path);
|
||||
}
|
||||
|
||||
wstring PathHelpers::RemoveSeparator(const wstring& path)
|
||||
{
|
||||
return RemoveSeparator_Tpl(path);
|
||||
}
|
||||
|
||||
|
||||
template <class TS>
|
||||
static inline TS RemoveDuplicateSeparators_Tpl(const TS& path)
|
||||
{
|
||||
if (path.length() <= 1)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
TS ret;
|
||||
ret.reserve(path.length());
|
||||
|
||||
const typename TS::value_type* p = path.c_str();
|
||||
|
||||
// We start from the second char just to avoid damaging UNC paths with double backslash at the beginning (e.g. "\\Server04\file.txt")
|
||||
ret += *p++;
|
||||
|
||||
while (*p)
|
||||
{
|
||||
ret += *p++;
|
||||
if (p[-1] == '\\' || p[-1] == '/')
|
||||
{
|
||||
while (*p == '\\' || *p == '/')
|
||||
{
|
||||
++p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
string PathHelpers::RemoveDuplicateSeparators(const string& path)
|
||||
{
|
||||
return RemoveDuplicateSeparators_Tpl(path);
|
||||
}
|
||||
|
||||
wstring PathHelpers::RemoveDuplicateSeparators(const wstring& path)
|
||||
{
|
||||
return RemoveDuplicateSeparators_Tpl(path);
|
||||
}
|
||||
|
||||
|
||||
template <class TS>
|
||||
static inline TS Join_Tpl(const TS& path1, const TS& path2)
|
||||
{
|
||||
if (path1.empty())
|
||||
{
|
||||
return path2;
|
||||
}
|
||||
if (path2.empty())
|
||||
{
|
||||
return path1;
|
||||
}
|
||||
|
||||
if (!PathHelpers::IsRelative(path2))
|
||||
{
|
||||
assert(0 && "Join(): path2 is not relative");
|
||||
return TS();
|
||||
}
|
||||
|
||||
const typename TS::value_type last = path1[path1.length() - 1];
|
||||
if (last == '/' || last == '\\' || last == ':')
|
||||
{
|
||||
return path1 + path2;
|
||||
}
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
static const typename TS::value_type separator[] = { '\\', 0 };
|
||||
#else
|
||||
static const typename TS::value_type separator[] = { '/', 0 };
|
||||
#endif
|
||||
return path1 + separator + path2;
|
||||
}
|
||||
|
||||
|
||||
string PathHelpers::Join(const string& path1, const string& path2)
|
||||
{
|
||||
return Join_Tpl(path1, path2);
|
||||
}
|
||||
|
||||
wstring PathHelpers::Join(const wstring& path1, const wstring& path2)
|
||||
{
|
||||
return Join_Tpl(path1, path2);
|
||||
}
|
||||
|
||||
|
||||
template <class TS>
|
||||
static inline bool IsRelative_Tpl(const TS& path)
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return path[0] != '/' && path[0] != '\\' && path.find(':') == TS::npos;
|
||||
}
|
||||
|
||||
bool PathHelpers::IsRelative(const string& path)
|
||||
{
|
||||
return IsRelative_Tpl(path);
|
||||
}
|
||||
|
||||
bool PathHelpers::IsRelative(const wstring& path)
|
||||
{
|
||||
return IsRelative_Tpl(path);
|
||||
}
|
||||
|
||||
|
||||
string PathHelpers::ToUnixPath(const string& path)
|
||||
{
|
||||
return StringHelpers::Replace(path, '\\', '/');
|
||||
}
|
||||
|
||||
wstring PathHelpers::ToUnixPath(const wstring& path)
|
||||
{
|
||||
wstring s(path);
|
||||
std::replace(s.begin(), s.end(), L'\\', L'/');
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
string PathHelpers::ToDosPath(const string& path)
|
||||
{
|
||||
return StringHelpers::Replace(path, '/', '\\');
|
||||
}
|
||||
|
||||
wstring PathHelpers::ToDosPath(const wstring& path)
|
||||
{
|
||||
wstring s(path);
|
||||
std::replace(s.begin(), s.end(), L'/', L'\\');
|
||||
return s;
|
||||
}
|
||||
|
||||
string PathHelpers::ToPlatformPath(const string& path)
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
return ToDosPath(path);
|
||||
#else
|
||||
return ToUnixPath(path);
|
||||
#endif
|
||||
}
|
||||
|
||||
wstring PathHelpers::ToPlatformPath(const wstring& path)
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
return ToDosPath(path);
|
||||
#else
|
||||
return ToUnixPath(path);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
string PathHelpers::GetAsciiPath(const char* pPath)
|
||||
{
|
||||
AZStd::wstring wstr;
|
||||
AZStd::to_wstring(wstr, pPath);
|
||||
return GetAsciiPath(wstr.c_str());
|
||||
}
|
||||
|
||||
string PathHelpers::GetAsciiPath(const wchar_t* pPath)
|
||||
{
|
||||
if (!pPath[0])
|
||||
{
|
||||
return string();
|
||||
}
|
||||
|
||||
wstring w = ToPlatformPath(RemoveSeparator(wstring(pPath)));
|
||||
|
||||
if (StringHelpers::Utf16ContainsAsciiOnly(w.c_str()))
|
||||
{
|
||||
return StringHelpers::ConvertAsciiUtf16ToAscii(w.c_str());
|
||||
}
|
||||
|
||||
// The path is non-ASCII, so let's resort to using short
|
||||
// filenames where needed (short names are always ASCII-only)
|
||||
|
||||
// Long names components
|
||||
std::vector<wstring> p0;
|
||||
StringHelpers::Split(w, wstring(L"\\"), true, p0);
|
||||
|
||||
// find last component that is not in ASCII char set
|
||||
int lastNonAscii;
|
||||
for (lastNonAscii = (int)p0.size() - 1; lastNonAscii >= 0; --lastNonAscii)
|
||||
{
|
||||
if (!StringHelpers::Utf16ContainsAsciiOnly(p0[lastNonAscii].c_str()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(lastNonAscii >= 0);
|
||||
|
||||
string res;
|
||||
res.reserve(w.length());
|
||||
|
||||
w.clear();
|
||||
for (int i = 0; i <= lastNonAscii; ++i)
|
||||
{
|
||||
w.append(p0[i]);
|
||||
if (i < lastNonAscii)
|
||||
{
|
||||
w.push_back('\\');
|
||||
}
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
kBufferLen = AZ_MAX_PATH_LEN
|
||||
};
|
||||
wchar_t bufferWchars[kBufferLen];
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
const int charCount = GetShortPathNameW(w.c_str(), bufferWchars, kBufferLen);
|
||||
#else
|
||||
const int charCount = w.length();
|
||||
wcsncpy(bufferWchars, w.c_str(), kBufferLen);
|
||||
#endif
|
||||
if (charCount <= 0 || charCount >= kBufferLen)
|
||||
{
|
||||
return string();
|
||||
}
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
// Paranoid
|
||||
if (!StringHelpers::Utf16ContainsAsciiOnly(bufferWchars))
|
||||
{
|
||||
assert(0);
|
||||
return string();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Short names components
|
||||
std::vector<wstring> p1;
|
||||
StringHelpers::Split(wstring(bufferWchars), wstring(L"\\"), true, p1);
|
||||
|
||||
for (size_t i = 0; i < (int)p0.size(); ++i)
|
||||
{
|
||||
if (!p0[i].empty())
|
||||
{
|
||||
const wstring& p =
|
||||
(i > lastNonAscii || StringHelpers::Utf16ContainsAsciiOnly(p0[i].c_str()))
|
||||
? p0[i]
|
||||
: p1[i];
|
||||
res.append(StringHelpers::ConvertAsciiUtf16ToAscii(p.c_str()));
|
||||
}
|
||||
if (i + 1 < (int)p0.size())
|
||||
{
|
||||
res.push_back('\\');
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
string PathHelpers::GetAbsoluteAsciiPath(const char* pPath)
|
||||
{
|
||||
char fullPath[AZ_MAX_PATH_LEN];
|
||||
AZ::IO::LocalFileIO localFileIO;
|
||||
|
||||
AZStd::string normalizedPath(pPath);
|
||||
AzFramework::StringFunc::Path::Normalize(normalizedPath);
|
||||
|
||||
localFileIO.ConvertToAbsolutePath(normalizedPath.c_str(), fullPath, AZ_MAX_PATH_LEN);
|
||||
fullPath[sizeof(fullPath) - 1] = '\0';
|
||||
|
||||
AZStd::wstring wstr;
|
||||
AZStd::to_wstring(wstr, fullPath);
|
||||
return GetAsciiPath(wstr.c_str());
|
||||
}
|
||||
|
||||
string PathHelpers::GetAbsoluteAsciiPath(const wchar_t* pPath)
|
||||
{
|
||||
AZStd::string str;
|
||||
AZStd::to_string(str, pPath);
|
||||
|
||||
AzFramework::StringFunc::Path::Normalize(str);
|
||||
|
||||
char fullPath[AZ_MAX_PATH_LEN];
|
||||
AZ::IO::LocalFileIO localFileIO;
|
||||
localFileIO.ConvertToAbsolutePath(str.c_str(), fullPath, AZ_MAX_PATH_LEN);
|
||||
fullPath[sizeof(fullPath) - 1] = '\0';
|
||||
|
||||
AZStd::wstring wstr;
|
||||
AZStd::to_wstring(wstr, fullPath);
|
||||
return GetAsciiPath(wstr.c_str());
|
||||
}
|
||||
|
||||
|
||||
string PathHelpers::GetShortestRelativeAsciiPath(const string& baseFolder, const string& dependentPath)
|
||||
{
|
||||
const string d = GetAbsoluteAsciiPath(dependentPath.c_str());
|
||||
if (d.empty())
|
||||
{
|
||||
return PathHelpers::CanonicalizePath(dependentPath);
|
||||
}
|
||||
|
||||
const string b = GetAbsoluteAsciiPath(baseFolder.c_str());
|
||||
if (b.empty())
|
||||
{
|
||||
return PathHelpers::CanonicalizePath(dependentPath);
|
||||
}
|
||||
|
||||
const string b2 = AddSeparator(b);
|
||||
if (StringHelpers::StartsWithIgnoreCase(d, b2))
|
||||
{
|
||||
const size_t len = d.length() - b2.length();
|
||||
// note: len == 0 is possible in case of "C:\" and "C:\".
|
||||
return (len == 0) ? string(".") : d.substr(b2.length(), len);
|
||||
}
|
||||
|
||||
std::vector<string> p0;
|
||||
StringHelpers::Split(b2, string("\\"), true, p0);
|
||||
std::vector<string> p1;
|
||||
StringHelpers::Split(d, string("\\"), true, p1);
|
||||
|
||||
if (!StringHelpers::EqualsIgnoreCase(p0[0], p1[0]))
|
||||
{
|
||||
// got different drive letters
|
||||
return PathHelpers::CanonicalizePath(dependentPath);
|
||||
}
|
||||
|
||||
if (StringHelpers::EqualsIgnoreCase(d, b))
|
||||
{
|
||||
// exactly same path
|
||||
return string(".");
|
||||
}
|
||||
|
||||
// Search for first non-matching component
|
||||
for (int i = 1; i < (int)p0.size(); ++i)
|
||||
{
|
||||
if (StringHelpers::EqualsIgnoreCase(p0[i], p1[i]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string s;
|
||||
s.reserve(Util::getMax(d.length(), b.length()));
|
||||
for (int j = i; j < (int)p0.size(); ++j)
|
||||
{
|
||||
if (!p0[j].empty())
|
||||
{
|
||||
s.append("..\\");
|
||||
}
|
||||
}
|
||||
for (int j = i; j < (int)p1.size(); ++j)
|
||||
{
|
||||
s.append(p1[j]);
|
||||
if (j + 1 < (int)p1.size())
|
||||
{
|
||||
s.push_back('\\');
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
return string();
|
||||
}
|
||||
|
||||
|
||||
string PathHelpers::CanonicalizePath(const string& path)
|
||||
{
|
||||
string result = RemoveSeparator(path);
|
||||
// remove .\ or ./ at the path beginning.
|
||||
if (result.length() > 2)
|
||||
{
|
||||
if (result[0] == '.' && (result[1] == '\\' || result[1] == '/'))
|
||||
{
|
||||
result = result.substr(2);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_PATHHELPERS_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_PATHHELPERS_H
|
||||
#pragma once
|
||||
|
||||
#include <CryString.h>
|
||||
|
||||
namespace PathHelpers
|
||||
{
|
||||
// checks to see what the extension is in a string path
|
||||
// returns the extension if found or an empty string if not found
|
||||
string FindExtension(const string& path);
|
||||
wstring FindExtension(const wstring& path);
|
||||
|
||||
// replace an extension of a string path with a new specified extension
|
||||
// returns a string with the replaced extension or the original string if unable to replace the extension
|
||||
string ReplaceExtension(const string& path, const string& newExtension);
|
||||
wstring ReplaceExtension(const wstring& path, const wstring& newExtension);
|
||||
|
||||
// removes the extension of a specified string path
|
||||
// returns a string with the extension removed or the original string if no extension was found
|
||||
string RemoveExtension(const string& path);
|
||||
wstring RemoveExtension(const wstring& path);
|
||||
|
||||
// "abc/def/ghi" -> "abc/def"
|
||||
// "abc/def/ghi/" -> "abc/def/ghi"
|
||||
// "/" -> "/"
|
||||
// gets the directory path out of a specified string path
|
||||
// returns a string of the directory path
|
||||
string GetDirectory(const string& path);
|
||||
wstring GetDirectory(const wstring& path);
|
||||
|
||||
// gets the file name out of a specified string path
|
||||
// returns a string of the file name
|
||||
string GetFilename(const string& path);
|
||||
wstring GetFilename(const wstring& path);
|
||||
|
||||
// add a backslash to a specified path if it doesn't already have a separator
|
||||
// returns a path with the appended backslash unless there was already a separator
|
||||
string AddSeparator(const string& path);
|
||||
wstring AddSeparator(const wstring& path);
|
||||
|
||||
// removes a forward slash or backslash from the end of a specified string path if found
|
||||
// returns a string with the separator removed
|
||||
string RemoveSeparator(const string& path);
|
||||
wstring RemoveSeparator(const wstring& path);
|
||||
|
||||
// removes extra forward slashes and backslashes if they're contained within the string path
|
||||
// returns a string with the extra forward slashes and backslashes removed
|
||||
string RemoveDuplicateSeparators(const string& path);
|
||||
wstring RemoveDuplicateSeparators(const wstring& path);
|
||||
|
||||
// It's not allowed to pass an absolute path in path2.
|
||||
// Join(GetDirectory(fname), GetFilename(fname)) returns fname.
|
||||
// merges two string paths together into one
|
||||
// returns the merged string paths
|
||||
string Join(const string& path1, const string& path2);
|
||||
wstring Join(const wstring& path1, const wstring& path2);
|
||||
|
||||
// checks to see if the path is a relative path
|
||||
// returns true if it is or false if it is not
|
||||
bool IsRelative(const string& path);
|
||||
bool IsRelative(const wstring& path);
|
||||
|
||||
// converts a string path to a unix path format
|
||||
// returns the path in unix format
|
||||
string ToUnixPath(const string& path);
|
||||
wstring ToUnixPath(const wstring& path);
|
||||
|
||||
// converts a string path to a dos path format
|
||||
// returns the path in dos format
|
||||
string ToDosPath(const string& path);
|
||||
wstring ToDosPath(const wstring& path);
|
||||
|
||||
// converts a string to the platform's path format.
|
||||
// returns the path in the platform's path format.
|
||||
string ToPlatformPath(const string& path);
|
||||
wstring ToPlatformPath(const wstring& path);
|
||||
|
||||
// char* pPath: in ASCII or UTF-8 encoding
|
||||
// wchar_t* pPath: in UTF-16 encoding
|
||||
// Non-ASCII components of pPath (everything from &pPath[0] to last non-ASCII
|
||||
// part, inclusively) should exist on disk, otherwise an empty string is returned.
|
||||
string GetAsciiPath(const char* pPath);
|
||||
string GetAsciiPath(const wchar_t* pPath);
|
||||
|
||||
// pPath passed should be in ASCII or UTF-8 encoding
|
||||
string GetAbsoluteAsciiPath(const char* pPath);
|
||||
// pPath passed should be in UTF-16 encoding
|
||||
string GetAbsoluteAsciiPath(const wchar_t* pPath);
|
||||
|
||||
// baseFolder and dependentPath passed should be in ASCII or UTF-8 encoding
|
||||
string GetShortestRelativeAsciiPath(const string& baseFolder, const string& dependentPath);
|
||||
|
||||
string CanonicalizePath(const string& path);
|
||||
}
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_PATHHELPERS_H
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define AZ_TRAIT_CRYCOMMONTOOLS_FSEEK(file, offset, s) fseek(file, offset, s)
|
||||
#define AZ_TRAIT_CRYCOMMONTOOLS_FTELL(file) ftell(file)
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <../Common/UnixLike/ZipDir/ZipDir_Traits_UnixLike.h>
|
||||
|
||||
#define AZ_TRAIT_CRYCOMMONTOOLS_PACK_1 0
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <../Common/UnixLike/ZipDir/ZipDir_Traits_UnixLike.h>
|
||||
#include <ZipDir/ZipDir_Traits_Linux.h>
|
||||
@@ -1,16 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
ZipDir/ZipDir_Traits_Platform.h
|
||||
ZipDir/ZipDir_Traits_Linux.h
|
||||
../Common/UnixLike/ZipDir/ZipDir_Traits_UnixLike.h
|
||||
)
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <../Common/UnixLike/ZipDir/ZipDir_Traits_UnixLike.h>
|
||||
|
||||
#define AZ_TRAIT_CRYCOMMONTOOLS_PACK_1 1
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <ZipDir/ZipDir_Traits_Mac.h>
|
||||
@@ -1,16 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
ZipDir/ZipDir_Traits_Platform.h
|
||||
ZipDir/ZipDir_Traits_Mac.h
|
||||
../Common/UnixLike/ZipDir/ZipDir_Traits_UnixLike.h
|
||||
)
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <ZipDir/ZipDir_Traits_Windows.h>
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define AZ_TRAIT_CRYCOMMONTOOLS_FSEEK(file, offset, s) _fseeki64(file, (__int64)offset, s)
|
||||
#define AZ_TRAIT_CRYCOMMONTOOLS_FTELL(file) (size_t)_ftelli64(file)
|
||||
#define AZ_TRAIT_CRYCOMMONTOOLS_PACK_1 1
|
||||
@@ -1,15 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
ZipDir/ZipDir_Traits_Platform.h
|
||||
ZipDir/ZipDir_Traits_Windows.h
|
||||
)
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_PROGRESSRANGE_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_PROGRESSRANGE_H
|
||||
#pragma once
|
||||
|
||||
|
||||
class ProgressRange
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
ProgressRange(T* object, void (T::* setter)(float progress))
|
||||
: m_target(new MethodTarget<T>(object, setter))
|
||||
, m_progress(0.0f)
|
||||
, m_start(0.0f)
|
||||
, m_scale(1.0f)
|
||||
{
|
||||
m_target->Set(m_start);
|
||||
}
|
||||
|
||||
ProgressRange(ProgressRange& parent, float scale)
|
||||
: m_target(new ParentRangeTarget(parent))
|
||||
, m_progress(0.0f)
|
||||
, m_start(parent.m_progress)
|
||||
, m_scale(scale)
|
||||
{
|
||||
m_target->Set(m_start);
|
||||
}
|
||||
|
||||
~ProgressRange()
|
||||
{
|
||||
m_target->Set(m_start + m_scale);
|
||||
delete m_target;
|
||||
}
|
||||
|
||||
void SetProgress(float progress)
|
||||
{
|
||||
assert(progress > -0.01f && progress < 1.1f);
|
||||
m_progress = progress;
|
||||
m_target->Set(m_start + m_scale * progress);
|
||||
}
|
||||
|
||||
private:
|
||||
struct ITarget
|
||||
{
|
||||
virtual ~ITarget() {}
|
||||
virtual void Set(float progress) = 0;
|
||||
};
|
||||
|
||||
struct ParentRangeTarget
|
||||
: public ITarget
|
||||
{
|
||||
ParentRangeTarget(ProgressRange& range)
|
||||
: range(range) {}
|
||||
virtual void Set(float progress) {range.SetProgress(progress); }
|
||||
ProgressRange& range;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct MethodTarget
|
||||
: public ITarget
|
||||
{
|
||||
typedef void (T::* Setter)(float progress);
|
||||
MethodTarget(T* object, Setter setter)
|
||||
: object(object)
|
||||
, setter(setter) {}
|
||||
virtual void Set(float progress) {(object->*setter)(progress); }
|
||||
T* object;
|
||||
Setter setter;
|
||||
};
|
||||
|
||||
ITarget* m_target;
|
||||
float m_progress;
|
||||
float m_start;
|
||||
float m_scale;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_PROGRESSRANGE_H
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include <platform.h>
|
||||
#include "PropertyHelpers.h"
|
||||
#include "StringHelpers.h"
|
||||
|
||||
|
||||
bool PropertyHelpers::GetPropertyValue(const string& a_propertiesString, const char* a_propertyName, string& a_value)
|
||||
{
|
||||
if ((a_propertyName == 0) || (a_propertyName[0] == 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* lineStart = a_propertiesString.c_str();
|
||||
|
||||
while (*lineStart)
|
||||
{
|
||||
string key;
|
||||
string value;
|
||||
|
||||
const size_t lineEndPosition = strcspn(lineStart, "\n");
|
||||
const size_t equalPosition = strcspn(lineStart, "=");
|
||||
|
||||
if (equalPosition < lineEndPosition)
|
||||
{
|
||||
key = string(lineStart, equalPosition);
|
||||
value = string(lineStart + equalPosition + 1, lineEndPosition - equalPosition - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
key = string(lineStart, lineEndPosition);
|
||||
value = "";
|
||||
}
|
||||
|
||||
key = StringHelpers::Trim(key);
|
||||
|
||||
if (_stricmp(key.c_str(), a_propertyName) == 0)
|
||||
{
|
||||
a_value = StringHelpers::Trim(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
lineStart += lineEndPosition;
|
||||
if (*lineStart)
|
||||
{
|
||||
++lineStart;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void PropertyHelpers::SetPropertyValue(string& a_propertiesString, const char* a_propertyName, const char* a_value)
|
||||
{
|
||||
if ((a_propertyName == 0) || (a_propertyName[0] == 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const string newValue = StringHelpers::Trim(string(a_value));
|
||||
|
||||
const char* lineStart = a_propertiesString.c_str();
|
||||
|
||||
while (*lineStart)
|
||||
{
|
||||
const size_t lineEndPosition = strcspn(lineStart, "\n");
|
||||
const size_t equalPosition = strcspn(lineStart, "=");
|
||||
|
||||
const string key = StringHelpers::Trim(string(lineStart, ((equalPosition < lineEndPosition) ? equalPosition : lineEndPosition)));
|
||||
|
||||
if (_stricmp(key.c_str(), a_propertyName) == 0)
|
||||
{
|
||||
const size_t prefixSz = lineStart - a_propertiesString.c_str();
|
||||
const size_t expressionSz = lineEndPosition;
|
||||
|
||||
if (newValue.empty())
|
||||
{
|
||||
a_propertiesString = a_propertiesString.substr(0, prefixSz) + string(a_propertyName) + a_propertiesString.substr(prefixSz + expressionSz, string::npos);
|
||||
}
|
||||
else
|
||||
{
|
||||
a_propertiesString = a_propertiesString.substr(0, prefixSz) + string(a_propertyName) + string("=") + newValue + a_propertiesString.substr(prefixSz + expressionSz, string::npos);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
lineStart += lineEndPosition;
|
||||
if (*lineStart)
|
||||
{
|
||||
++lineStart;
|
||||
}
|
||||
}
|
||||
|
||||
if (a_propertiesString.empty() || (a_propertiesString[a_propertiesString.size() - 1] != '\n'))
|
||||
{
|
||||
a_propertiesString += string("\r\n");
|
||||
}
|
||||
|
||||
if (newValue.empty())
|
||||
{
|
||||
a_propertiesString += string(a_propertyName);
|
||||
}
|
||||
else
|
||||
{
|
||||
a_propertiesString += string(a_propertyName) + string("=") + newValue;
|
||||
}
|
||||
}
|
||||
|
||||
bool PropertyHelpers::HasProperty(const string& a_propertiesString, const char* a_propertyName)
|
||||
{
|
||||
string value;
|
||||
return PropertyHelpers::GetPropertyValue(a_propertiesString, a_propertyName, value);
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_PROPERTYHELPERS_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_PROPERTYHELPERS_H
|
||||
#pragma once
|
||||
|
||||
|
||||
namespace PropertyHelpers
|
||||
{
|
||||
bool GetPropertyValue(const string& propertiesString, const char* propertyName, string& value);
|
||||
void SetPropertyValue(string& a_propertiesString, const char* propertyName, const char* value);
|
||||
bool HasProperty(const string& propertiesString, const char* propertyName);
|
||||
}
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_PROPERTYHELPERS_H
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include <platform.h>
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_STLHELPERS_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_STLHELPERS_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace STLHelpers
|
||||
{
|
||||
template <class Type>
|
||||
inline const char* constchar_cast(const Type& type)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const char* constchar_cast(const std::string& type)
|
||||
{
|
||||
return type.c_str();
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
struct less_strcmp
|
||||
{
|
||||
bool operator()(const Type& left, const Type& right) const
|
||||
{
|
||||
return strcmp(constchar_cast(left), constchar_cast(right)) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Type>
|
||||
struct less_stricmp
|
||||
{
|
||||
bool operator()(const Type& left, const Type& right) const
|
||||
{
|
||||
return _stricmp(constchar_cast(left), constchar_cast(right)) < 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_STLHELPERS_H
|
||||
@@ -1,508 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#pragma once
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_SIMPLEBITMAP_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_SIMPLEBITMAP_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <vector> // STL vector
|
||||
#include "platform.h" // uint32
|
||||
#include "Cry_Math.h" // uint32
|
||||
#include "Util.h" // getMin()
|
||||
|
||||
enum EImageFilteringMode
|
||||
{
|
||||
eifm2DBorder = 0,
|
||||
eifmCubemapFilter = 1,
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
enum ECubeFace
|
||||
{
|
||||
ecfPosX = 0,
|
||||
ecfNegX = 1,
|
||||
ecfPosY = 2,
|
||||
ecfNegY = 3,
|
||||
ecfPosZ = 4,
|
||||
ecfNegZ = 5,
|
||||
ecfUnknown = -1,
|
||||
};
|
||||
|
||||
struct JumpEntry
|
||||
{
|
||||
ECubeFace face;
|
||||
int rot;
|
||||
};
|
||||
|
||||
static const JumpEntry XJmpTable[] =
|
||||
{
|
||||
{ecfNegZ, 0}, {ecfPosZ, 2}, // ecfPosXa
|
||||
{ecfPosZ, 0}, {ecfNegZ, 2}, // ecfNegXa
|
||||
{ecfPosX, 1}, {ecfNegX, 3}, // ecfPosYa
|
||||
{ecfPosX, 3}, {ecfNegX, 1}, // ecfNegYa
|
||||
{ecfPosX, 0}, {ecfNegX, 0}, // ecfPosZa
|
||||
{ecfPosX, 2}, {ecfNegX, 2} // ecfNegZa
|
||||
};
|
||||
|
||||
static const JumpEntry YJmpTable[] =
|
||||
{
|
||||
{ecfPosY, 3}, {ecfNegY, 1}, // ecfPosXa
|
||||
{ecfPosY, 1}, {ecfNegY, 3}, // ecfNegXa
|
||||
{ecfNegZ, 2}, {ecfPosZ, 0}, // ecfPosYa
|
||||
{ecfPosZ, 0}, {ecfNegZ, 2}, // ecfNegYa
|
||||
{ecfNegY, 0}, {ecfPosY, 2}, // ecfPosZa
|
||||
{ecfNegY, 2}, {ecfPosY, 0} // ecfNegZa
|
||||
};
|
||||
}
|
||||
|
||||
//! memory block used as bitmap
|
||||
//! if you might need mipmaps please consider using ImageObject instead
|
||||
template <class RasterElement>
|
||||
class CSimpleBitmap
|
||||
{
|
||||
public:
|
||||
|
||||
CSimpleBitmap()
|
||||
: m_dwWidth(0)
|
||||
, m_dwHeight(0)
|
||||
{
|
||||
}
|
||||
|
||||
~CSimpleBitmap()
|
||||
{
|
||||
}
|
||||
|
||||
// copy constructor
|
||||
CSimpleBitmap(const CSimpleBitmap<RasterElement>& rhs)
|
||||
: m_dwWidth(0)
|
||||
, m_dwHeight(0)
|
||||
{
|
||||
*this = rhs; // call assignment operator
|
||||
}
|
||||
|
||||
// assignment operator
|
||||
CSimpleBitmap<RasterElement>& operator=(const CSimpleBitmap<RasterElement>& rhs)
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
m_data = rhs.m_data;
|
||||
m_dwWidth = rhs.m_dwWidth;
|
||||
m_dwHeight = rhs.m_dwHeight;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! free all the memory resources
|
||||
void FreeData()
|
||||
{
|
||||
m_data = std::vector<RasterElement>();
|
||||
m_dwWidth = 0;
|
||||
m_dwHeight = 0;
|
||||
}
|
||||
|
||||
//! /return true=success, false=failed because of low memory
|
||||
bool SetSize(const uint32 indwWidth, const uint32 indwHeight)
|
||||
{
|
||||
if (m_dwWidth * m_dwHeight != indwWidth * indwHeight)
|
||||
{
|
||||
FreeData();
|
||||
m_data.resize(indwWidth * indwHeight);
|
||||
m_dwWidth = indwWidth;
|
||||
m_dwHeight = indwHeight;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
ECubeFace JumpX(const ECubeFace srcFace, const bool isdXPos, int* rotCoords) const
|
||||
{
|
||||
int index = (int)srcFace * 2 + (isdXPos ? 0 : 1);
|
||||
assert(index < sizeof(XJmpTable));
|
||||
const JumpEntry& jmp = XJmpTable[index];
|
||||
(*rotCoords) += jmp.rot;
|
||||
return jmp.face;
|
||||
}
|
||||
|
||||
ECubeFace JumpY(const ECubeFace srcFace, const bool isdYPos, int* rotCoords) const
|
||||
{
|
||||
int index = (int)srcFace * 2 + (isdYPos ? 0 : 1);
|
||||
assert(index < sizeof(YJmpTable));
|
||||
const JumpEntry& jmp = YJmpTable[index];
|
||||
(*rotCoords) += jmp.rot;
|
||||
return jmp.face;
|
||||
}
|
||||
|
||||
// table that shows to which face we jump
|
||||
ECubeFace JumpTable(const ECubeFace srcFace, int isdXPos, int isdYPos, int* rotCoords) const
|
||||
{
|
||||
if (isdXPos != 0) // recursive jump until dx==0
|
||||
{
|
||||
int newSwap = 0;
|
||||
ECubeFace newFace = JumpX(srcFace, isdXPos > 0, &newSwap);
|
||||
(*rotCoords) += newSwap;
|
||||
isdXPos -= ((isdXPos > 0) ? 1 : -1);
|
||||
RotateCoord(&isdXPos, &isdYPos, newSwap);
|
||||
return JumpTable(newFace, isdXPos, isdYPos, rotCoords);
|
||||
}
|
||||
if (isdYPos != 0) // recursive jump until dy==0
|
||||
{
|
||||
int newSwap = 0;
|
||||
ECubeFace newFace = JumpY(srcFace, isdYPos > 0, &newSwap);
|
||||
(*rotCoords) += newSwap;
|
||||
isdYPos -= ((isdYPos > 0) ? 1 : -1);
|
||||
RotateCoord(&isdXPos, &isdYPos, newSwap);
|
||||
return JumpTable(newFace, isdXPos, isdYPos, rotCoords);
|
||||
}
|
||||
assert(isdXPos == 0 && isdYPos == 0);
|
||||
return srcFace;
|
||||
}
|
||||
|
||||
void RotateCoord(int* x, int* y, int mode) const
|
||||
{
|
||||
if (mode != 0)
|
||||
{
|
||||
if (mode == 2) // 180 degrees
|
||||
{
|
||||
(*x) = -(*x);
|
||||
(*y) = -(*y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mode == 1) // 90 dergees
|
||||
{
|
||||
int tmp = (*y);
|
||||
(*y) = (*x);
|
||||
(*x) = -tmp;
|
||||
}
|
||||
else // 270 degrees
|
||||
{
|
||||
assert(mode == 3);
|
||||
int tmp = (*y);
|
||||
(*y) = -(*x);
|
||||
(*x) = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
//! works only within the Bitmap for filter kernels
|
||||
//! /param inX 0..m_dwWidth-1 or the method returns false
|
||||
//! /param inY 0..m_dwHeight-1 or the method returns false
|
||||
//! /param outValue
|
||||
//! /return pointer to the raster element value if position was in the bitmap, NULL otherwise
|
||||
const RasterElement* GetForFiltering_2D(const int inX, const int inY) const
|
||||
{
|
||||
return Get(inX, inY);
|
||||
}
|
||||
|
||||
//! works only within the Bitmap for filter kernels
|
||||
//! /param inX 0..m_dwWidth-1 or the method returns false
|
||||
//! /param inY 0..m_dwHeight-1 or the method returns false
|
||||
//! /param outValue
|
||||
//! /return pointer to the raster element value if position was in the bitmap, NULL otherwise
|
||||
const RasterElement* GetForFiltering_Cubemap(const int inX, const int inY, const int srcX, const int srcY) const
|
||||
{
|
||||
if (m_data.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(m_dwWidth == m_dwHeight * 6);
|
||||
assert(srcX >= 0 && srcX < m_dwWidth);
|
||||
assert(srcY >= 0 && srcY < m_dwHeight);
|
||||
|
||||
const int sideSize = m_dwHeight;
|
||||
|
||||
ECubeFace srcFace = (ECubeFace)(srcX / sideSize);
|
||||
|
||||
if (inX >= 0 && inX < m_dwWidth && inY >= 0 && inY < m_dwHeight) // if we're inside the cubemap
|
||||
{
|
||||
ECubeFace destFace = (ECubeFace)(inX / sideSize);
|
||||
if (destFace == srcFace) // we have the same face as src texel
|
||||
{
|
||||
return &m_data[inY * m_dwWidth + inX];
|
||||
}
|
||||
}
|
||||
const int halfSideSize = Util::getMax(1, sideSize / 2);
|
||||
|
||||
// ternary logic
|
||||
const int isdXPositive = int(floorf((float)inX / sideSize) - floorf((float)srcX / sideSize));
|
||||
const int isdYPositive = int(floorf((float)inY / sideSize) - floorf((float)srcY / sideSize));
|
||||
//if(isdXPositive==0&&isdYPositive<0&&srcFace==ecfPosY)
|
||||
//{
|
||||
// int tmp = 0;
|
||||
//}
|
||||
assert(isdXPositive != 0 || isdYPositive != 0);
|
||||
int rotCoords = 0; // quadrants to rotate coords
|
||||
ECubeFace destFace = JumpTable(srcFace, isdXPositive, isdYPositive, &rotCoords);
|
||||
rotCoords = ((rotCoords % 4) + 4) % 4;
|
||||
int destX = inX - srcFace * sideSize;
|
||||
int destY = inY;
|
||||
|
||||
// rotate coords
|
||||
destX -= halfSideSize; // center coords
|
||||
destY -= halfSideSize;
|
||||
RotateCoord(&destX, &destY, rotCoords);
|
||||
destX += halfSideSize; // shift back
|
||||
destY += halfSideSize;
|
||||
|
||||
destX = ((destX + sideSize) % sideSize + sideSize) % sideSize; // tile in the face
|
||||
destY = ((destY + sideSize) % sideSize + sideSize) % sideSize;
|
||||
|
||||
destX = Util::getMin(destX, sideSize - 1);
|
||||
destY = Util::getMin(destY, sideSize - 1);
|
||||
destX += sideSize * destFace;
|
||||
|
||||
assert(destX < m_dwWidth);
|
||||
assert((ECubeFace)(destX / sideSize) == destFace);
|
||||
|
||||
return &m_data[destY * m_dwWidth + destX];
|
||||
}
|
||||
|
||||
const RasterElement* GetForFiltering(const Vec3& inDir) const
|
||||
{
|
||||
Vec3 vcAbsDir(fabsf(inDir.x), fabsf(inDir.y), fabsf(inDir.z));
|
||||
ECubeFace face;
|
||||
int rotQuadrant = 0;
|
||||
Vec2 texCoord;
|
||||
if (vcAbsDir.x > vcAbsDir.y && vcAbsDir.x > vcAbsDir.z)
|
||||
{
|
||||
if (inDir.x > 0)
|
||||
{
|
||||
rotQuadrant = 3;
|
||||
face = ecfPosX;
|
||||
}
|
||||
else
|
||||
{
|
||||
rotQuadrant = 1;
|
||||
face = ecfNegX;
|
||||
}
|
||||
texCoord = Vec2(inDir.y, inDir.z) / vcAbsDir.x;
|
||||
}
|
||||
else if (vcAbsDir.y > vcAbsDir.x && vcAbsDir.y > vcAbsDir.z)
|
||||
{
|
||||
if (inDir.y > 0)
|
||||
{
|
||||
rotQuadrant = 2;
|
||||
face = ecfPosY;
|
||||
}
|
||||
else
|
||||
{
|
||||
rotQuadrant = 0;
|
||||
face = ecfNegY;
|
||||
}
|
||||
texCoord = Vec2(inDir.x, inDir.z) / vcAbsDir.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(vcAbsDir.z >= vcAbsDir.x && vcAbsDir.z >= vcAbsDir.y);
|
||||
if (inDir.z > 0)
|
||||
{
|
||||
rotQuadrant = 1;
|
||||
face = ecfPosZ;
|
||||
}
|
||||
else
|
||||
{
|
||||
rotQuadrant = 3;
|
||||
face = ecfNegZ;
|
||||
}
|
||||
texCoord = Vec2(inDir.x, inDir.y) / vcAbsDir.z;
|
||||
}
|
||||
|
||||
texCoord = texCoord * .5f + Vec2(.5f, .5f);
|
||||
assert(texCoord.x <= 1.f && texCoord.x >= 0);
|
||||
assert(texCoord.y <= 1.f && texCoord.y >= 0);
|
||||
|
||||
Vec2i texelPos(texCoord.x * (m_dwHeight - 1), texCoord.y * (m_dwHeight - 1));
|
||||
|
||||
texelPos.x += face * m_dwHeight; // plus face
|
||||
return &m_data[texelPos.y * m_dwWidth + texelPos.x];
|
||||
}
|
||||
|
||||
//! works only within the Bitmap
|
||||
//! /param inX 0..m_dwWidth-1 or the method returns false
|
||||
//! /param inY 0..m_dwHeight-1 or the method returns false
|
||||
//! /param outValue
|
||||
//! /return pointer to raster element value if position was in the bitmap, NULL otherwise
|
||||
const RasterElement* Get(const uint32 inX, const uint32 inY) const
|
||||
{
|
||||
if (m_data.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (inX >= m_dwWidth || inY >= m_dwHeight)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return &m_data[inY * m_dwWidth + inX];
|
||||
}
|
||||
|
||||
|
||||
//! bilinear, works only well within 0..1
|
||||
bool GetFiltered(const float infX, const float infY, RasterElement& outValue) const
|
||||
{
|
||||
float fIX = floorf(infX), fIY = floorf(infY);
|
||||
float fFX = infX - fIX, fFY = infY - fIY;
|
||||
int iXa = (int)fIX, iYa = (int)fIY;
|
||||
int iXb = iXa + 1, iYb = iYa + 1;
|
||||
|
||||
if (iXb == m_dwWidth)
|
||||
{
|
||||
iXb = 0;
|
||||
}
|
||||
|
||||
if (iYb == m_dwHeight)
|
||||
{
|
||||
iYb = 0;
|
||||
}
|
||||
|
||||
const RasterElement* p[4];
|
||||
|
||||
if ((p[0] = Get(iXa, iYa)) && (p[1] = Get(iXb, iYa)) && (p[2] = Get(iXa, iYb)) && (p[3] = Get(iXb, iYb)))
|
||||
{
|
||||
outValue =
|
||||
(*p[0]) * ((1.0f - fFX) * (1.0f - fFY)) + // left top
|
||||
(*p[1]) * ((fFX) * (1.0f - fFY)) + // right top
|
||||
(*p[2]) * ((1.0f - fFX) * (fFY)) + // left bottom
|
||||
(*p[3]) * ((fFX) * (fFY)); // right bottom
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//! works only within the Bitmap
|
||||
//! /param inX 0..m_dwWidth-1 or the method returns false
|
||||
//! /param inY 0..m_dwHeight-1 or the method returns false
|
||||
const RasterElement& GetRef(const uint32 inX, const uint32 inY) const
|
||||
{
|
||||
assert(!m_data.empty());
|
||||
assert(inX < m_dwWidth && inY < m_dwHeight);
|
||||
return m_data[inY * m_dwWidth + inX];
|
||||
}
|
||||
|
||||
//! works only within the Bitmap
|
||||
//! /param inX 0..m_dwWidth-1 or the method returns false
|
||||
//! /param inY 0..m_dwHeight-1 or the method returns false
|
||||
RasterElement& GetRef(const uint32 inX, const uint32 inY)
|
||||
{
|
||||
assert(!m_data.empty());
|
||||
assert(inX < m_dwWidth && inY < m_dwHeight);
|
||||
return m_data[inY * m_dwWidth + inX];
|
||||
}
|
||||
|
||||
//! works even outside of the Bitmap (tiled)
|
||||
//! /param inX 0..m_dwWidth-1 or the method returns false
|
||||
//! /param inY 0..m_dwHeight-1 or the method returns false
|
||||
RasterElement& GetTiledRef(const uint32 inX, const uint32 inY)
|
||||
{
|
||||
assert(!m_data.empty());
|
||||
const uint32 x = inX % m_dwWidth;
|
||||
const uint32 y = inY % m_dwHeight;
|
||||
return m_data[y * m_dwWidth + x];
|
||||
}
|
||||
|
||||
//! works only within the Bitmap
|
||||
//! /param inX 0..m_dwWidth-1 or the method returns false
|
||||
//! /param inY 0..m_dwHeight-1 or the method returns false
|
||||
//! /param inValue
|
||||
bool Set(const uint32 inX, const uint32 inY, const RasterElement& inValue)
|
||||
{
|
||||
if (m_data.empty())
|
||||
{
|
||||
assert(!m_data.empty());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (inX >= m_dwWidth || inY >= m_dwHeight)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_data[inY * m_dwWidth + inX] = inValue;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 GetWidth() const
|
||||
{
|
||||
return m_dwWidth;
|
||||
}
|
||||
|
||||
uint32 GetHeight() const
|
||||
{
|
||||
return m_dwHeight;
|
||||
}
|
||||
|
||||
// Returns size of one line in bytes
|
||||
size_t GetPitch() const
|
||||
{
|
||||
return m_dwWidth * sizeof(RasterElement);
|
||||
}
|
||||
|
||||
uint32 GetBitmapSizeInBytes() const
|
||||
{
|
||||
return m_dwWidth * m_dwHeight * sizeof(RasterElement);
|
||||
}
|
||||
|
||||
//! /return could be 0 if the pixel is outside the bitmap
|
||||
const RasterElement* GetPointer(const uint32 inX = 0, const uint32 inY = 0) const
|
||||
{
|
||||
if (inX >= m_dwWidth || inY >= m_dwHeight)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return &m_data[inY * m_dwWidth + inX];
|
||||
}
|
||||
|
||||
//! /return could be 0 if the pixel is outside the bitmap
|
||||
RasterElement* GetPointer(const uint32 inX = 0, const uint32 inY = 0)
|
||||
{
|
||||
if (inX >= m_dwWidth || inY >= m_dwHeight)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return &m_data[inY * m_dwWidth + inX];
|
||||
}
|
||||
|
||||
void Fill(const RasterElement& inValue)
|
||||
{
|
||||
const uint32 n = m_dwHeight * m_dwWidth;
|
||||
for (uint32 i = 0; i < n; ++i)
|
||||
{
|
||||
m_data[i] = inValue;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return !m_data.empty();
|
||||
}
|
||||
|
||||
protected: // ------------------------------------------------------
|
||||
|
||||
std::vector<RasterElement> m_data; //!< [m_dwWidth * m_dwHeight]
|
||||
|
||||
uint32 m_dwWidth;
|
||||
uint32 m_dwHeight;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_SIMPLEBITMAP_H
|
||||
@@ -1,249 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_SIMPLESTRINGPOOL_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_SIMPLESTRINGPOOL_H
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// String pool implementation.
|
||||
// Inspired by expat implementation.
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
class CSimpleStringPool
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
STD_BLOCK_SIZE = 4096
|
||||
};
|
||||
struct BLOCK
|
||||
{
|
||||
BLOCK* next;
|
||||
int size;
|
||||
char s[1];
|
||||
};
|
||||
unsigned int m_blockSize;
|
||||
BLOCK* m_blocks;
|
||||
BLOCK* m_free_blocks;
|
||||
const char* m_end;
|
||||
char* m_ptr;
|
||||
char* m_start;
|
||||
int nUsedSpace;
|
||||
int nUsedBlocks;
|
||||
|
||||
CSimpleStringPool()
|
||||
{
|
||||
m_blockSize = STD_BLOCK_SIZE;
|
||||
m_blocks = 0;
|
||||
m_start = 0;
|
||||
m_ptr = 0;
|
||||
m_end = 0;
|
||||
nUsedSpace = 0;
|
||||
nUsedBlocks = 0;
|
||||
m_free_blocks = 0;
|
||||
}
|
||||
~CSimpleStringPool()
|
||||
{
|
||||
BLOCK* pBlock = m_blocks;
|
||||
while (pBlock)
|
||||
{
|
||||
BLOCK* temp = pBlock->next;
|
||||
//nFree++;
|
||||
free(pBlock);
|
||||
pBlock = temp;
|
||||
}
|
||||
pBlock = m_free_blocks;
|
||||
while (pBlock)
|
||||
{
|
||||
BLOCK* temp = pBlock->next;
|
||||
//nFree++;
|
||||
free(pBlock);
|
||||
pBlock = temp;
|
||||
}
|
||||
m_blocks = 0;
|
||||
m_ptr = 0;
|
||||
m_start = 0;
|
||||
m_end = 0;
|
||||
}
|
||||
void SetBlockSize(unsigned int nBlockSize)
|
||||
{
|
||||
if (nBlockSize > 1024 * 1024)
|
||||
{
|
||||
nBlockSize = 1024 * 1024;
|
||||
}
|
||||
unsigned int size = 512;
|
||||
while (size < nBlockSize)
|
||||
{
|
||||
size *= 2;
|
||||
}
|
||||
|
||||
m_blockSize = size - offsetof(BLOCK, s);
|
||||
}
|
||||
void Clear()
|
||||
{
|
||||
if (m_free_blocks)
|
||||
{
|
||||
BLOCK* pLast = m_blocks;
|
||||
while (pLast)
|
||||
{
|
||||
BLOCK* temp = pLast->next;
|
||||
if (!temp)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pLast = temp;
|
||||
}
|
||||
if (pLast)
|
||||
{
|
||||
pLast->next = m_free_blocks;
|
||||
}
|
||||
}
|
||||
m_free_blocks = m_blocks;
|
||||
m_blocks = 0;
|
||||
m_start = 0;
|
||||
m_ptr = 0;
|
||||
m_end = 0;
|
||||
nUsedSpace = 0;
|
||||
}
|
||||
char* Append(const char* ptr, int nStrLen)
|
||||
{
|
||||
char* ret = m_ptr;
|
||||
if (m_ptr && nStrLen + 1 < (m_end - m_ptr))
|
||||
{
|
||||
memcpy(m_ptr, ptr, nStrLen);
|
||||
m_ptr = m_ptr + nStrLen;
|
||||
*m_ptr++ = 0; // add null termination.
|
||||
}
|
||||
else
|
||||
{
|
||||
int nNewBlockSize = (std::max)(nStrLen + 1, (int)m_blockSize);
|
||||
AllocBlock(nNewBlockSize, nStrLen + 1);
|
||||
memcpy(m_ptr, ptr, nStrLen);
|
||||
m_ptr = m_ptr + nStrLen;
|
||||
*m_ptr++ = 0; // add null termination.
|
||||
ret = m_start;
|
||||
}
|
||||
nUsedSpace += nStrLen;
|
||||
return ret;
|
||||
}
|
||||
char* ReplaceString(const char* str1, const char* str2)
|
||||
{
|
||||
int nStrLen1 = check_cast<int>(strlen(str1));
|
||||
int nStrLen2 = check_cast<int>(strlen(str2));
|
||||
|
||||
// undo ptr1 add.
|
||||
if (m_ptr != m_start)
|
||||
{
|
||||
m_ptr = m_ptr - nStrLen1 - 1;
|
||||
}
|
||||
|
||||
assert(m_ptr == str1);
|
||||
|
||||
int nStrLen = nStrLen1 + nStrLen2;
|
||||
|
||||
char* ret = m_ptr;
|
||||
if (m_ptr && nStrLen + 1 < (m_end - m_ptr))
|
||||
{
|
||||
memcpy(m_ptr, str1, nStrLen1);
|
||||
memcpy(m_ptr + nStrLen1, str2, nStrLen2);
|
||||
m_ptr = m_ptr + nStrLen;
|
||||
*m_ptr++ = 0; // add null termination.
|
||||
}
|
||||
else
|
||||
{
|
||||
int nNewBlockSize = (std::max)(nStrLen + 1, check_cast<int>(m_blockSize));
|
||||
if (m_ptr == m_start)
|
||||
{
|
||||
ReallocBlock(nNewBlockSize * 2); // Reallocate current block.
|
||||
memcpy(m_ptr + nStrLen1, str2, nStrLen2);
|
||||
}
|
||||
else
|
||||
{
|
||||
AllocBlock(nNewBlockSize, nStrLen + 1);
|
||||
memcpy(m_ptr, str1, nStrLen1);
|
||||
memcpy(m_ptr + nStrLen1, str2, nStrLen2);
|
||||
}
|
||||
|
||||
m_ptr = m_ptr + nStrLen;
|
||||
*m_ptr++ = 0; // add null termination.
|
||||
ret = m_start;
|
||||
}
|
||||
nUsedSpace += nStrLen;
|
||||
return ret;
|
||||
}
|
||||
private:
|
||||
void AllocBlock(int blockSize, int nMinBlockSize)
|
||||
{
|
||||
if (m_free_blocks)
|
||||
{
|
||||
BLOCK* pBlock = m_free_blocks;
|
||||
BLOCK* pPrev = 0;
|
||||
while (pBlock)
|
||||
{
|
||||
if (pBlock->size >= nMinBlockSize)
|
||||
{
|
||||
// Reuse free block
|
||||
if (pPrev)
|
||||
{
|
||||
pPrev->next = pBlock->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_free_blocks = pBlock->next;
|
||||
}
|
||||
|
||||
pBlock->next = m_blocks;
|
||||
m_blocks = pBlock;
|
||||
m_ptr = pBlock->s;
|
||||
m_start = pBlock->s;
|
||||
m_end = pBlock->s + pBlock->size;
|
||||
return;
|
||||
}
|
||||
pPrev = pBlock;
|
||||
pBlock = pBlock->next;
|
||||
}
|
||||
}
|
||||
size_t nMallocSize = offsetof(BLOCK, s) + blockSize * sizeof(char);
|
||||
//nMallocs++;
|
||||
BLOCK* pBlock = (BLOCK*)malloc(nMallocSize);
|
||||
pBlock->size = blockSize;
|
||||
pBlock->next = m_blocks;
|
||||
m_blocks = pBlock;
|
||||
m_ptr = pBlock->s;
|
||||
m_start = pBlock->s;
|
||||
m_end = pBlock->s + blockSize;
|
||||
nUsedBlocks++;
|
||||
}
|
||||
void ReallocBlock(int blockSize)
|
||||
{
|
||||
BLOCK* pThisBlock = m_blocks;
|
||||
BLOCK* pPrevBlock = m_blocks->next;
|
||||
m_blocks = pPrevBlock;
|
||||
|
||||
size_t nMallocSize = offsetof(BLOCK, s) + blockSize * sizeof(char);
|
||||
|
||||
//nMallocs++;
|
||||
BLOCK* pBlock = (BLOCK*)realloc(pThisBlock, nMallocSize);
|
||||
pBlock->size = blockSize;
|
||||
pBlock->next = m_blocks;
|
||||
m_blocks = pBlock;
|
||||
m_ptr = pBlock->s;
|
||||
m_start = pBlock->s;
|
||||
m_end = pBlock->s + blockSize;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_SIMPLESTRINGPOOL_H
|
||||
@@ -1,580 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include <platform.h>
|
||||
#include "StealingThreadPool.h"
|
||||
#include "ThreadUtils.h"
|
||||
#include <AzCore/std/bind/bind.h>
|
||||
#include <AzCore/std/parallel/thread.h>
|
||||
#include <Cry_Math.h>
|
||||
|
||||
namespace ThreadUtils {
|
||||
class StealingWorker
|
||||
{
|
||||
public:
|
||||
StealingWorker(StealingThreadPool* pool, int index, bool trace, AZStd::condition_variable& jobsCV)
|
||||
: m_pool(pool)
|
||||
, m_index(index)
|
||||
, m_tracingEnabled(trace)
|
||||
, m_lastStartTime(0)
|
||||
, m_exitFlag(0)
|
||||
, m_jobsCV(jobsCV)
|
||||
{
|
||||
}
|
||||
|
||||
static unsigned int __stdcall ThreadFunc(void* param)
|
||||
{
|
||||
StealingWorker* self = (StealingWorker*)(param);
|
||||
self->Work();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Start(int startTime)
|
||||
{
|
||||
m_lastStartTime = startTime;
|
||||
|
||||
string threadName;
|
||||
threadName.Format("StealingWorker %d", m_index);
|
||||
|
||||
AZStd::thread_desc threadDesc;
|
||||
threadDesc.m_name = threadName.c_str();
|
||||
m_thread = AZStd::thread(AZStd::bind(StealingWorker::ThreadFunc, (void*)this), &threadDesc);
|
||||
|
||||
}
|
||||
|
||||
bool GetJobLockless(Job& job)
|
||||
{
|
||||
if (m_jobs.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
job = m_jobs.front();
|
||||
m_jobs.pop_front();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetJob(Job& job)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_lockJobs);
|
||||
return GetJobLockless(job);
|
||||
}
|
||||
|
||||
void ExecuteJob(Job& job)
|
||||
{
|
||||
--m_pool->m_numJobsWaitingForExecution;
|
||||
job.Run();
|
||||
|
||||
if (m_tracingEnabled)
|
||||
{
|
||||
int time = (int)GetTickCount();
|
||||
|
||||
JobTrace trace;
|
||||
trace.m_job = job;
|
||||
trace.m_duration = time - m_lastStartTime;
|
||||
m_traces.push_back(trace);
|
||||
|
||||
m_lastStartTime = time;
|
||||
}
|
||||
|
||||
--m_pool->m_numJobs;
|
||||
m_pool->m_jobFinishedCV.notify_all();
|
||||
}
|
||||
|
||||
bool TryToStealJob(Job& job)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
StealingWorker* victim = m_pool->FindBestVictim(m_index);
|
||||
if (!victim)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (StealJobs(job, victim))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Work()
|
||||
{
|
||||
Job job;
|
||||
|
||||
while (true)
|
||||
{
|
||||
AZStd::mutex loadMutex;
|
||||
AZStd::unique_lock<AZStd::mutex> loadLock(loadMutex, AZStd::defer_lock_t());
|
||||
|
||||
while (m_pool->m_numJobsWaitingForExecution == 0)
|
||||
{
|
||||
|
||||
m_jobsCV.wait(loadLock);
|
||||
|
||||
if (m_exitFlag == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (GetJob(job))
|
||||
{
|
||||
ExecuteJob(job);
|
||||
}
|
||||
else if (TryToStealJob(job))
|
||||
{
|
||||
ExecuteJob(job);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Called from different worker thread
|
||||
bool StealJobs(Job& job, StealingWorker* victim)
|
||||
{
|
||||
if (victim == this)
|
||||
{
|
||||
assert(0 && "Trying to steal own jobs");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool order = m_index < victim->m_index;
|
||||
AZStd::lock_guard<AZStd::mutex> lock1(order ? m_lockJobs : victim->m_lockJobs);
|
||||
AZStd::lock_guard<AZStd::mutex> lock2(order ? victim->m_lockJobs : m_lockJobs);
|
||||
|
||||
if (victim->m_jobs.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int numJobs = (int)victim->m_jobs.size();
|
||||
size_t stealUntil = numJobs - numJobs / 2;
|
||||
Jobs::iterator begin = victim->m_jobs.begin();
|
||||
Jobs::iterator end = victim->m_jobs.begin() + stealUntil;
|
||||
|
||||
m_jobs.insert(m_jobs.end(), begin, end);
|
||||
victim->m_jobs.erase(begin, end);
|
||||
|
||||
return GetJobLockless(job);
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
void Submit(const Job& job)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_lockJobs);
|
||||
|
||||
m_jobs.push_back(job);
|
||||
m_jobs.back().m_debugInitialThread = m_index;
|
||||
|
||||
m_jobsCV.notify_one();
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
void Submit(const Jobs& jobs)
|
||||
{
|
||||
const size_t numJobs = jobs.size();
|
||||
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_lockJobs);
|
||||
|
||||
m_jobs.insert(m_jobs.begin(), jobs.begin(), jobs.end());
|
||||
for (size_t i = 0; i < numJobs; ++i)
|
||||
{
|
||||
m_jobs[i].m_debugInitialThread = m_index;
|
||||
}
|
||||
|
||||
m_jobsCV.notify_one();
|
||||
}
|
||||
|
||||
long NumJobsPending() const
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_lockJobs);
|
||||
return m_jobs.size();
|
||||
}
|
||||
|
||||
// Called from main thread
|
||||
void SignalExit()
|
||||
{
|
||||
CryInterlockedCompareExchange(&m_exitFlag, 1, 0);
|
||||
}
|
||||
|
||||
void GetTraces(JobTraces& traces)
|
||||
{
|
||||
if (m_tracingEnabled)
|
||||
{
|
||||
m_traces.swap(traces);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
StealingThreadPool* m_pool;
|
||||
AZStd::thread m_thread;
|
||||
int m_index;
|
||||
bool m_tracingEnabled;
|
||||
int m_lastStartTime;
|
||||
JobTraces m_traces;
|
||||
|
||||
Jobs m_jobs;
|
||||
mutable AZStd::mutex m_lockJobs;
|
||||
AZStd::condition_variable& m_jobsCV;
|
||||
|
||||
LONG m_exitFlag;
|
||||
friend class StealingThreadPool;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
StealingThreadPool::StealingThreadPool(int numThreads, bool enableTracing)
|
||||
: m_numThreads(numThreads)
|
||||
, m_numJobs(0)
|
||||
, m_numJobsWaitingForExecution(0)
|
||||
, m_enableTracing(enableTracing)
|
||||
{
|
||||
m_workers.resize(numThreads);
|
||||
for (int i = 0; i < numThreads; ++i)
|
||||
{
|
||||
m_workers[i] = new StealingWorker(this, i, m_enableTracing, m_jobsCV);
|
||||
}
|
||||
}
|
||||
|
||||
StealingThreadPool::~StealingThreadPool()
|
||||
{
|
||||
WaitAllJobs();
|
||||
|
||||
size_t numThreads = m_workers.size();
|
||||
for (size_t i = 0; i < numThreads; ++i)
|
||||
{
|
||||
m_workers[i]->SignalExit();
|
||||
}
|
||||
m_jobsCV.notify_all();
|
||||
|
||||
m_threadTraces.resize(numThreads);
|
||||
for (size_t i = 0; i < numThreads; ++i)
|
||||
{
|
||||
m_workers[i]->GetTraces(m_threadTraces[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void StealingThreadPool::Start()
|
||||
{
|
||||
int startTime = (int)GetTickCount();
|
||||
size_t numThreads = m_workers.size();
|
||||
for (int i = 0; i < numThreads; ++i)
|
||||
{
|
||||
m_workers[i]->Start(startTime);
|
||||
}
|
||||
}
|
||||
|
||||
void StealingThreadPool::WaitAllJobs()
|
||||
{
|
||||
AZStd::mutex loadMutex;
|
||||
AZStd::unique_lock<AZStd::mutex> loadLock(loadMutex, AZStd::defer_lock_t());
|
||||
|
||||
while (m_numJobs > 0)
|
||||
{
|
||||
m_jobsCV.wait(loadLock);
|
||||
}
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
void StealingThreadPool::Submit(const Job& job)
|
||||
{
|
||||
++m_numJobs;
|
||||
++m_numJobsWaitingForExecution;
|
||||
|
||||
if (StealingWorker* worker = FindWorstWorker())
|
||||
{
|
||||
worker->Submit(job);
|
||||
}
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
void StealingThreadPool::Submit(const Jobs& jobs)
|
||||
{
|
||||
m_numJobs += jobs.size();
|
||||
m_numJobsWaitingForExecution += jobs.size();
|
||||
if (StealingWorker* worker = FindWorstWorker())
|
||||
{
|
||||
worker->Submit(jobs);
|
||||
}
|
||||
}
|
||||
|
||||
JobGroup* StealingThreadPool::CreateJobGroup(JobFunc func, void* data)
|
||||
{
|
||||
return new JobGroup(this, func, data);
|
||||
}
|
||||
|
||||
StealingWorker* StealingThreadPool::FindBestVictim(int exceptFor) const
|
||||
{
|
||||
int maxJobs = 0;
|
||||
StealingWorker* bestVictim = 0;
|
||||
for (size_t i = 0; i < m_workers.size(); ++i)
|
||||
{
|
||||
if (i == exceptFor)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
StealingWorker* worker = m_workers[i];
|
||||
long numJobs = worker->NumJobsPending();
|
||||
if (numJobs > maxJobs)
|
||||
{
|
||||
maxJobs = numJobs;
|
||||
bestVictim = worker;
|
||||
}
|
||||
}
|
||||
return bestVictim;
|
||||
}
|
||||
|
||||
StealingWorker* StealingThreadPool::FindWorstWorker() const
|
||||
{
|
||||
if (m_workers.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int minJobs = INT_MAX;
|
||||
StealingWorker* worstWorker = m_workers[0];
|
||||
for (size_t i = 0; i < m_workers.size(); ++i)
|
||||
{
|
||||
StealingWorker* worker = m_workers[i];
|
||||
long numJobs = worker->NumJobsPending();
|
||||
if (numJobs < minJobs)
|
||||
{
|
||||
minJobs = numJobs;
|
||||
worstWorker = worker;
|
||||
}
|
||||
}
|
||||
return worstWorker;
|
||||
}
|
||||
|
||||
static bool WriteString(FILE* f, const char* str)
|
||||
{
|
||||
return fwrite(str, strlen(str), 1, f) == 1;
|
||||
}
|
||||
|
||||
static int Interpolate(int a, int b, float phase)
|
||||
{
|
||||
return int(float(a) + float(b - a) * phase);
|
||||
}
|
||||
|
||||
static int InterpolateColor(int c1, int c2, float phase)
|
||||
{
|
||||
const int r1 = (c1 & 0x0000ff);
|
||||
const int g1 = (c1 & 0x00ff00) >> 8;
|
||||
const int b1 = (c1 & 0xff0000) >> 16;
|
||||
const int r2 = (c2 & 0x0000ff);
|
||||
const int g2 = (c2 & 0x00ff00) >> 8;
|
||||
const int b2 = (c2 & 0xff0000) >> 16;
|
||||
|
||||
const int r = min(255, max(0, Interpolate(r1, r2, phase)));
|
||||
const int g = min(255, max(0, Interpolate(g1, g2, phase)));
|
||||
const int b = min(255, max(0, Interpolate(b1, b2, phase)));
|
||||
|
||||
return r + (g << 8) + (b << 16);
|
||||
}
|
||||
|
||||
static const int g_animColors[] = {
|
||||
0xff0000, 0x0000ff, 0x00ff00,
|
||||
0xffff00, 0xff00ff, 0x00ffff,
|
||||
0xff8080, 0x8080ff, 0x80ff80,
|
||||
0xffff80, 0xff80ff, 0x80ffff
|
||||
};
|
||||
|
||||
static int ColorizeJobTrace(const ThreadUtils::JobTrace& trace)
|
||||
{
|
||||
const int numColors = sizeof(g_animColors) / sizeof(g_animColors[0]);
|
||||
const int initialThread = trace.m_job.m_debugInitialThread;
|
||||
const int index = initialThread % numColors;
|
||||
const float brightness = aznumeric_cast<float>(pow(0.5f, initialThread / numColors));
|
||||
return InterpolateColor(0, InterpolateColor(g_animColors[index], 0xffffff, 0.5f), brightness);
|
||||
}
|
||||
|
||||
bool StealingThreadPool::SaveTracesGraph(const char* filename)
|
||||
{
|
||||
if (!m_enableTracing)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const float screenWidth = 1240.0f;
|
||||
|
||||
float duration = 0;
|
||||
for (size_t t = 0; t < m_threadTraces.size(); ++t)
|
||||
{
|
||||
float threadDuration = 0;
|
||||
const JobTraces& traces = m_threadTraces[t];
|
||||
for (int i = 0; i < traces.size(); ++i)
|
||||
{
|
||||
threadDuration += traces[i].m_duration;
|
||||
}
|
||||
duration = max(threadDuration, duration);
|
||||
}
|
||||
|
||||
const float padding = 10.0f;
|
||||
const float rowHeight = 60.0f;
|
||||
const float xScale = fabsf(duration) > FLT_EPSILON ? (screenWidth - padding * 2.0f) / duration : 1.0f;
|
||||
|
||||
const float width = screenWidth;
|
||||
const float height = (m_threadTraces.size() + 0.5f) * rowHeight;
|
||||
|
||||
FILE* f = nullptr;
|
||||
azfopen(&f, filename, "wt");
|
||||
if (!f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char buf[4096];
|
||||
azsnprintf(buf, sizeof(buf),
|
||||
"<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
"<svg\n"
|
||||
" xmlns:dc='http://purl.org/dc/elements/1.1/'\n"
|
||||
" xmlns:cc='http://creativecommons.org/ns#'\n"
|
||||
" xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'\n"
|
||||
" xmlns:svg='http://www.w3.org/2000/svg'\n"
|
||||
" xmlns='http://www.w3.org/2000/svg'\n"
|
||||
" xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd'\n"
|
||||
" xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape'\n"
|
||||
" width='%f'\n"
|
||||
" height='%f'\n"
|
||||
" id='svg2'\n"
|
||||
" version='1.1'\n"
|
||||
" >\n",
|
||||
width, height
|
||||
);
|
||||
|
||||
if (!WriteString(f, buf))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t t = 0; t < m_threadTraces.size(); ++t)
|
||||
{
|
||||
float x = padding;
|
||||
float y = rowHeight * 0.5f + rowHeight * t;
|
||||
|
||||
azsnprintf(buf, sizeof(buf),
|
||||
" <text\n"
|
||||
" xml:space='preserve'\n"
|
||||
" style='font-size:40px;font-style:normal;font-weight:normal;line-height:125%%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans'\n"
|
||||
" x='%f'\n"
|
||||
" y='%f'\n"
|
||||
" sodipodi:linespacing='125%%'><tspan sodipodi:role='line' x='%f' y='%f' style='font-size:12px;fill:#000000'>Thread %i</tspan></text>\n",
|
||||
x, y, x, y, static_cast<int>(t + 1));
|
||||
|
||||
if (!WriteString(f, buf))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
y += padding;
|
||||
|
||||
const ThreadUtils::JobTraces& traces = m_threadTraces[t];
|
||||
for (int i = 0; i < traces.size(); ++i)
|
||||
{
|
||||
const float width2 = traces[i].m_duration * xScale;
|
||||
const float height2 = rowHeight * 0.5f;
|
||||
|
||||
const int color = ColorizeJobTrace(traces[i]);
|
||||
const int strokeColor = 0;
|
||||
azsnprintf(buf, sizeof(buf),
|
||||
" <rect\n"
|
||||
" style='fill:#%06x;fill-rule:evenodd;stroke:#%06x;stroke-width:0.25px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1'\n"
|
||||
" width='%f'\n"
|
||||
" height='%f'\n"
|
||||
" x='%f'\n"
|
||||
" y='%f' />\n",
|
||||
color, strokeColor, width2, height2, x, y);
|
||||
|
||||
if (!WriteString(f, buf))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
x += width2;
|
||||
}
|
||||
|
||||
y += rowHeight;
|
||||
}
|
||||
|
||||
if (!WriteString(f, "\n</svg>\n"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void JobGroup::Process(JobGroup::GroupInfo* info)
|
||||
{
|
||||
info->m_job.Run();
|
||||
|
||||
long jobsLeft = --info->m_group->m_numJobsRunning;
|
||||
assert(jobsLeft >= 0);
|
||||
if (jobsLeft == 0)
|
||||
{
|
||||
info->m_group->m_finishJob.Run();
|
||||
delete info->m_group;
|
||||
}
|
||||
}
|
||||
|
||||
JobGroup::JobGroup(StealingThreadPool* pool, JobFunc func, void* data)
|
||||
: m_pool(pool)
|
||||
, m_numJobsRunning(0)
|
||||
, m_finishJob(func, data)
|
||||
, m_submited(false)
|
||||
{
|
||||
}
|
||||
|
||||
void JobGroup::Submit()
|
||||
{
|
||||
if (m_submited)
|
||||
{
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_numJobsRunning == 0)
|
||||
{
|
||||
m_pool->Submit(m_finishJob);
|
||||
return;
|
||||
}
|
||||
|
||||
Jobs jobs;
|
||||
jobs.resize(m_infos.size());
|
||||
for (size_t i = 0; i < m_infos.size(); ++i)
|
||||
{
|
||||
jobs[i] = Job((JobFunc) & JobGroup::Process, &m_infos[i]);
|
||||
}
|
||||
|
||||
m_pool->Submit(jobs);
|
||||
}
|
||||
|
||||
void JobGroup::Add(JobFunc func, void* data)
|
||||
{
|
||||
if (m_submited)
|
||||
{
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
GroupInfo info;
|
||||
info.m_job = Job(func, data);
|
||||
info.m_group = this;
|
||||
|
||||
m_infos.push_back(info);
|
||||
++m_numJobsRunning;
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_STEALINGTHREADPOOL_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_STEALINGTHREADPOOL_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "ThreadUtils.h"
|
||||
#include <AzCore/std/parallel/condition_variable.h>
|
||||
#include <AzCore/std/parallel/atomic.h>
|
||||
#include <BaseTypes.h>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#if AZ_TRAIT_OS_PLATFORM_APPLE
|
||||
#include "AppleSpecific.h"
|
||||
#endif
|
||||
|
||||
namespace ThreadUtils {
|
||||
class StealingWorker;
|
||||
class JobGroup;
|
||||
|
||||
// Simple stealing thread pool
|
||||
class StealingThreadPool
|
||||
{
|
||||
public:
|
||||
explicit StealingThreadPool(int numThreads, bool enableTracing = false);
|
||||
~StealingThreadPool();
|
||||
|
||||
void Start();
|
||||
void WaitAllJobs();
|
||||
|
||||
const std::vector<JobTraces>& Traces() const{ return m_threadTraces; }
|
||||
bool SaveTracesGraph(const char* filename);
|
||||
|
||||
// Submits single independent job
|
||||
template<class T>
|
||||
void Submit(void(* jobFunc)(T*), T* data)
|
||||
{
|
||||
Submit(Job((JobFunc)jobFunc, data));
|
||||
}
|
||||
|
||||
// Create a group of jobs. A group of jobs can be followed by one "finishing" job.
|
||||
// It is a way to express dependencies between jobs.
|
||||
template<class T>
|
||||
JobGroup* CreateJobGroup(void(* jobFunc)(T*), T* data)
|
||||
{
|
||||
return CreateJobGroup((JobFunc)jobFunc, (void*)data);
|
||||
}
|
||||
|
||||
uint GetNumThreads() const { return aznumeric_cast<uint>(m_numThreads); }
|
||||
|
||||
private:
|
||||
StealingWorker* FindBestVictim(int exceptFor) const;
|
||||
StealingWorker* FindWorstWorker() const;
|
||||
|
||||
void Submit(const Job& job);
|
||||
void Submit(const Jobs& jobs);
|
||||
JobGroup* CreateJobGroup(JobFunc, void* data);
|
||||
|
||||
size_t m_numThreads;
|
||||
typedef std::vector<class StealingWorker*> ThreadWorkers;
|
||||
ThreadWorkers m_workers;
|
||||
|
||||
bool m_enableTracing;
|
||||
std::vector<JobTraces> m_threadTraces;
|
||||
|
||||
AZStd::atomic_long m_numJobsWaitingForExecution;
|
||||
AZStd::atomic_long m_numJobs;
|
||||
AZStd::condition_variable m_jobsCV;
|
||||
AZStd::condition_variable m_jobFinishedCV;
|
||||
|
||||
|
||||
friend class JobGroup;
|
||||
friend class StealingWorker;
|
||||
};
|
||||
|
||||
|
||||
// JobGroup represents a group of jobs that can be followed by one "finishing"
|
||||
// job. This is a way to express dependencies between jobs.
|
||||
class JobGroup
|
||||
{
|
||||
public:
|
||||
template<class T>
|
||||
void Add(void(* jobFunc)(T*), T* data)
|
||||
{
|
||||
Add((JobFunc)jobFunc, data);
|
||||
}
|
||||
|
||||
// Submits group to thread pool
|
||||
void Submit();
|
||||
private:
|
||||
struct GroupInfo
|
||||
{
|
||||
Job m_job;
|
||||
JobGroup* m_group;
|
||||
};
|
||||
typedef std::vector<GroupInfo> GroupInfos;
|
||||
|
||||
JobGroup(StealingThreadPool* pool, JobFunc func, void* data);
|
||||
|
||||
static void Process(JobGroup::GroupInfo* job);
|
||||
void Add(JobFunc func, void* data);
|
||||
|
||||
volatile LONG m_numJobsRunning;
|
||||
StealingThreadPool* m_pool;
|
||||
GroupInfos m_infos;
|
||||
Job m_finishJob;
|
||||
bool m_submited;
|
||||
friend class StealingThreadPool;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_STEALINGTHREADPOOL_H
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_SUFFIXUTIL_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_SUFFIXUTIL_H
|
||||
#pragma once
|
||||
|
||||
|
||||
// convenience class to work with suffixes in filenames, like in like dirt_ddn.dds
|
||||
class SuffixUtil
|
||||
{
|
||||
public:
|
||||
|
||||
// filename allowed to have many suffixes (e.g. "test_ddn_bump.dds" has "bump" and "ddn"
|
||||
// as suffixes (assuming that suffixSeparator is '_').
|
||||
// suffixes in file extension are also considered (e.g. "test_abc.my_data" has "abc" and "data" as suffixes)
|
||||
// suffixes in path part are also considered. if it's not what you want - remove path before calling this function.
|
||||
// comparison is case insensitive
|
||||
static bool HasSuffix(const char* const filename, const char suffixSeparator, const char* const suffix)
|
||||
{
|
||||
assert(filename);
|
||||
assert(suffix && suffix[0]);
|
||||
|
||||
const size_t suffixLen = strlen(suffix);
|
||||
|
||||
for (const char* p = filename; *p; ++p)
|
||||
{
|
||||
if (p[0] != suffixSeparator)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (azmemicmp(&p[1], suffix, suffixLen) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const char c = p[1 + suffixLen];
|
||||
if ((c == 0) || (c == suffixSeparator) || (c == '.'))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_SUFFIXUTIL_H
|
||||
@@ -1,442 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include <platform.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h> // assert()
|
||||
#include <math.h> // floorf()
|
||||
#include "SummedAreaFilterKernel.h" // CSummedAreaFilterKernel
|
||||
|
||||
CSummedAreaFilterKernel::CSummedAreaFilterKernel()
|
||||
{
|
||||
m_eFilterType = eEmpty;
|
||||
m_fCorrectionFactor = 0.0f;
|
||||
}
|
||||
|
||||
// http://www.sixsigma.de/english/sixsigma/6s_e_gauss.htm
|
||||
bool CSummedAreaFilterKernel::CreateFromGauss(const unsigned long indwSize)
|
||||
{
|
||||
assert(indwSize > 2);
|
||||
|
||||
int iInit = 0;
|
||||
|
||||
if (!Alloc(indwSize, indwSize, &iInit))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned long y = 0; y < indwSize; y++)
|
||||
{
|
||||
for (unsigned long x = 0; x < indwSize; x++)
|
||||
{
|
||||
float fX = (float)(x) - (float)(indwSize) * 0.5f;
|
||||
float fY = (float)(y) - (float)(indwSize) * 0.5f;
|
||||
|
||||
double r1 = sqrt(fX * fX + fY * fY) / (indwSize * 0.5 - 2.0);
|
||||
|
||||
if (r1 > 1)
|
||||
{
|
||||
m_pData[y * indwSize + x] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double fSigma = 1.0 / 3.0; // we aim for 6*sigma = 99,99996 of all values
|
||||
|
||||
double fWeight = exp(-r1 * r1 / (2 * fSigma * fSigma));
|
||||
|
||||
fWeight -= (1.0 - 0.9999996);
|
||||
|
||||
m_pData[y * indwSize + x] = (int)(255.0f * fWeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_eFilterType = eGaussBlur;
|
||||
_SumUpTableAndNormalize();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// create summed area table
|
||||
void CSummedAreaFilterKernel::_SumUpTableAndNormalize()
|
||||
{
|
||||
for (unsigned long y = 0; y < m_dwHeight; y++)
|
||||
{
|
||||
int iFromLeft = 0;
|
||||
|
||||
for (unsigned long x = 0; x < m_dwWidth; x++)
|
||||
{
|
||||
iFromLeft += m_pData[y * m_dwWidth + x];
|
||||
|
||||
if (y != 0)
|
||||
{
|
||||
m_pData[y * m_dwWidth + x] = iFromLeft + m_pData[(y - 1) * m_dwWidth + x];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pData[y * m_dwWidth + x] = iFromLeft;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_fCorrectionFactor = 1.0f / ((float)m_pData[m_dwHeight * m_dwWidth - 1]);
|
||||
}
|
||||
|
||||
|
||||
// windows size 16x16 = radius 8
|
||||
bool CSummedAreaFilterKernel::CreateFromSincCalc(const unsigned long indwSize)
|
||||
{
|
||||
assert(indwSize > 2);
|
||||
|
||||
int iInit = 0;
|
||||
|
||||
if (!Alloc(indwSize, indwSize, &iInit))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned long y = 0; y < indwSize; y++)
|
||||
{
|
||||
for (unsigned long x = 0; x < indwSize; x++)
|
||||
{
|
||||
float fX = (float)(x - indwSize * 0.5f);
|
||||
float fY = (float)(y - indwSize * 0.5f);
|
||||
|
||||
float r1 = sqrtf(fX * fX + fY * fY) / (indwSize * 0.5f - 2.0f);
|
||||
|
||||
if (r1 > 1.0f)
|
||||
{
|
||||
m_pData[y * indwSize + x] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
r1 *= 3.1415926535897932384626433832795f;
|
||||
|
||||
float r2 = r1 * 8.0f;
|
||||
|
||||
// http://home.no.net/dmaurer/~dersch/interpolator/interpolator.html
|
||||
// weight = [ sin(x*pi) / (x*pi) ] * [ sin(x*pi / 8) / (x*pi/8) ]
|
||||
|
||||
// http://www.binbooks.com/books/photo/i/l/57186AF8DE
|
||||
// sinc(x) = sin(pi * x) / (pi * x)
|
||||
// L8interp(x) = sinc(x) * sinc(x/8) if abs(x) <= 8
|
||||
// = 0 if abs(x) > 8
|
||||
|
||||
float fWeight = (sinf(r1) * sinf(r2)) / (r1 * r2);
|
||||
|
||||
m_pData[y * indwSize + x] = (int)(255.0f * fWeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_eFilterType = eSinc;
|
||||
_SumUpTableAndNormalize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool CSummedAreaFilterKernel::CreateFromRAWFile(const char* filename, const unsigned long indwSize, const int iniMidValue)
|
||||
{
|
||||
assert(iniMidValue >= 0 && iniMidValue < 255);
|
||||
|
||||
int iInit = 0;
|
||||
|
||||
if (!Alloc(indwSize, indwSize, &iInit))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE* in = fopen(filename, "rb");
|
||||
if (!in)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned long y = 0; y < m_dwHeight; y++)
|
||||
{
|
||||
for (unsigned long x = 0; x < m_dwWidth; x++)
|
||||
{
|
||||
unsigned char val;
|
||||
|
||||
if (fread(&val, 1, 1, in) != 1)
|
||||
{
|
||||
fclose(in);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pData[y * m_dwWidth + x] = (int)val - iniMidValue;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
|
||||
m_eFilterType = eRAW;
|
||||
_SumUpTableAndNormalize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::string CSummedAreaFilterKernel::GetInfoString(void) const
|
||||
{
|
||||
std::string sRet = "FilterKernel(";
|
||||
|
||||
switch (m_eFilterType)
|
||||
{
|
||||
case eEmpty:
|
||||
sRet += "Empty";
|
||||
break;
|
||||
case eSinc:
|
||||
sRet += "Sinc16x16";
|
||||
break;
|
||||
case eRAW:
|
||||
sRet += "RAW";
|
||||
break;
|
||||
case eGaussBlur:
|
||||
sRet += "GaussBlur";
|
||||
break;
|
||||
case eGaussSharp:
|
||||
sRet += "GaussSharp";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
sRet += ")";
|
||||
|
||||
return(sRet);
|
||||
}
|
||||
|
||||
float CSummedAreaFilterKernel::GetAreaNonAA(float infAx, float infAy, float infDx, float infDy) const
|
||||
{
|
||||
assert(m_eFilterType != eEmpty);
|
||||
|
||||
int ax = (int)floorf(infAx * 127.5f + 127.5f);
|
||||
int ay = (int)floorf(infAy * 127.5f + 127.5f);
|
||||
int dx = (int)floorf(infDx * 127.5f + 127.5f);
|
||||
int dy = (int)floorf(infDy * 127.5f + 127.5f);
|
||||
|
||||
if (ax < 0)
|
||||
{
|
||||
ax = 0;
|
||||
}
|
||||
else if (ax > 255)
|
||||
{
|
||||
ax = 255;
|
||||
}
|
||||
if (dx < 0)
|
||||
{
|
||||
dx = 0;
|
||||
}
|
||||
else if (dx > 255)
|
||||
{
|
||||
dx = 255;
|
||||
}
|
||||
if (ay < 0)
|
||||
{
|
||||
ay = 0;
|
||||
}
|
||||
else if (ay > 255)
|
||||
{
|
||||
ay = 255;
|
||||
}
|
||||
if (dy < 0)
|
||||
{
|
||||
dy = 0;
|
||||
}
|
||||
else if (dy > 255)
|
||||
{
|
||||
dy = 255;
|
||||
}
|
||||
|
||||
unsigned long area = m_pData[dy * m_dwWidth + dx] - m_pData[dy * m_dwWidth + ax] - m_pData[ay * m_dwWidth + dx] + m_pData[ay * m_dwWidth + ax];
|
||||
|
||||
return(m_fCorrectionFactor * (float)area);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// optimizable
|
||||
float CSummedAreaFilterKernel::GetAreaAA(float infAx, float infAy, float infDx, float infDy) const
|
||||
{
|
||||
assert(m_eFilterType != eEmpty);
|
||||
|
||||
infAx = infAx * 127.5f + 127.5f;
|
||||
infAy = infAy * 127.5f + 127.5f;
|
||||
infDx = infDx * 127.5f + 127.5f;
|
||||
infDy = infDy * 127.5f + 127.5f;
|
||||
|
||||
float fSum = _GetBilinearFiltered(infDx, infDy)
|
||||
- _GetBilinearFiltered(infAx, infDy)
|
||||
- _GetBilinearFiltered(infDx, infAy)
|
||||
+ _GetBilinearFiltered(infAx, infAy);
|
||||
|
||||
return(fSum * m_fCorrectionFactor);
|
||||
}
|
||||
|
||||
|
||||
float CSummedAreaFilterKernel::_GetBilinearFiltered(const float infX, const float infY) const
|
||||
{
|
||||
float fIX = floorf(infX), fIY = floorf(infY);
|
||||
float fFX = infX - fIX, fFY = infY - fIY;
|
||||
int iX = (int)fIX, iY = (int)fIY;
|
||||
|
||||
if (iX < 0)
|
||||
{
|
||||
iX = 0;
|
||||
}
|
||||
else if (iX > 254)
|
||||
{
|
||||
iX = 254;
|
||||
}
|
||||
if (iY < 0)
|
||||
{
|
||||
iY = 0;
|
||||
}
|
||||
else if (iY > 254)
|
||||
{
|
||||
iY = 254;
|
||||
}
|
||||
|
||||
float fArea = m_pData[ iY * m_dwWidth + iX ] * ((1.0f - fFX) * (1.0f - fFY)) // left top
|
||||
+ m_pData[ iY * m_dwWidth + iX + 1 ] * ((fFX) * (1.0f - fFY)) // right top
|
||||
+ m_pData[(iY + 1) * m_dwWidth + iX ] * ((1.0f - fFX) * (fFY)) // left bottom
|
||||
+ m_pData[ iY * m_dwWidth + iX + 257] * ((fFX) * (fFY)); // right bottom
|
||||
|
||||
return(fArea);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CSummedAreaFilterKernel::CreateWeightFilter(CSimpleBitmap<float>& outFilter, const float infX, const float infY,
|
||||
const float infWeight, const float infR) const
|
||||
{
|
||||
assert(infX >= 0.0f);
|
||||
assert(infX < 1.0f);
|
||||
assert(infY >= 0.0f);
|
||||
assert(infY < 1.0f);
|
||||
assert(infWeight >= 0.0f);
|
||||
assert(infR > 0.0f);
|
||||
|
||||
float fLeftTop = ceilf(infR);
|
||||
int iSide = 2 * (int)fLeftTop + 1;
|
||||
|
||||
float fInit = 0.0f;
|
||||
|
||||
if (!outFilter.Alloc(iSide, iSide, &fInit))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AddWeights(outFilter, infX + fLeftTop, infY + fLeftTop, infWeight, infR);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CSummedAreaFilterKernel::CreateWeightFilterBlock(CSimpleBitmap<float>& outFilter, const unsigned long indwSideLength,
|
||||
const float infR) const
|
||||
{
|
||||
assert(indwSideLength >= 0);
|
||||
assert(infR > 0.0f);
|
||||
|
||||
float fLeftTop = ceilf(infR);
|
||||
int iSide = 2 * (int)fLeftTop + 1;
|
||||
|
||||
float fInit = 0.0f;
|
||||
|
||||
if (!outFilter.Alloc(iSide, iSide, &fInit))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float fStep = 1.0f / (float)indwSideLength;
|
||||
float fHalf = fStep * 0.5f;
|
||||
|
||||
float fWeight = fStep * fStep;
|
||||
|
||||
for (float y = fHalf; y < 1.0f; y += fStep)
|
||||
{
|
||||
for (float x = fHalf; x < 1.0f; x += fStep)
|
||||
{
|
||||
AddWeights(outFilter, x + fLeftTop, y + fLeftTop, fWeight, infR);
|
||||
}
|
||||
}
|
||||
|
||||
// check
|
||||
#ifdef _DEBUG
|
||||
float fSum = 0.0f;
|
||||
for (int y = 0; y < iSide; y++)
|
||||
{
|
||||
for (int x = 0; x < iSide; x++)
|
||||
{
|
||||
float f;
|
||||
|
||||
outFilter.Get(x, y, f);
|
||||
fSum += f;
|
||||
}
|
||||
}
|
||||
assert(fSum >= 0.98f);
|
||||
assert(fSum <= 1.02f);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CSummedAreaFilterKernel::AddWeights(CSimpleBitmap<float>& inoutFilter, const float infX, const float infY,
|
||||
const float infWeight, const float infR) const
|
||||
{
|
||||
assert(infWeight >= 0.0f);
|
||||
assert(infR > 0.0f);
|
||||
|
||||
if (infWeight <= 0.0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float fInvR = 1.0f / infR;
|
||||
float sx = floorf(infX - infR);
|
||||
float sy = floorf(infY - infR);
|
||||
|
||||
int iax = (int)sx;
|
||||
int iay = (int)sy;
|
||||
int iex = (int)ceilf(infX + infR);
|
||||
int iey = (int)ceilf(infY + infR);
|
||||
|
||||
float x, y;
|
||||
int ix, iy;
|
||||
|
||||
for (iy = iay, y = (sy - infY) * fInvR; iy <= iey; iy++, y += fInvR)
|
||||
{
|
||||
for (ix = iax, x = (sx - infX) * fInvR; ix <= iex; ix++, x += fInvR)
|
||||
{
|
||||
float fArea = GetAreaAA(x, y, x + fInvR, y + fInvR); // better quality
|
||||
// float fArea=m_Filter.GetAreaNonAA(x,y,x+fInvR,y+fInvR); // faster
|
||||
|
||||
// assert(fArea<=1.0f); // may be wrong if we use sharpening filter
|
||||
|
||||
float fOldVal;
|
||||
|
||||
inoutFilter.Get(ix, iy, fOldVal);
|
||||
inoutFilter.Set(ix, iy, fOldVal + fArea * infWeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#pragma once
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_SUMMEDAREAFILTERKERNEL_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_SUMMEDAREAFILTERKERNEL_H
|
||||
|
||||
#include <string> // STL string
|
||||
#include "SimpleBitmap.h" // SimpleBitmap<>
|
||||
|
||||
// squared of any size (summed area tables limit the size and/or values)
|
||||
// normalized(sum=1)
|
||||
|
||||
// optimized for high quality, not speed
|
||||
// for faster filter kernels extract the neccessary size and use this 1:1
|
||||
|
||||
// based on summed area tables
|
||||
|
||||
class CSummedAreaFilterKernel
|
||||
: public CSimpleBitmap<int>
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor init is eEmpty
|
||||
CSummedAreaFilterKernel();
|
||||
|
||||
//! load 8 bit photoshop 256x256 raw image - slow
|
||||
//! typical filtersize for a gaussian filter kernel is 1.44
|
||||
//! /param iniMidValue [0..255[ this enables sharpening - sharpening may expand the result range
|
||||
bool CreateFromRAWFile(const char* filename, const unsigned long indwSize = 256, const int iniMidValue = 0);
|
||||
|
||||
//! sharpest possible result - filter diameter size has to be 16*pixelsize (256 samples per pixel)
|
||||
//! theory: http://home.no.net/dmaurer/~dersch/interpolator/interpolator.html
|
||||
//! /param indwSize >2
|
||||
bool CreateFromSincCalc(const unsigned long indwSize = 256);
|
||||
|
||||
//! shttp://www.sixsigma.de/english/sixsigma/6s_e_gauss.htm
|
||||
//! /param indwSize >2
|
||||
bool CreateFromGauss(const unsigned long indwSize = 256);
|
||||
|
||||
//! optimizable O(k*1) with high k
|
||||
//! bokeh is in the range ([-1..1],[-1..1])
|
||||
//! return normalized result
|
||||
float GetAreaAA(float infAx, float infAy, float infDx, float infDy) const;
|
||||
|
||||
//! O(k*1) with low k
|
||||
//! bokeh is in the range ([-1..1],[-1..1])
|
||||
//! return normalized result
|
||||
float GetAreaNonAA(float infAx, float infAy, float infDx, float infDy) const;
|
||||
|
||||
//!
|
||||
//! /return e.g. "FilterKernel(Sinc16x16)"
|
||||
std::string GetInfoString(void) const;
|
||||
|
||||
//! /param infX [0..1[
|
||||
//! /param infY [0..1[
|
||||
//! /param infWeight [0..[
|
||||
//! /param infR >0, radius
|
||||
bool CreateWeightFilter(CSimpleBitmap<float>& outFilter, const float infX, const float infY,
|
||||
const float infWeight, const float infR) const;
|
||||
|
||||
//! weight for the whole block is 1.0
|
||||
//! /param indwSideLength [1,..[ e.g. 3 for 3x3 block
|
||||
//! /param infR >0, radius
|
||||
bool CreateWeightFilterBlock(CSimpleBitmap<float>& outFilter, const unsigned long indwSideLength, const float infR) const;
|
||||
|
||||
//! with user filter kernel
|
||||
//! /param infX
|
||||
//! /param infY
|
||||
//! /param infWeight [0..[
|
||||
//! /param infR >0, radius
|
||||
void AddWeights(CSimpleBitmap<float>& inoutFilter, const float infX, const float infY,
|
||||
const float infWeight, const float infR) const;
|
||||
|
||||
private: // --------------------------------------------------------------------
|
||||
|
||||
enum EFilterState
|
||||
{
|
||||
eEmpty, //!< after calling constructor
|
||||
eSinc, //!< from CreateFromSincCalc
|
||||
eRAW, //!< from CreateFromRAWFile
|
||||
eGaussBlur, //!< from CreateFromGauss
|
||||
eDisc, //!< not implemented
|
||||
eGaussSharp //!< not implemented
|
||||
};
|
||||
|
||||
EFilterState m_eFilterType; //!< for error checks and GetInfoString()
|
||||
float m_fCorrectionFactor; //!< to get the normalized (whole kernel has sum of 1) result
|
||||
|
||||
//! optimizable
|
||||
//! bokeh is in the range ([0..255],[0..255])
|
||||
//! /param infX
|
||||
//! /param infY
|
||||
//! /return not normalized result
|
||||
float _GetBilinearFiltered(const float infX, const float infY) const;
|
||||
|
||||
//! sum the stored values in the bitmap together
|
||||
//! calculate m_fCorrectionFactor
|
||||
void _SumUpTableAndNormalize(void);
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_SUMMEDAREAFILTERKERNEL_H
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
// Description : Opens a temporary file for read only access, where the file could be
|
||||
// located in a zip or pak file. Note that if the file specified
|
||||
// already exists it does not delete it when finished.
|
||||
|
||||
|
||||
#include "TempFilePakExtraction.h"
|
||||
#include "FileUtil.h"
|
||||
#include "PathHelpers.h"
|
||||
#include "IPakSystem.h"
|
||||
|
||||
|
||||
TempFilePakExtraction::TempFilePakExtraction(const char* filename, const char* tempPath, IPakSystem* pPakSystem)
|
||||
: m_strOriginalFileName(filename)
|
||||
, m_strTempFileName(filename)
|
||||
{
|
||||
if (!pPakSystem || !tempPath)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
FILE* fileOnDisk = nullptr;
|
||||
azfopen(&fileOnDisk, m_strOriginalFileName.c_str(), "rb");
|
||||
if (fileOnDisk)
|
||||
{
|
||||
fclose(fileOnDisk);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Choose the name for the temporary file.
|
||||
string tempFullFileName;
|
||||
{
|
||||
uint32 tempNumber = 0;
|
||||
{
|
||||
LARGE_INTEGER performanceCount;
|
||||
if (QueryPerformanceCounter(&performanceCount))
|
||||
{
|
||||
tempNumber = performanceCount.u.LowPart;
|
||||
}
|
||||
}
|
||||
|
||||
string tempName;
|
||||
{
|
||||
// CryEngine's pak system supports filenames in format "@pakFilename|fileInPak",
|
||||
// so let's handle such cases by using fileInPak part of the filename.
|
||||
const size_t pos = m_strOriginalFileName.find_last_of('|');
|
||||
if (pos != string::npos)
|
||||
{
|
||||
tempName = m_strOriginalFileName.substr(pos + 1, string::npos);
|
||||
if (tempName.empty())
|
||||
{
|
||||
tempName = "BadFilenameSyntax";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tempName = m_strOriginalFileName;
|
||||
}
|
||||
tempName = PathHelpers::GetFilename(tempName);
|
||||
}
|
||||
|
||||
int tryCount = 2000;
|
||||
while (--tryCount >= 0)
|
||||
{
|
||||
tempFullFileName.Format("%sRC%04x_%s", tempPath, (tempNumber & 0xFFFF), tempName.c_str());
|
||||
|
||||
if (!FileUtil::FileExists(tempFullFileName.c_str()))
|
||||
{
|
||||
FILE* f = nullptr;
|
||||
azfopen(&f, tempFullFileName.c_str(), "wb");
|
||||
if (f)
|
||||
{
|
||||
fclose(f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tempFullFileName.clear();
|
||||
++tempNumber;
|
||||
}
|
||||
|
||||
if (tempFullFileName.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (pPakSystem->ExtractNoOverwrite(m_strOriginalFileName.c_str(), tempFullFileName.c_str()))
|
||||
{
|
||||
m_strTempFileName = tempFullFileName;
|
||||
AZ::IO::SystemFile::SetWritable(m_strTempFileName.c_str(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ::IO::LocalFileIO().Remove(tempFullFileName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TempFilePakExtraction::~TempFilePakExtraction()
|
||||
{
|
||||
if (HasTempFile())
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
SetFileAttributesA(m_strTempFileName.c_str(), FILE_ATTRIBUTE_ARCHIVE);
|
||||
#endif
|
||||
AZ::IO::LocalFileIO().Remove(m_strTempFileName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool TempFilePakExtraction::HasTempFile() const
|
||||
{
|
||||
return (m_strOriginalFileName != m_strTempFileName);
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
// Description : Opens a temporary file for read only access, where the file could be
|
||||
// located in a zip or pak file. Note that if the file specified
|
||||
// already exists it does not delete it when finished.
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_TEMPFILEPAKEXTRACTION_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_TEMPFILEPAKEXTRACTION_H
|
||||
#pragma once
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
struct IPakSystem;
|
||||
|
||||
class TempFilePakExtraction
|
||||
{
|
||||
public:
|
||||
TempFilePakExtraction(const char* filename, const char* tempPath, IPakSystem* pPakSystem);
|
||||
~TempFilePakExtraction();
|
||||
|
||||
const string& GetTempName() const
|
||||
{
|
||||
return m_strTempFileName;
|
||||
}
|
||||
|
||||
const string& GetOriginalName() const
|
||||
{
|
||||
return m_strOriginalFileName;
|
||||
}
|
||||
|
||||
bool HasTempFile() const;
|
||||
|
||||
private:
|
||||
string m_strTempFileName;
|
||||
string m_strOriginalFileName;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_TEMPFILEPAKEXTRACTION_H
|
||||
@@ -1,171 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include <platform.h>
|
||||
#include "ThreadUtils.h"
|
||||
#include <AzCore/std/parallel/thread.h>
|
||||
#include <AzCore/std/bind/bind.h>
|
||||
#include <AzCore/std/parallel/lock.h>
|
||||
#include <CryAssert.h>
|
||||
|
||||
namespace ThreadUtils
|
||||
{
|
||||
class SimpleWorker
|
||||
{
|
||||
public:
|
||||
SimpleWorker(SimpleThreadPool* pool, int index, bool trace)
|
||||
: m_pool(pool)
|
||||
, m_index(index)
|
||||
, m_trace(trace)
|
||||
{
|
||||
}
|
||||
|
||||
void Start(int startTime)
|
||||
{
|
||||
m_lastStartTime = startTime;
|
||||
m_handle = AZStd::thread(AZStd::bind(SimpleWorker::ThreadFunc, (void*)this));
|
||||
}
|
||||
|
||||
static unsigned int __stdcall ThreadFunc(void* param)
|
||||
{
|
||||
SimpleWorker* self = (SimpleWorker*)(param);
|
||||
self->Work();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ExecuteJob(Job& job)
|
||||
{
|
||||
job.Run();
|
||||
if (m_trace)
|
||||
{
|
||||
int time = (int)GetTickCount();
|
||||
|
||||
JobTrace trace;
|
||||
trace.m_job = job;
|
||||
trace.m_duration = time - m_lastStartTime;
|
||||
m_traces.push_back(trace);
|
||||
|
||||
m_lastStartTime = time;
|
||||
}
|
||||
}
|
||||
|
||||
void Work()
|
||||
{
|
||||
Job job;
|
||||
for (;; )
|
||||
{
|
||||
if (m_pool->GetJob(job, m_index))
|
||||
{
|
||||
ExecuteJob(job);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Called from main thread
|
||||
void Join(JobTraces& traces)
|
||||
{
|
||||
if(m_handle.joinable())
|
||||
{
|
||||
m_handle.join();
|
||||
}
|
||||
|
||||
if (m_trace)
|
||||
{
|
||||
m_traces.swap(traces);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SimpleThreadPool* m_pool;
|
||||
AZStd::thread m_handle;
|
||||
int m_index;
|
||||
bool m_trace;
|
||||
int m_lastStartTime;
|
||||
JobTraces m_traces;
|
||||
friend SimpleThreadPool;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
SimpleThreadPool::SimpleThreadPool(bool trace)
|
||||
: m_trace(trace)
|
||||
, m_started(false)
|
||||
, m_numProcessedJobs(0)
|
||||
{
|
||||
}
|
||||
|
||||
SimpleThreadPool::~SimpleThreadPool()
|
||||
{
|
||||
WaitAllJobs();
|
||||
}
|
||||
|
||||
void SimpleThreadPool::Start(int numThreads)
|
||||
{
|
||||
m_workers.resize(numThreads);
|
||||
for (int i = 0; i < numThreads; ++i)
|
||||
{
|
||||
m_workers[i] = new SimpleWorker(this, i, m_trace);
|
||||
}
|
||||
|
||||
m_started = true;
|
||||
|
||||
int startTime = (int)GetTickCount();
|
||||
for (int i = 0; i < numThreads; ++i)
|
||||
{
|
||||
m_workers[i]->Start(startTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SimpleThreadPool::WaitAllJobs()
|
||||
{
|
||||
size_t numThreads = m_workers.size();
|
||||
m_threadTraces.resize(numThreads);
|
||||
for (size_t i = 0; i < numThreads; ++i)
|
||||
{
|
||||
m_workers[i]->Join(m_threadTraces[i]);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < numThreads; ++i)
|
||||
{
|
||||
delete m_workers[i];
|
||||
}
|
||||
m_workers.clear();
|
||||
|
||||
m_started = false;
|
||||
}
|
||||
|
||||
void SimpleThreadPool::Submit(const Job& job)
|
||||
{
|
||||
assert(!m_started);
|
||||
m_jobs.push_back(job);
|
||||
}
|
||||
|
||||
bool SimpleThreadPool::GetJob(Job& job, [[maybe_unused]] int threadIndex)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_lockJobs);
|
||||
|
||||
if (m_numProcessedJobs >= m_jobs.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
job = m_jobs[m_numProcessedJobs];
|
||||
++m_numProcessedJobs;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,288 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_THREADUTILS_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_THREADUTILS_H
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/parallel/mutex.h>
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h> // CRITICAL_SECTION
|
||||
#endif
|
||||
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
|
||||
namespace ThreadUtils
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
class CriticalSection
|
||||
{
|
||||
friend class ConditionVariable;
|
||||
|
||||
public:
|
||||
CriticalSection()
|
||||
{
|
||||
memset(&m_cs, 0, sizeof(m_cs));
|
||||
InitializeCriticalSection(&m_cs);
|
||||
}
|
||||
|
||||
~CriticalSection()
|
||||
{
|
||||
DeleteCriticalSection(&m_cs);
|
||||
}
|
||||
|
||||
void Lock()
|
||||
{
|
||||
EnterCriticalSection(&m_cs);
|
||||
}
|
||||
void Unlock()
|
||||
{
|
||||
LeaveCriticalSection(&m_cs);
|
||||
}
|
||||
bool TryLock()
|
||||
{
|
||||
return TryEnterCriticalSection(&m_cs) != FALSE;
|
||||
}
|
||||
|
||||
#if defined(AZ_DEBUG_BUILD)
|
||||
bool IsLocked()
|
||||
{
|
||||
return m_cs.RecursionCount > 0 && m_cs.OwningThread == GetCurrentThread();
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
// You are not allowed to copy or move a CRITICAL_SECTION
|
||||
// handle, so make this class non-copyable
|
||||
CriticalSection(const CriticalSection& cs);
|
||||
CriticalSection& operator=(const CriticalSection& cs);
|
||||
|
||||
CRITICAL_SECTION m_cs;
|
||||
};
|
||||
|
||||
class ConditionVariable
|
||||
{
|
||||
public:
|
||||
ConditionVariable()
|
||||
{
|
||||
InitializeConditionVariable(&m_cv);
|
||||
}
|
||||
|
||||
void Wake()
|
||||
{
|
||||
WakeConditionVariable(&m_cv);
|
||||
}
|
||||
|
||||
void WakeAll()
|
||||
{
|
||||
WakeAllConditionVariable(&m_cv);
|
||||
}
|
||||
|
||||
void Sleep(CriticalSection& cs, DWORD milliseconds = INFINITE)
|
||||
{
|
||||
SleepConditionVariableCS(&m_cv, &cs.m_cs, milliseconds);
|
||||
}
|
||||
|
||||
private:
|
||||
// You are not allowed to copy or move a CONDITION_VARIABLE
|
||||
// handle, so make this class non-copyable
|
||||
ConditionVariable(const ConditionVariable& cs);
|
||||
ConditionVariable& operator=(const ConditionVariable& cs);
|
||||
|
||||
CONDITION_VARIABLE m_cv;
|
||||
};
|
||||
#elif AZ_TRAIT_OS_PLATFORM_APPLE || defined(AZ_PLATFORM_LINUX)
|
||||
class CriticalSection
|
||||
{
|
||||
public:
|
||||
CriticalSection()
|
||||
: m_locked(false)
|
||||
{
|
||||
}
|
||||
|
||||
~CriticalSection()
|
||||
{
|
||||
}
|
||||
|
||||
void Lock()
|
||||
{
|
||||
m_cs.lock();
|
||||
m_locked = true;
|
||||
}
|
||||
void Unlock()
|
||||
{
|
||||
m_cs.unlock();
|
||||
m_locked = false;
|
||||
}
|
||||
bool TryLock()
|
||||
{
|
||||
m_locked = m_cs.try_lock();
|
||||
return m_locked;
|
||||
}
|
||||
|
||||
#if defined (AZ_DEBUG_BUILD)
|
||||
bool IsLocked()
|
||||
{
|
||||
return m_locked;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
// You are not allowed to copy or move a CRITICAL_SECTION
|
||||
// handle, so make this class non-copyable
|
||||
CriticalSection(const CriticalSection& cs);
|
||||
CriticalSection& operator=(const CriticalSection& cs);
|
||||
|
||||
bool m_locked;
|
||||
AZStd::recursive_mutex m_cs;
|
||||
};
|
||||
#endif
|
||||
|
||||
class AutoLock
|
||||
{
|
||||
private:
|
||||
CriticalSection& m_lock;
|
||||
|
||||
AutoLock();
|
||||
AutoLock(const AutoLock&);
|
||||
AutoLock& operator = (const AutoLock&);
|
||||
|
||||
public:
|
||||
AutoLock(CriticalSection& lock)
|
||||
: m_lock(lock)
|
||||
{
|
||||
m_lock.Lock();
|
||||
}
|
||||
~AutoLock()
|
||||
{
|
||||
m_lock.Unlock();
|
||||
}
|
||||
};
|
||||
|
||||
typedef void(* JobFunc)(void*);
|
||||
|
||||
struct Job
|
||||
{
|
||||
JobFunc m_func;
|
||||
void* m_data;
|
||||
int m_debugInitialThread;
|
||||
|
||||
Job()
|
||||
: m_func(0)
|
||||
, m_data(0)
|
||||
, m_debugInitialThread(0)
|
||||
{
|
||||
}
|
||||
|
||||
Job(JobFunc func, void* data)
|
||||
: m_func(func)
|
||||
, m_data(data)
|
||||
, m_debugInitialThread(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Run()
|
||||
{
|
||||
m_func(m_data);
|
||||
}
|
||||
};
|
||||
typedef std::deque<Job> Jobs;
|
||||
|
||||
struct JobTrace
|
||||
{
|
||||
Job m_job;
|
||||
bool m_stolen;
|
||||
int m_duration;
|
||||
|
||||
JobTrace()
|
||||
: m_duration(0)
|
||||
, m_stolen(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
typedef std::vector<JobTrace> JobTraces;
|
||||
|
||||
class SimpleWorker;
|
||||
|
||||
class SimpleThreadPool
|
||||
{
|
||||
public:
|
||||
SimpleThreadPool(bool trace);
|
||||
~SimpleThreadPool();
|
||||
|
||||
bool GetJob(Job& job, int threadIndex);
|
||||
|
||||
// Submits single independent job
|
||||
template<class T>
|
||||
void Submit(void(* jobFunc)(T*), T* data)
|
||||
{
|
||||
Submit(Job((JobFunc)jobFunc, data));
|
||||
}
|
||||
|
||||
void Start(int numThreads);
|
||||
void WaitAllJobs();
|
||||
|
||||
private:
|
||||
void Submit(const Job& job);
|
||||
|
||||
bool m_started;
|
||||
bool m_trace;
|
||||
|
||||
std::vector<SimpleWorker*> m_workers;
|
||||
|
||||
std::vector<JobTraces> m_threadTraces;
|
||||
|
||||
int m_numProcessedJobs;
|
||||
AZStd::mutex m_lockJobs;
|
||||
std::vector<Job> m_jobs;
|
||||
};
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
#pragma pack(push, 8)
|
||||
struct ThreadNameInfo
|
||||
{
|
||||
DWORD dwType; // Must be 0x1000.
|
||||
LPCSTR szName; // Pointer to name (in user addr space).
|
||||
DWORD dwThreadID; // Thread ID (-1=caller thread).
|
||||
DWORD dwFlags; // Reserved for future use, must be zero.
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
// Usage: SetThreadName (-1, "MainThread");
|
||||
// From http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
|
||||
inline void SetThreadName([[maybe_unused]] DWORD dwThreadID, [[maybe_unused]] const char* threadName)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
ThreadNameInfo info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = threadName;
|
||||
info.dwThreadID = dwThreadID;
|
||||
info.dwFlags = 0;
|
||||
|
||||
__try
|
||||
{
|
||||
const DWORD exceptionCode = 0x406D1388;
|
||||
RaiseException(exceptionCode, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_THREADUTILS_H
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1fb280a5c873225c5f2b0518964c9b7947e81c6fdb4ec19374e02043a12dd295
|
||||
size 2358
|
||||
@@ -1,807 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <platform.h>
|
||||
#include "PathHelpers.h"
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <CryCommon/LegacyAllocator.h>
|
||||
|
||||
namespace PathHelpersTest
|
||||
{
|
||||
class CryCommonToolsPathHelpersTest
|
||||
: public UnitTest::AllocatorsTestFixture
|
||||
{
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
UnitTest::AllocatorsTestFixture::SetUp();
|
||||
AZ::AllocatorInstance<AZ::LegacyAllocator>::Create();
|
||||
AZ::AllocatorInstance<CryStringAllocator>::Create();
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
AZ::AllocatorInstance<AZ::LegacyAllocator>::Destroy();
|
||||
AZ::AllocatorInstance<CryStringAllocator>::Destroy();
|
||||
UnitTest::AllocatorsTestFixture::TearDown();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, FindExtension_StringPathNoExtension_ReturnsEmptyString)
|
||||
{
|
||||
const char* filePath = "ext";
|
||||
string result = PathHelpers::FindExtension(filePath);
|
||||
EXPECT_STREQ("", result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, FindExtension_StringPath_ReturnsStringExtension)
|
||||
{
|
||||
const char* extension = "ext";
|
||||
const char* filePath = "foo.ext";
|
||||
string result = PathHelpers::FindExtension(filePath);
|
||||
EXPECT_STREQ(extension, result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, FindExtension_WStringPathNoExtension_ReturnsEmptyString)
|
||||
{
|
||||
const wchar_t filePath[] = L"ext";
|
||||
const wchar_t expectedResult[] = L"";
|
||||
const wstring result = PathHelpers::FindExtension(filePath);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, FindExtension_WStringPath_ReturnsStringExtension)
|
||||
{
|
||||
const wchar_t extension[] = L"ext";
|
||||
const wchar_t filePath[] = L"foo.ext";
|
||||
const wstring result = PathHelpers::FindExtension(filePath);
|
||||
EXPECT_TRUE(result == extension);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ReplaceExtension_EmptyStringPath_ReturnsEmptyString)
|
||||
{
|
||||
const char* filePath = "";
|
||||
const char* newExtension = "new";
|
||||
string result = PathHelpers::ReplaceExtension(filePath, newExtension);
|
||||
EXPECT_STREQ(filePath, result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ReplaceExtension_StringNoExtension_ReturnsStringNoExtension)
|
||||
{
|
||||
const char* filePath = "foo.ext";
|
||||
const char* newExtension = "";
|
||||
string result = PathHelpers::ReplaceExtension(filePath, newExtension);
|
||||
EXPECT_STREQ("foo", result);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ReplaceExtension_StringPathWithDoubleBackSlash_ReturnsUnalteredString)
|
||||
{
|
||||
const char* filePath = "foo.ext\\";
|
||||
const char* newExtension = "new";
|
||||
string result = PathHelpers::ReplaceExtension(filePath, newExtension);
|
||||
EXPECT_STREQ(filePath, result);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ReplaceExtension_StringPathWithForwardSlash_ReturnsUnalteredString)
|
||||
{
|
||||
const char* filePath = "foo.ext/";
|
||||
const char* newExtension = "new";
|
||||
string result = PathHelpers::ReplaceExtension(filePath, newExtension);
|
||||
EXPECT_STREQ(filePath, result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ReplaceExtension_StringPathWithColon_ReturnsUnalteredString)
|
||||
{
|
||||
const char* filePath = "foo.ext:";
|
||||
const char* newExtension = "new";
|
||||
string result = PathHelpers::ReplaceExtension(filePath, newExtension);
|
||||
EXPECT_STREQ(filePath, result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ReplaceExtension_StringPathEndsWithPeriod_ReturnsUnalteredString)
|
||||
{
|
||||
const char* filePath = "foo.ext.";
|
||||
const char* newExtension = "new";
|
||||
string result = PathHelpers::ReplaceExtension(filePath, newExtension);
|
||||
EXPECT_STREQ(filePath, result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ReplaceExtension_StringNewExtension_ReturnsStringWithNewExtension)
|
||||
{
|
||||
const char* filePath = "foo.ext";
|
||||
const char* newExtension = "new";
|
||||
string result = PathHelpers::ReplaceExtension(filePath, newExtension);
|
||||
EXPECT_STREQ("foo.new", result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ReplaceExtension_EmptyWStringPath_ReturnsEmptyWString)
|
||||
{
|
||||
const wchar_t filePath[] = L"";
|
||||
const wchar_t newExtension[] = L"new";
|
||||
wstring result = PathHelpers::ReplaceExtension(filePath, newExtension);
|
||||
EXPECT_TRUE(result == filePath);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ReplaceExtension_WStringNoExtension_ReturnsWStringNoExtension)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo.ext";
|
||||
const wchar_t newExtension[] = L"";
|
||||
const wchar_t expectedResult[] = L"foo";
|
||||
wstring result = PathHelpers::ReplaceExtension(filePath, newExtension);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ReplaceExtension_WStringPathWithDoubleBackSlash_ReturnsUnalteredWString)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo.ext\\";
|
||||
const wchar_t newExtension[] = L"new";
|
||||
wstring result = PathHelpers::ReplaceExtension(filePath, newExtension);
|
||||
EXPECT_TRUE(result == filePath);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ReplaceExtension_WStringPathWithForwardSlash_ReturnsUnalteredWString)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo.ext/";
|
||||
const wchar_t newExtension[] = L"new";
|
||||
wstring result = PathHelpers::ReplaceExtension(filePath, newExtension);
|
||||
EXPECT_TRUE(result == filePath);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ReplaceExtension_WStringPathWithColon_ReturnsUnalteredWString)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo.ext:";
|
||||
const wchar_t newExtension[] = L"new";
|
||||
wstring result = PathHelpers::ReplaceExtension(filePath, newExtension);
|
||||
EXPECT_TRUE(result == filePath);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ReplaceExtension_WStringPathEndsWithPeriod_ReturnsUnalteredWString)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo.ext.";
|
||||
const wchar_t newExtension[] = L"new";
|
||||
wstring result = PathHelpers::ReplaceExtension(filePath, newExtension);
|
||||
EXPECT_TRUE(result == filePath);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ReplaceExtension_WStringNewExtension_ReturnsWStringWithNewExtension)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo.ext";
|
||||
const wchar_t newExtension[] = L"new";
|
||||
const wchar_t expectedResult[] = L"foo.new";
|
||||
wstring result = PathHelpers::ReplaceExtension(filePath, newExtension);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveExtension_StringPathNoExtension_ReturnsUnalteredString)
|
||||
{
|
||||
const char* filePath = "foo";
|
||||
string result = PathHelpers::RemoveExtension(filePath);
|
||||
EXPECT_STREQ(filePath, result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveExtension_StringPath_ReturnsStringWithoutExtension)
|
||||
{
|
||||
const char* filePath = "foo.bar";
|
||||
string result = PathHelpers::RemoveExtension(filePath);
|
||||
EXPECT_STREQ("foo", result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveExtension_WStringPathNoExtension_ReturnsUnalteredWString)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo";
|
||||
wstring result = PathHelpers::RemoveExtension(filePath);
|
||||
EXPECT_TRUE(result == filePath);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveExtension_WStringPath_ReturnsWStringWithoutExtension)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo.bar";
|
||||
const wchar_t expectedResult[] = L"foo";
|
||||
wstring result = PathHelpers::RemoveExtension(filePath);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetDirectory_StringPathWithColon_RemovesCharactersAfterColon)
|
||||
{
|
||||
const char* filePath = "foo:bar";
|
||||
string result = PathHelpers::GetDirectory(filePath);
|
||||
EXPECT_STREQ("foo:", result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetDirectory_StringPathWithColonAsCharacterBeforeLastSeparator_RemovesCharactersAfterLastSeparator)
|
||||
{
|
||||
const char* filePath = "foo:/bar";
|
||||
string result = PathHelpers::GetDirectory(filePath);
|
||||
EXPECT_STREQ("foo:/", result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetDirectory_StringPathWithLastSeparatorAsFirstCharacter_ReturnsStringColon)
|
||||
{
|
||||
const char* filePath = ":foo";
|
||||
string result = PathHelpers::GetDirectory(filePath);
|
||||
EXPECT_STREQ(":", result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetDirectory_StringPathStartsWithForwardSlash_ReturnsFullString)
|
||||
{
|
||||
const char* filePath = "//foo";
|
||||
string result = PathHelpers::GetDirectory(filePath);
|
||||
EXPECT_STREQ(filePath, result);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetDirectory_StringPathStartsWithDoubleBackSlash_ReturnsFullString)
|
||||
{
|
||||
const char* filePath = "\\\\foo";
|
||||
string result = PathHelpers::GetDirectory(filePath);
|
||||
EXPECT_STREQ(filePath, result);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetDirectory_StringPath_ReturnsOnlyStringPath)
|
||||
{
|
||||
const char* filePath = "foobar/";
|
||||
string result = PathHelpers::GetDirectory(filePath);
|
||||
EXPECT_STREQ("foobar", result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetDirectory_WStringPathWithColon_RemovesCharactersAfterColon)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo:bar";
|
||||
const wchar_t expectedResult[] = L"foo:";
|
||||
wstring result = PathHelpers::GetDirectory(filePath);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetDirectory_WStringPathWithColonAsCharacterBeforeLastSeparator_RemovesCharactersAfterLastSeparator)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo:/bar";
|
||||
const wchar_t expectedResult[] = L"foo:/";
|
||||
wstring result = PathHelpers::GetDirectory(filePath);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetDirectory_WStringPathWithLastSeparatorAsFirstCharacter_ReturnsWStringColon)
|
||||
{
|
||||
const wchar_t filePath[] = L":foo";
|
||||
const wchar_t expectedResult[] = L":";
|
||||
wstring result = PathHelpers::GetDirectory(filePath);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetDirectory_WStringPathStartsWithForwardSlash_ReturnsFullWString)
|
||||
{
|
||||
const wchar_t filePath[] = L"//foo";
|
||||
wstring result = PathHelpers::GetDirectory(filePath);
|
||||
EXPECT_TRUE(result == filePath);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetDirectory_WStringPathStartsWithDoubleBackSlash_ReturnsFullWString)
|
||||
{
|
||||
const wchar_t filePath[] = L"\\\\foo";
|
||||
wstring result = PathHelpers::GetDirectory(filePath);
|
||||
EXPECT_TRUE(result == filePath);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetDirectory_WStringPath_ReturnsOnlyWStringPath)
|
||||
{
|
||||
const wchar_t filePath[] = L"foobar/";
|
||||
const wchar_t expectedResult[] = L"foobar";
|
||||
wstring result = PathHelpers::GetDirectory(filePath);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetFilename_StringPathStartsWithForwardSlash_ReturnsEmptyString)
|
||||
{
|
||||
const char* filePath = "/:foobar";
|
||||
string result = PathHelpers::GetFilename(filePath);
|
||||
EXPECT_STREQ("", result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetFilename_StringPathStartsWithDoubleBackSlash_ReturnsEmptyString)
|
||||
{
|
||||
const char* filePath = "\\:foobar";
|
||||
string result = PathHelpers::GetFilename(filePath);
|
||||
EXPECT_STREQ("", result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetFilename_StringPath_ReturnsStringFilename)
|
||||
{
|
||||
const char* filePath = "/foo/foo/foobar";
|
||||
string result = PathHelpers::GetFilename(filePath);
|
||||
EXPECT_STREQ("foobar", result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetFilename_WStringPathStartsWithForwardSlash_ReturnsEmptyWString)
|
||||
{
|
||||
const wchar_t filePath[] = L"/:foobar";
|
||||
const wchar_t expectedResult[] = L"";
|
||||
wstring result = PathHelpers::GetFilename(filePath);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetFilename_WStringPathStartsWithDoubleBackSlash_ReturnsEmptyWString)
|
||||
{
|
||||
const wchar_t filePath[] = L"\\:foobar";
|
||||
const wchar_t expectedResult[] = L"";
|
||||
wstring result = PathHelpers::GetFilename(filePath);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetFilename_WStringPath_ReturnsWStringFilename)
|
||||
{
|
||||
const wchar_t filePath[] = L"/foo/foo/foobar";
|
||||
const wchar_t expectedResult[] = L"foobar";
|
||||
wstring result = PathHelpers::GetFilename(filePath);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, AddSeparator_EmptyPath_ReturnsEmptyString)
|
||||
{
|
||||
const char* filePath = "";
|
||||
string result = PathHelpers::AddSeparator(filePath);
|
||||
EXPECT_STREQ(filePath, result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, AddSeparator_StringPathEndsWithForwardSlash_ReturnsStringPath)
|
||||
{
|
||||
const char* filePath = "foo/";
|
||||
string result = PathHelpers::AddSeparator(filePath);
|
||||
EXPECT_STREQ(filePath, result);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, AddSeparator_StringPathEndsWithDoubleBackSlash_ReturnsStringPath)
|
||||
{
|
||||
const char* filePath = "foo\\";
|
||||
string result = PathHelpers::AddSeparator(filePath);
|
||||
EXPECT_STREQ(filePath, result);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, AddSeparator_StringPathEndsWithColon_ReturnsStringPath)
|
||||
{
|
||||
const char* filePath = "foo:";
|
||||
string result = PathHelpers::AddSeparator(filePath);
|
||||
EXPECT_STREQ(filePath, result);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, AddSeparator_StringPath_ReturnsStringWithDoubleBackSlashAdded)
|
||||
{
|
||||
const char* filePath = "foo";
|
||||
string result = PathHelpers::AddSeparator(filePath);
|
||||
EXPECT_STREQ("foo\\", result);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, AddSeparator_EmptyPath_ReturnsEmptyWString)
|
||||
{
|
||||
const wchar_t filePath[] = L"";
|
||||
wstring result = PathHelpers::AddSeparator(filePath);
|
||||
EXPECT_TRUE(result == filePath);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, AddSeparator_WStringPathEndsWithForwardSlash_ReturnsWStringPath)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo/";
|
||||
wstring result = PathHelpers::AddSeparator(filePath);
|
||||
EXPECT_TRUE(result == filePath);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, AddSeparator_WStringPathEndsWithDoubleBackSlash_ReturnsWStringPath)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo\\";
|
||||
wstring result = PathHelpers::AddSeparator(filePath);
|
||||
EXPECT_TRUE(result == filePath);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, AddSeparator_WStringPathEndsWithColon_ReturnsWStringPath)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo:";
|
||||
wstring result = PathHelpers::AddSeparator(filePath);
|
||||
EXPECT_TRUE(result == filePath);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, AddSeparator_WStringPath_ReturnsWStringWithDoubleBackSlashAdded)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo";
|
||||
const wchar_t expectedResult[] = L"foo\\";
|
||||
wstring result = PathHelpers::AddSeparator(filePath);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveSeparator_EmptyStringPath_ReturnsEmptyString)
|
||||
{
|
||||
const char* filePath = "";
|
||||
string result = PathHelpers::RemoveSeparator(filePath);
|
||||
EXPECT_STREQ(filePath, result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveSeparator_StringPathEndsWithForwardSlash_ReturnsStringWithoutForwardSlash)
|
||||
{
|
||||
const char* filePath = "foo/";
|
||||
string result = PathHelpers::RemoveSeparator(filePath);
|
||||
EXPECT_STREQ("foo", result);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveSeparator_StringPathEndsWithDoubleBackSlash_ReturnsStringWithoutDoubleBackSlash)
|
||||
{
|
||||
const char* filePath = "foo\\";
|
||||
string result = PathHelpers::RemoveSeparator(filePath);
|
||||
EXPECT_STREQ("foo", result);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveSeparator_StringPath_ReturnsStringPath)
|
||||
{
|
||||
const char* filePath = "foo";
|
||||
string result = PathHelpers::RemoveSeparator(filePath);
|
||||
EXPECT_STREQ(filePath, result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveSeparator_EmptyWStringPath_ReturnsEmptyWString)
|
||||
{
|
||||
const wchar_t filePath[] = L"";
|
||||
wstring result = PathHelpers::RemoveSeparator(filePath);
|
||||
EXPECT_TRUE(result == filePath);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveSeparator_WStringPathEndsWithForwardSlash_ReturnsWStringWithoutForwardSlash)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo/";
|
||||
const wchar_t expectedResult[] = L"foo";
|
||||
wstring result = PathHelpers::RemoveSeparator(filePath);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveSeparator_WStringPathEndsWithDoubleBackSlash_ReturnsWStringWithoutDoubleBackSlash)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo\\";
|
||||
const wchar_t expectedResult[] = L"foo";
|
||||
wstring result = PathHelpers::RemoveSeparator(filePath);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveSeparator_WStringPath_ReturnsWStringPath)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo";
|
||||
wstring result = PathHelpers::RemoveSeparator(filePath);
|
||||
EXPECT_TRUE(result == filePath);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveDuplicateSeparators_StringPathLengthEqualOne_ReturnsStringPath)
|
||||
{
|
||||
const char* filePath = "f";
|
||||
string result = PathHelpers::RemoveDuplicateSeparators(filePath);
|
||||
EXPECT_STREQ(filePath, result);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveDuplicateSeparators_StringPathWithDuplicateBackSlashes_ReturnsStringWithoutDoubleBackSlashes)
|
||||
{
|
||||
const char* filePath = "foo\\\\bar";
|
||||
string result = PathHelpers::RemoveDuplicateSeparators(filePath);
|
||||
EXPECT_STREQ("foo\\bar", result);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveDuplicateSeparators_StringPathWithDuplicateForwardSlashes_ReturnsStringWithoutForwardSlashes)
|
||||
{
|
||||
const char* filePath = "foo//bar";
|
||||
string result = PathHelpers::RemoveDuplicateSeparators(filePath);
|
||||
EXPECT_STREQ("foo/bar", result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveDuplicateSeparators_WStringPathLengthEqualOne_ReturnsWStringPath)
|
||||
{
|
||||
const wchar_t filePath[] = L"f";
|
||||
wstring result = PathHelpers::RemoveDuplicateSeparators(filePath);
|
||||
EXPECT_TRUE(result == filePath);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveDuplicateSeparators_WStringPathWithDuplicateBackSlashes_ReturnsWStringWithoutDoubleBackSlashes)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo\\\\bar";
|
||||
const wchar_t expectedResult[] = L"foo\\bar";
|
||||
wstring result = PathHelpers::RemoveDuplicateSeparators(filePath);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, RemoveDuplicateSeparators_WStringPathWithDuplicateForwardSlashes_ReturnsWStringWithoutForwardSlashes)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo//bar";
|
||||
const wchar_t expectedResult[] = L"foo/bar";
|
||||
wstring result = PathHelpers::RemoveDuplicateSeparators(filePath);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, Join_EmptySecondStringPath_ReturnsFirstString)
|
||||
{
|
||||
const char* filePath1 = "foo";
|
||||
const char* filePath2 = "";
|
||||
string result = PathHelpers::Join(filePath1, filePath2);
|
||||
EXPECT_STREQ(filePath1, result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, Join_EmptyFirstStringPath_ReturnsSecondString)
|
||||
{
|
||||
const char* filePath1 = "";
|
||||
const char* filePath2 = "bar";
|
||||
string result = PathHelpers::Join(filePath1, filePath2);
|
||||
EXPECT_STREQ(filePath2, result);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, Join_StringPath_ReturnsStringAppendedWithDoubleBackSlashDivider)
|
||||
{
|
||||
const char* filePath1 = "foo";
|
||||
const char* filePath2 = "bar";
|
||||
string result = PathHelpers::Join(filePath1, filePath2);
|
||||
EXPECT_STREQ("foo\\bar", result);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, Join_FirstStringPathEndsWithForwardSlash_ReturnsAppendedString)
|
||||
{
|
||||
const char* filePath1 = "foo/";
|
||||
const char* filePath2 = "bar";
|
||||
string result = PathHelpers::Join(filePath1, filePath2);
|
||||
EXPECT_STREQ("foo/bar", result);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, Join_FirstStringPathEndsWithDoubleBackSlash_ReturnsAppendedString)
|
||||
{
|
||||
const char* filePath1 = "foo\\";
|
||||
const char* filePath2 = "bar";
|
||||
string result = PathHelpers::Join(filePath1, filePath2);
|
||||
EXPECT_STREQ("foo\\bar", result);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, Join_FirstStringPathEndsWithColon_ReturnsAppendedString)
|
||||
{
|
||||
const char* filePath1 = "foo:";
|
||||
const char* filePath2 = "bar";
|
||||
string result = PathHelpers::Join(filePath1, filePath2);
|
||||
EXPECT_STREQ("foo:bar", result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, Join_EmptySecondWStringPath_ReturnsFirstWString)
|
||||
{
|
||||
const wchar_t filePath1[] = L"foo";
|
||||
const wchar_t filePath2[] = L"";
|
||||
wstring result = PathHelpers::Join(filePath1, filePath2);
|
||||
EXPECT_TRUE(result == filePath1);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, Join_EmptyFirstWStringPath_ReturnsSecondWString)
|
||||
{
|
||||
const wchar_t filePath1[] = L"";
|
||||
const wchar_t filePath2[] = L"bar";
|
||||
wstring result = PathHelpers::Join(filePath1, filePath2);
|
||||
EXPECT_TRUE(result == filePath2);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, Join_WStringPath_ReturnsWStringAppendedWithDoubleBackSlashDivider)
|
||||
{
|
||||
const wchar_t filePath1[] = L"foo";
|
||||
const wchar_t filePath2[] = L"bar";
|
||||
const wchar_t expectedResult[] = L"foo\\bar";
|
||||
wstring result = PathHelpers::Join(filePath1, filePath2);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, Join_FirstWStringPathEndsWithForwardSlash_ReturnsAppendedWString)
|
||||
{
|
||||
const wchar_t filePath1[] = L"foo/";
|
||||
const wchar_t filePath2[] = L"bar";
|
||||
const wchar_t expectedResult[] = L"foo/bar";
|
||||
wstring result = PathHelpers::Join(filePath1, filePath2);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, Join_FirstWStringPathEndsWithDoubleBackSlash_ReturnsAppendedWString)
|
||||
{
|
||||
const wchar_t filePath1[] = L"foo\\";
|
||||
const wchar_t filePath2[] = L"bar";
|
||||
const wchar_t expectedResult[] = L"foo\\bar";
|
||||
wstring result = PathHelpers::Join(filePath1, filePath2);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, Join_FirstWStringPathEndsWithColon_ReturnsAppendedWString)
|
||||
{
|
||||
const wchar_t filePath1[] = L"foo:";
|
||||
const wchar_t filePath2[] = L"bar";
|
||||
const wchar_t expectedResult[] = L"foo:bar";
|
||||
wstring result = PathHelpers::Join(filePath1, filePath2);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, IsRelative_EmptyStringPath_ReturnsTrue)
|
||||
{
|
||||
const char* filePath = "";
|
||||
bool result = PathHelpers::IsRelative(filePath);
|
||||
EXPECT_TRUE(result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, IsRelative_StringPath_ReturnsTrue)
|
||||
{
|
||||
const char* filePath = "foo";
|
||||
bool result = PathHelpers::IsRelative(filePath);
|
||||
EXPECT_TRUE(result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, IsRelative_StringPathBeginsWithForwardSlash_ReturnsFalse)
|
||||
{
|
||||
const char* filePath = "/foo";
|
||||
bool result = PathHelpers::IsRelative(filePath);
|
||||
EXPECT_FALSE(result);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, IsRelative_StringPathBeginsWithDoubleBackSlash_ReturnsFalse)
|
||||
{
|
||||
const char* filePath = "\\foo";
|
||||
bool result = PathHelpers::IsRelative(filePath);
|
||||
EXPECT_FALSE (result);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, IsRelative_StringPathBeginsWithColon_ReturnsFalse)
|
||||
{
|
||||
const char* filePath = ":foo";
|
||||
bool result = PathHelpers::IsRelative(filePath);
|
||||
EXPECT_FALSE(result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, IsRelative_EmptyWStringPath_ReturnsTrue)
|
||||
{
|
||||
const wchar_t filePath[] = L"";
|
||||
bool result = PathHelpers::IsRelative(filePath);
|
||||
EXPECT_TRUE(result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, IsRelative_WStringPath_ReturnsTrue)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo";
|
||||
bool result = PathHelpers::IsRelative(filePath);
|
||||
EXPECT_TRUE(result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, IsRelative_WStringPathBeginsWithForwardSlash_ReturnsFalse)
|
||||
{
|
||||
const wchar_t filePath[] = L"/foo";
|
||||
bool result = PathHelpers::IsRelative(filePath);
|
||||
EXPECT_FALSE(result);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, IsRelative_WStringPathBeginsWithDoubleBackSlash_ReturnsFalse)
|
||||
{
|
||||
const wchar_t filePath[] = L"\\foo";
|
||||
bool result = PathHelpers::IsRelative(filePath);
|
||||
EXPECT_FALSE(result);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, IsRelative_WStringPathBeginsWithColon_ReturnsFalse)
|
||||
{
|
||||
const wchar_t filePath[] = L":foo";
|
||||
bool result = PathHelpers::IsRelative(filePath);
|
||||
EXPECT_FALSE(result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ToUnixPath_StringPath_ReturnsStringWithForwardSlashes)
|
||||
{
|
||||
const char* filePath = "foo\\foo\\foo";
|
||||
string result = PathHelpers::ToUnixPath(filePath);
|
||||
EXPECT_STREQ("foo/foo/foo", result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ToUnixPath_WStringPath_ReturnsWStringWithForwardSlashes)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo\\foo\\foo";
|
||||
const wchar_t expectedResult[] = L"foo/foo/foo";
|
||||
wstring result = PathHelpers::ToUnixPath(filePath);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ToDosPath_StringPath_ReturnsStringWithDoubleBackSlashes)
|
||||
{
|
||||
const char* filePath = "foo/foo/foo";
|
||||
string result = PathHelpers::ToDosPath(filePath);
|
||||
EXPECT_STREQ("foo\\foo\\foo", result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, ToDosPath_WStringPath_ReturnsStringWithDoubleBackSlashes)
|
||||
{
|
||||
const wchar_t filePath[] = L"foo/foo/foo";
|
||||
const wchar_t expectedResult[] = L"foo\\foo\\foo";
|
||||
wstring result = PathHelpers::ToDosPath(filePath);
|
||||
EXPECT_TRUE(result == expectedResult);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetAsciiPath_EmptyStringPath_ReturnsEmpty)
|
||||
{
|
||||
const char* filePath = "";
|
||||
string result = PathHelpers::GetAsciiPath(filePath);
|
||||
EXPECT_STREQ(filePath, result);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetAsciiPath_StringPath_ReturnsStringWithoutForwardSlash)
|
||||
{
|
||||
const char* filePath = "foo/bar/";
|
||||
string result = PathHelpers::GetAsciiPath(filePath);
|
||||
EXPECT_STREQ("foo\\bar", result);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, GetAsciiPath_EmptyWStringPath_ReturnsEmpty)
|
||||
{
|
||||
const wchar_t filePath[] = L"";
|
||||
string expectedResult = "";
|
||||
string result = PathHelpers::GetAsciiPath(filePath);
|
||||
EXPECT_STREQ(expectedResult, result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, CanonicalizePath_StringPathLengthLessThanThree_ReturnsStringWithoutForwardSlash)
|
||||
{
|
||||
const char* filePath = "./";
|
||||
string result = PathHelpers::CanonicalizePath(filePath);
|
||||
EXPECT_STREQ(".", result);
|
||||
}
|
||||
|
||||
TEST_F(CryCommonToolsPathHelpersTest, CanonicalizePath_StringPathStartsWithPeriodForwardSlash_ReturnsStringWithoutPeriodAndForwardSlash)
|
||||
{
|
||||
const char* filePath = "./foo";
|
||||
string result = PathHelpers::CanonicalizePath(filePath);
|
||||
EXPECT_STREQ("foo", result);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
TEST_F(CryCommonToolsPathHelpersTest, CanonicalizePath_StringPathStartsWithPeriodDoubleBackSlash_ReturnsStringWithoutPeriodAndDoubleBackSlash)
|
||||
{
|
||||
const char* filePath = ".\\foo";
|
||||
string result = PathHelpers::CanonicalizePath(filePath);
|
||||
EXPECT_STREQ("foo", result);
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
}
|
||||
|
||||
AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include <platform.h>
|
||||
#include <assert.h> // assert()
|
||||
#include "WeightFilterSet.h" // CWeightFilterSet
|
||||
|
||||
|
||||
|
||||
void CWeightFilterSet::FreeData()
|
||||
{
|
||||
m_FilterKernelBlock.FreeData();
|
||||
}
|
||||
|
||||
|
||||
bool CWeightFilterSet::Create(const unsigned long indwSideLength, const CSummedAreaFilterKernel& inFilter, const float infR)
|
||||
{
|
||||
assert(indwSideLength >= 1);
|
||||
|
||||
FreeData();
|
||||
|
||||
// 32 Baustelle
|
||||
inFilter.CreateWeightFilterBlock(m_FilterKernelBlock, 1, infR * indwSideLength);
|
||||
return(true);
|
||||
}
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#pragma once
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_WEIGHTFILTERSET_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_WEIGHTFILTERSET_H
|
||||
|
||||
|
||||
#include "SimpleBitmap.h" // SimpleBitmap<>
|
||||
#include <vector> // STL vector<>
|
||||
#include "SummedAreaFilterKernel.h" // CSummedAreaFilterKernel
|
||||
|
||||
class CWeightFilterSet
|
||||
{
|
||||
public:
|
||||
|
||||
//! /param indwSideLength [1,..[ e.g. 3 for 3x3 block
|
||||
bool Create(const unsigned long indwSideLength, const CSummedAreaFilterKernel& inFilter, const float infR);
|
||||
|
||||
//!
|
||||
void FreeData();
|
||||
|
||||
//! optimizable
|
||||
//! weight is 1.0
|
||||
//! /param iniX x position in inoutDest
|
||||
//! /param iniY y position in inoutDest
|
||||
//! /param TInputImage typically CSimpleBitmap<TElement>
|
||||
//! /return weight
|
||||
template <class TElement, class TInputImage >
|
||||
float GetBlockWithFilter(const TInputImage& inSrc, const int iniX, const int iniY, TElement& outResult)
|
||||
{
|
||||
float fWeightSum = 0.0f;
|
||||
CSimpleBitmap<float>& rBitmap = m_FilterKernelBlock;
|
||||
|
||||
int W = (int)rBitmap.GetWidth();
|
||||
int H = (int)rBitmap.GetHeight();
|
||||
|
||||
int iSrcW = (int)inSrc.GetWidth();
|
||||
int iSrcH = (int)inSrc.GetHeight();
|
||||
|
||||
float* pfWeights = rBitmap.GetPointer(0, 0);
|
||||
|
||||
for (int y = 0; y < H; y++)
|
||||
{
|
||||
int iDestY = y + iniY - H / 2;
|
||||
|
||||
// optimizable (don't use the bottom border)
|
||||
// if(iDestY==iSrcH){ pfWeights+=H;continue; }
|
||||
|
||||
for (int x = 0; x < W; x++, pfWeights++)
|
||||
{
|
||||
int iDestX = x + iniX - W / 2;
|
||||
|
||||
// optimizable (don't use the right border)
|
||||
// if(iDestX==iSrcW)
|
||||
// continue;
|
||||
|
||||
TElement Value;
|
||||
|
||||
// if(inSrc.Get(iDestX,iDestY,Value))
|
||||
if (inSrc.Get((iDestX + iSrcW * 2) % iSrcW, (iDestY + iSrcH * 2) % iSrcH, Value)) // tiled
|
||||
{
|
||||
float fWeight = *pfWeights;
|
||||
|
||||
outResult += Value * fWeight;
|
||||
fWeightSum += fWeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fWeightSum;
|
||||
}
|
||||
|
||||
int GetBorderSize()
|
||||
{
|
||||
int W = (int)m_FilterKernelBlock.GetWidth();
|
||||
|
||||
return (W - 1) / 2;
|
||||
}
|
||||
|
||||
private: // -------------------------------------------------------------
|
||||
|
||||
CSimpleBitmap<float> m_FilterKernelBlock; //!< weight = 1
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_WEIGHTFILTERSET_H
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include <platform.h>
|
||||
#include "XMLPakFileSink.h"
|
||||
#include "StringHelpers.h"
|
||||
|
||||
XMLPakFileSink::XMLPakFileSink(IPakSystem* pakSystem, const string& archivePath, const string& filePath)
|
||||
: pakSystem(pakSystem)
|
||||
, filePath(filePath)
|
||||
{
|
||||
archive = pakSystem->OpenArchive(archivePath.c_str());
|
||||
}
|
||||
|
||||
XMLPakFileSink::~XMLPakFileSink()
|
||||
{
|
||||
if (archive && pakSystem)
|
||||
{
|
||||
SYSTEMTIME st;
|
||||
GetSystemTime(&st);
|
||||
|
||||
FILETIME ft;
|
||||
ZeroStruct(ft);
|
||||
const BOOL ok = SystemTimeToFileTime(&st, &ft);
|
||||
|
||||
LARGE_INTEGER lt;
|
||||
lt.HighPart = ft.dwHighDateTime;
|
||||
lt.LowPart = ft.dwLowDateTime;
|
||||
|
||||
const __int64 modTime = lt.QuadPart;
|
||||
;
|
||||
|
||||
pakSystem->AddToArchive(archive, filePath.c_str(), &data[0], int(data.size()), modTime);
|
||||
pakSystem->CloseArchive(archive);
|
||||
}
|
||||
}
|
||||
|
||||
void XMLPakFileSink::Write(const char* text)
|
||||
{
|
||||
string asciiText = text;
|
||||
int len = int(asciiText.size());
|
||||
int start = int(data.size());
|
||||
data.resize(data.size() + len);
|
||||
memcpy(&data[start], asciiText.c_str(), len);
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_XMLPAKFILESINK_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_XMLPAKFILESINK_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "XMLWriter.h"
|
||||
#include "IPakSystem.h"
|
||||
|
||||
class XMLPakFileSink
|
||||
: public IXMLSink
|
||||
{
|
||||
public:
|
||||
XMLPakFileSink(IPakSystem* pakSystem, const string& archivePath, const string& filePath);
|
||||
~XMLPakFileSink();
|
||||
|
||||
// IXMLSink
|
||||
virtual void Write(const char* text);
|
||||
|
||||
private:
|
||||
IPakSystem* pakSystem;
|
||||
PakSystemArchive* archive;
|
||||
string filePath;
|
||||
std::vector<char> data;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_XMLPAKFILESINK_H
|
||||
@@ -1,261 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include <platform.h>
|
||||
#include "XMLWriter.h"
|
||||
#include "StringHelpers.h"
|
||||
#include <cstdarg>
|
||||
|
||||
XMLWriter::XMLWriter(IXMLSink* sink)
|
||||
{
|
||||
m_indentationSize = -1;
|
||||
m_sink = sink;
|
||||
|
||||
WriteText("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
|
||||
}
|
||||
|
||||
void XMLWriter::BeginElement(const string& name)
|
||||
{
|
||||
// Write the indentation.
|
||||
if (m_newLine)
|
||||
{
|
||||
for (int i = 0; i < m_indentationSize; ++i)
|
||||
{
|
||||
WriteText(" ");
|
||||
}
|
||||
}
|
||||
|
||||
WriteText("<%s", name.c_str());
|
||||
m_newLine = false;
|
||||
}
|
||||
|
||||
void XMLWriter::EndElement(const string& name)
|
||||
{
|
||||
// Write the indentation.
|
||||
if (m_newLine)
|
||||
{
|
||||
for (int i = 0; i < m_indentationSize; ++i)
|
||||
{
|
||||
WriteText(" ");
|
||||
}
|
||||
}
|
||||
|
||||
WriteText("</%s>\n", name.c_str());
|
||||
m_newLine = true;
|
||||
}
|
||||
|
||||
void XMLWriter::CloseElement(const string& name, bool newLine)
|
||||
{
|
||||
if (newLine)
|
||||
{
|
||||
WriteText(">\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteText(">");
|
||||
}
|
||||
m_newLine = newLine;
|
||||
}
|
||||
|
||||
void XMLWriter::CloseLeafElement(const string& name)
|
||||
{
|
||||
WriteText(" />\n");
|
||||
m_newLine = true;
|
||||
}
|
||||
|
||||
void XMLWriter::IncreaseIndentation()
|
||||
{
|
||||
++m_indentationSize;
|
||||
}
|
||||
|
||||
void XMLWriter::DecreaseIndentation()
|
||||
{
|
||||
--m_indentationSize;
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttribute(const string& name, const string& value)
|
||||
{
|
||||
WriteText(" %s=\"%s\"", name.c_str(), value.c_str());
|
||||
}
|
||||
|
||||
void XMLWriter::SerializeAttribute(char* buffer, size_t bufferSize, const string& value)
|
||||
{
|
||||
// TODO: Escape string.
|
||||
strcpy_s(buffer, bufferSize, value.c_str());
|
||||
}
|
||||
|
||||
void XMLWriter::SerializeAttribute(char* buffer, size_t bufferSize, float value)
|
||||
{
|
||||
sprintf_s(buffer, bufferSize, "%.10e", value);
|
||||
}
|
||||
|
||||
void XMLWriter::SerializeAttribute(char* buffer, size_t bufferSize, int value)
|
||||
{
|
||||
sprintf_s(buffer, bufferSize, "%d", value);
|
||||
}
|
||||
|
||||
void XMLWriter::SerializeArrayElement(char* buffer, size_t bufferSize, float value)
|
||||
{
|
||||
sprintf_s(buffer, bufferSize, "%.10e", value);
|
||||
}
|
||||
|
||||
void XMLWriter::SerializeArrayElement(char* buffer, size_t bufferSize, const string& value)
|
||||
{
|
||||
strcpy(buffer, value.c_str());
|
||||
}
|
||||
|
||||
void XMLWriter::SerializeArrayElement(char* buffer, size_t bufferSize, int value)
|
||||
{
|
||||
sprintf_s(buffer, bufferSize, "%d", value);
|
||||
}
|
||||
|
||||
void XMLWriter::WriteContent(const string& text)
|
||||
{
|
||||
WriteText("%s", text.c_str());
|
||||
}
|
||||
|
||||
void XMLWriter::WriteContentLine(const string& text)
|
||||
{
|
||||
// Write the indentation.
|
||||
if (m_newLine)
|
||||
{
|
||||
for (int i = 0; i < m_indentationSize; ++i)
|
||||
{
|
||||
WriteText(" ");
|
||||
}
|
||||
}
|
||||
|
||||
WriteText("%s\n", text.c_str());
|
||||
m_newLine = true;
|
||||
}
|
||||
|
||||
void XMLWriter::WriteText(const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
char buffer[40000];
|
||||
azvsnprintf(buffer, sizeof(buffer), format, args);
|
||||
m_sink->Write(buffer);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
XMLWriter::Element::Element(XMLWriter& writer, const string& name, bool output)
|
||||
: m_writer(writer)
|
||||
, m_name(name)
|
||||
, m_output(output)
|
||||
, isParent(false)
|
||||
{
|
||||
if (!m_writer.m_elements.empty())
|
||||
{
|
||||
Element* parent = m_writer.m_elements.back();
|
||||
if (!parent->isParent)
|
||||
{
|
||||
parent->isParent = true;
|
||||
if (parent->m_output)
|
||||
{
|
||||
m_writer.CloseElement(m_name, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_writer.m_elements.push_back(this);
|
||||
if (m_output)
|
||||
{
|
||||
m_writer.IncreaseIndentation();
|
||||
}
|
||||
if (m_output)
|
||||
{
|
||||
m_writer.BeginElement(m_name);
|
||||
}
|
||||
}
|
||||
|
||||
XMLWriter::Element::~Element()
|
||||
{
|
||||
if (m_output)
|
||||
{
|
||||
if (isParent)
|
||||
{
|
||||
m_writer.EndElement(m_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_writer.CloseLeafElement(m_name);
|
||||
}
|
||||
}
|
||||
m_writer.m_elements.pop_back();
|
||||
if (m_output)
|
||||
{
|
||||
m_writer.DecreaseIndentation();
|
||||
}
|
||||
}
|
||||
|
||||
void XMLWriter::Element::Child(const string& name, const string& value)
|
||||
{
|
||||
Element child(m_writer, name);
|
||||
child.Content(value);
|
||||
}
|
||||
|
||||
void XMLWriter::Element::Content(const string& text)
|
||||
{
|
||||
if (m_output)
|
||||
{
|
||||
assert(!isParent);
|
||||
if (!isParent)
|
||||
{
|
||||
isParent = true;
|
||||
m_writer.CloseElement(m_name, false);
|
||||
}
|
||||
m_writer.WriteContent(text);
|
||||
}
|
||||
}
|
||||
|
||||
void XMLWriter::Element::ContentLine(const string& text)
|
||||
{
|
||||
if (!isParent)
|
||||
{
|
||||
isParent = true;
|
||||
if (m_output)
|
||||
{
|
||||
m_writer.CloseElement(m_name, true);
|
||||
}
|
||||
}
|
||||
if (m_output)
|
||||
{
|
||||
m_writer.WriteContentLine(text);
|
||||
}
|
||||
}
|
||||
|
||||
XMLFileSink::XMLFileSink(const string& filename)
|
||||
{
|
||||
m_file = std::fopen(filename.c_str(), "w");
|
||||
if (!m_file)
|
||||
{
|
||||
throw OpenFailedError("Unable to open file.");
|
||||
}
|
||||
}
|
||||
|
||||
XMLFileSink::~XMLFileSink()
|
||||
{
|
||||
if (m_file)
|
||||
{
|
||||
fclose(m_file);
|
||||
}
|
||||
}
|
||||
|
||||
void XMLFileSink::Write(const char* text)
|
||||
{
|
||||
if (m_file)
|
||||
{
|
||||
string asciiText = StringHelpers::ConvertString<string>(text);
|
||||
fwrite(asciiText.c_str(), 1, asciiText.size(), m_file);
|
||||
}
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_XMLWRITER_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_XMLWRITER_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "Exceptions.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
class IXMLSink
|
||||
{
|
||||
public:
|
||||
// Define an exception type to throw when file opening fails.
|
||||
struct OpenFailedErrorTag {};
|
||||
typedef Exception<OpenFailedErrorTag> OpenFailedError;
|
||||
|
||||
virtual void Write(const char* text) = 0;
|
||||
};
|
||||
|
||||
class XMLFileSink
|
||||
: public IXMLSink
|
||||
{
|
||||
public:
|
||||
XMLFileSink(const string& name);
|
||||
~XMLFileSink();
|
||||
|
||||
virtual void Write(const char* text);
|
||||
|
||||
private:
|
||||
FILE* m_file;
|
||||
};
|
||||
|
||||
class XMLWriter
|
||||
{
|
||||
public:
|
||||
XMLWriter(IXMLSink* sink);
|
||||
|
||||
class Element
|
||||
{
|
||||
public:
|
||||
Element(XMLWriter& writer, const string& name, bool output = true);
|
||||
~Element();
|
||||
|
||||
template <typename T>
|
||||
void Attribute(const string& name, const T& value);
|
||||
void Child(const string& name, const string& value);
|
||||
void Content(const string& text);
|
||||
void ContentLine(const string& text);
|
||||
template <typename T>
|
||||
void ContentArrayElement(const T& value);
|
||||
void ContentArrayFloat24(const float floatBuffer[24], const int entryCount);
|
||||
|
||||
void WriteDirectText(const char* text)
|
||||
{
|
||||
if (!isParent)
|
||||
{
|
||||
isParent = true;
|
||||
if (m_output)
|
||||
{
|
||||
m_writer.CloseElement(m_name, false);
|
||||
}
|
||||
}
|
||||
m_writer.WriteDirectText(text);
|
||||
}
|
||||
|
||||
private:
|
||||
XMLWriter& m_writer;
|
||||
string m_name;
|
||||
bool isParent;
|
||||
bool m_output;
|
||||
};
|
||||
|
||||
void WriteDirectText(const char* text)
|
||||
{
|
||||
m_sink->Write(text);
|
||||
}
|
||||
|
||||
private:
|
||||
void IncreaseIndentation();
|
||||
void DecreaseIndentation();
|
||||
|
||||
void BeginElement(const string& name);
|
||||
void EndElement(const string& name);
|
||||
void CloseElement(const string& name, bool newLine);
|
||||
void CloseLeafElement(const string& name);
|
||||
|
||||
void WriteAttribute(const string& name, const string& value);
|
||||
static void SerializeAttribute(char* buffer, size_t bufferSize, const string& value);
|
||||
static void SerializeAttribute(char* buffer, size_t bufferSize, float value);
|
||||
static void SerializeAttribute(char* buffer, size_t bufferSize, int value);
|
||||
static void SerializeArrayElement(char* buffer, size_t bufferSize, float value);
|
||||
static void SerializeArrayElement(char* buffer, size_t bufferSize, const string& value);
|
||||
static void SerializeArrayElement(char* buffer, size_t bufferSize, int value);
|
||||
void WriteContent(const string& text);
|
||||
void WriteContentLine(const string& text);
|
||||
|
||||
void WriteText(const char* format, ...);
|
||||
|
||||
IXMLSink* m_sink;
|
||||
int m_indentationSize;
|
||||
|
||||
std::vector<Element*> m_elements;
|
||||
bool m_newLine;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void XMLWriter::Element::Attribute(const string& name, const T& value)
|
||||
{
|
||||
assert(!isParent);
|
||||
char buffer[1024];
|
||||
XMLWriter::SerializeAttribute(buffer, sizeof(buffer), value);
|
||||
if (m_output)
|
||||
{
|
||||
m_writer.WriteAttribute(name, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void XMLWriter::Element::ContentArrayElement(const T& value)
|
||||
{
|
||||
if (!m_output)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isParent)
|
||||
{
|
||||
isParent = true;
|
||||
m_writer.CloseElement(m_name, false);
|
||||
}
|
||||
|
||||
char buffer[1024] = {' ', 0};
|
||||
XMLWriter::SerializeArrayElement(buffer + 1, sizeof(buffer) - 1, value);
|
||||
|
||||
m_writer.WriteDirectText(buffer);
|
||||
}
|
||||
|
||||
inline void XMLWriter::Element::ContentArrayFloat24(const float floatBuffer[24], const int entryCount)
|
||||
{
|
||||
if (!m_output)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!isParent)
|
||||
{
|
||||
isParent = true;
|
||||
m_writer.CloseElement(m_name, false);
|
||||
}
|
||||
|
||||
char buffer[2048];
|
||||
if (entryCount == 24)
|
||||
{
|
||||
sprintf_s(buffer, " %.10e %.10e %.10e %.10e %.10e %.10e %.10e %.10e %.10e %.10e %.10e %.10e %.10e %.10e %.10e %.10e %.10e %.10e %.10e %.10e %.10e %.10e %.10e %.10e",
|
||||
floatBuffer[0], floatBuffer[1], floatBuffer[2], floatBuffer[3], floatBuffer[4], floatBuffer[5], floatBuffer[6], floatBuffer[7],
|
||||
floatBuffer[8], floatBuffer[9], floatBuffer[10], floatBuffer[11], floatBuffer[12], floatBuffer[13], floatBuffer[14], floatBuffer[15],
|
||||
floatBuffer[16], floatBuffer[17], floatBuffer[18], floatBuffer[19], floatBuffer[20], floatBuffer[21], floatBuffer[22], floatBuffer[23]);
|
||||
m_writer.WriteDirectText(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < entryCount; i++)
|
||||
{
|
||||
char buffer[1024];
|
||||
sprintf_s(buffer, " %.10e", floatBuffer[i]);
|
||||
m_writer.WriteDirectText(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_XMLWRITER_H
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_ZIPDIR_ZIPDIR_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_ZIPDIR_ZIPDIR_H
|
||||
#pragma once
|
||||
|
||||
#include "smartptr.h"
|
||||
#include "ZipFileFormat.h"
|
||||
#include "zipdirstructures.h"
|
||||
#include "smartptr.h"
|
||||
#include "ZipDirTree.h"
|
||||
#include "ZipDirList.h"
|
||||
#include "ZipDirCache.h"
|
||||
#include "ZipDirCacheRW.h"
|
||||
#include "ZipDirCacheFactory.h"
|
||||
#include "ZipDirFind.h"
|
||||
#include "ZipDirFindRW.h"
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_ZIPDIR_ZIPDIR_H
|
||||
@@ -1,298 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
|
||||
#include <smartptr.h>
|
||||
#include "FileUtil.h"
|
||||
#include "ZipFileFormat.h"
|
||||
#include "zipdirstructures.h"
|
||||
#include "ZipDirTree.h"
|
||||
#include "ZipDirCache.h"
|
||||
#include "ZipDirFind.h"
|
||||
#include "ZipDirCacheFactory.h"
|
||||
#include <zlib.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include "PathHelpers.h"
|
||||
#include <ZipDir/ZipDir_Traits_Platform.h>
|
||||
|
||||
using namespace ZipFile;
|
||||
|
||||
// initializes the instance structure
|
||||
void ZipDir::Cache::Construct(FILE* fNew, size_t nDataSizeIn, const EncryptionKey& key)
|
||||
{
|
||||
m_nRefCount = 0;
|
||||
m_pFile = fNew;
|
||||
m_nDataSize = nDataSizeIn;
|
||||
m_nZipPathOffset = nDataSizeIn;
|
||||
m_bEncryptHeaders = false;
|
||||
m_encryptionKey = key;
|
||||
}
|
||||
|
||||
// self-destruct when ref count drops to 0
|
||||
void ZipDir::Cache::Delete()
|
||||
{
|
||||
if (m_pFile)
|
||||
{
|
||||
fclose (m_pFile);
|
||||
}
|
||||
free(this);
|
||||
}
|
||||
|
||||
// looks for the given file record in the Central Directory. If there's none, returns NULL.
|
||||
// if there is some, returns the pointer to it.
|
||||
// the Path must be the relative path to the file inside the Zip
|
||||
// if the file handle is passed, it will be used to find the file data offset, if one hasn't been initialized yet
|
||||
ZipDir::FileEntry* ZipDir::Cache::FindFile (const char* szPath, [[maybe_unused]] bool bRefresh)
|
||||
{
|
||||
ZipDir::FindFile fd (this);
|
||||
if (!fd.FindExact(szPath))
|
||||
{
|
||||
assert (!fd.GetFileEntry());
|
||||
return NULL;
|
||||
}
|
||||
assert (fd.GetFileEntry());
|
||||
return fd.GetFileEntry();
|
||||
}
|
||||
|
||||
// loads the given file into the pCompressed buffer (the actual compressed data)
|
||||
// if the pUncompressed buffer is supplied, uncompresses the data there
|
||||
// buffers must have enough memory allocated, according to the info in the FileEntry
|
||||
// NOTE: there's no need to decompress if the method is 0 (store)
|
||||
// returns 0 if successful or error code if couldn't do something
|
||||
ZipDir::ErrorEnum ZipDir::Cache::ReadFile (FileEntry* pFileEntry, void* pCompressed, void* pUncompressed)
|
||||
{
|
||||
if (!pFileEntry)
|
||||
{
|
||||
return ZD_ERROR_INVALID_CALL;
|
||||
}
|
||||
|
||||
if (pFileEntry->desc.lSizeUncompressed == 0)
|
||||
{
|
||||
assert (pFileEntry->desc.lSizeCompressed == 0);
|
||||
return ZD_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
assert (pFileEntry->desc.lSizeCompressed > 0);
|
||||
|
||||
ErrorEnum nError = Refresh(pFileEntry);
|
||||
if (nError != ZD_ERROR_SUCCESS)
|
||||
{
|
||||
return nError;
|
||||
}
|
||||
|
||||
if (AZ_TRAIT_CRYCOMMONTOOLS_FSEEK(m_pFile, pFileEntry->nFileDataOffset, SEEK_SET))
|
||||
{
|
||||
return ZD_ERROR_IO_FAILED;
|
||||
}
|
||||
|
||||
SmartPtr pBufferDestroyer;
|
||||
|
||||
void* pBuffer = pCompressed; // the buffer where the compressed data will go
|
||||
|
||||
if (pFileEntry->nMethod == 0 && pUncompressed)
|
||||
{
|
||||
// we can directly read into the uncompress buffer
|
||||
pBuffer = pUncompressed;
|
||||
}
|
||||
|
||||
if (!pBuffer)
|
||||
{
|
||||
if (!pUncompressed)
|
||||
{
|
||||
// what's the sense of it - no buffers at all?
|
||||
return ZD_ERROR_INVALID_CALL;
|
||||
}
|
||||
|
||||
pBuffer = malloc(pFileEntry->desc.lSizeCompressed);
|
||||
pBufferDestroyer.Attach(pBuffer); // we want it auto-freed once we return
|
||||
}
|
||||
|
||||
|
||||
if (fread (pBuffer, pFileEntry->desc.lSizeCompressed, 1, m_pFile) != 1)
|
||||
{
|
||||
return ZD_ERROR_IO_FAILED;
|
||||
}
|
||||
|
||||
if (pFileEntry->nMethod == METHOD_DEFLATE_AND_ENCRYPT)
|
||||
{
|
||||
ZipDir::Decrypt((char*)pBuffer, pFileEntry->desc.lSizeCompressed, m_encryptionKey);
|
||||
}
|
||||
|
||||
// if there's a buffer for uncompressed data, uncompress it to that buffer
|
||||
if (pUncompressed)
|
||||
{
|
||||
if (pFileEntry->nMethod == 0)
|
||||
{
|
||||
assert (pBuffer == pUncompressed);
|
||||
//assert (pFileEntry->desc.lSizeCompressed == pFileEntry->nSizeUncompressed);
|
||||
//memcpy (pUncompressed, pBuffer, pFileEntry->desc.lSizeCompressed);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long nSizeUncompressed = pFileEntry->desc.lSizeUncompressed;
|
||||
if (Z_OK != ZipRawUncompress(pUncompressed, &nSizeUncompressed, pBuffer, pFileEntry->desc.lSizeCompressed))
|
||||
{
|
||||
return ZD_ERROR_CORRUPTED_DATA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ZD_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// loads and unpacks the file into a newly created buffer (that must be subsequently freed with
|
||||
// Free()) Returns NULL if failed
|
||||
void* ZipDir::Cache::AllocAndReadFile (FileEntry* pFileEntry)
|
||||
{
|
||||
if (!pFileEntry)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* pData = malloc(pFileEntry->desc.lSizeUncompressed);
|
||||
if (pData)
|
||||
{
|
||||
if (ZD_ERROR_SUCCESS != ReadFile (pFileEntry, NULL, pData))
|
||||
{
|
||||
free(pData);
|
||||
pData = NULL;
|
||||
}
|
||||
}
|
||||
return pData;
|
||||
}
|
||||
|
||||
// frees the memory block that was previously allocated by AllocAndReadFile
|
||||
void ZipDir::Cache::Free (void* pData)
|
||||
{
|
||||
free(pData);
|
||||
}
|
||||
|
||||
// refreshes information about the given file entry into this file entry
|
||||
ZipDir::ErrorEnum ZipDir::Cache::Refresh (FileEntry* pFileEntry)
|
||||
{
|
||||
if (!pFileEntry)
|
||||
{
|
||||
return ZD_ERROR_INVALID_CALL;
|
||||
}
|
||||
|
||||
if (pFileEntry->nFileDataOffset != pFileEntry->INVALID_DATA_OFFSET)
|
||||
{
|
||||
return ZD_ERROR_SUCCESS; // the data offset has been successfully read..
|
||||
}
|
||||
|
||||
return ZipDir::Refresh(m_pFile, pFileEntry, m_bEncryptHeaders);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
uint32 ZipDir::Cache::GetFileDataOffset(FileEntry* pFileEntry)
|
||||
{
|
||||
if (pFileEntry->nFileDataOffset == pFileEntry->INVALID_DATA_OFFSET)
|
||||
{
|
||||
ZipDir::Refresh (m_pFile, pFileEntry, m_bEncryptHeaders);
|
||||
}
|
||||
return pFileEntry->nFileDataOffset;
|
||||
}
|
||||
|
||||
// returns the size of memory occupied by the instance referred to by this cache
|
||||
// must be exact, because it's used by CacheRW to reallocate this cache
|
||||
size_t ZipDir::Cache::GetSize() const
|
||||
{
|
||||
return m_nDataSize + sizeof(Cache) + strlen(GetFilePath());
|
||||
}
|
||||
|
||||
|
||||
// QUICK check to determine whether the file entry belongs to this object
|
||||
bool ZipDir::Cache::IsOwnerOf (const FileEntry* pFileEntry) const
|
||||
{
|
||||
// just check whether the pointer is within the memory block of this cache instance
|
||||
return ((ULONG_PTR)pFileEntry >= (ULONG_PTR)(GetRoot() + 1)
|
||||
&& (ULONG_PTR)pFileEntry <= ((ULONG_PTR)GetRoot()) + m_nDataSize - sizeof(FileEntry));
|
||||
}
|
||||
|
||||
bool ZipDir::Cache::UnpakToDisk(const string& destFolder)
|
||||
{
|
||||
return UnpakToDiskInternal(GetRoot(), destFolder);
|
||||
}
|
||||
|
||||
bool ZipDir::Cache::UnpakToDiskInternal(ZipDir::DirHeader* folder, const string& destFolder)
|
||||
{
|
||||
if (!folder)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!FileUtil::EnsureDirectoryExists(destFolder.c_str()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
for (ZipFile::ushort fileNum = 0; fileNum < folder->numFiles; ++fileNum)
|
||||
{
|
||||
ZipDir::FileEntry* fileEntry = folder->GetFileEntry(fileNum);
|
||||
if (!fileEntry)
|
||||
{
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
string filePath = PathHelpers::Join(destFolder, fileEntry->GetName(folder->GetNamePool()));
|
||||
AZ::IO::SystemFile file;
|
||||
if (!file.Open(filePath.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_WRITE | AZ::IO::SystemFile::SF_OPEN_CREATE))
|
||||
{
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!fileEntry->desc.lSizeUncompressed)
|
||||
{
|
||||
// Nothing to write. Just close the file.
|
||||
file.Close();
|
||||
continue;
|
||||
}
|
||||
|
||||
AZStd::vector<AZ::u8> buffer(fileEntry->desc.lSizeUncompressed);
|
||||
if (ReadFile(fileEntry, nullptr, buffer.data()) == ZD_ERROR_SUCCESS)
|
||||
{
|
||||
file.Write(buffer.data(), buffer.size());
|
||||
file.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
file.Close();
|
||||
AZ::IO::SystemFile::Delete(filePath.c_str());
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (ZipFile::ushort dirNum = 0; dirNum < folder->numDirs; ++dirNum)
|
||||
{
|
||||
ZipDir::DirEntry* entry = folder->GetSubdirEntry(dirNum);
|
||||
if (!entry)
|
||||
{
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
string newPath = PathHelpers::Join(destFolder, entry->GetName(folder->GetNamePool()));
|
||||
if (!UnpakToDiskInternal(entry->GetDirectory(), newPath))
|
||||
{
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
// Declarations of the class used to parse and cache Zipped directory.
|
||||
// This class is actually an auto-pointer to the instance of the cache, so it can
|
||||
// be easily passed by value.
|
||||
// The cache instance contains the optimized for memory usage and fast search tree
|
||||
// of the files/directories inside the zip; each file has a descriptor with the
|
||||
// info about where its compressed data lies within the file
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_ZIPDIR_ZIPDIRCACHE_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_ZIPDIR_ZIPDIRCACHE_H
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// THe Zip Dir uses a special memory layout for keeping the structure of zip file.
|
||||
// This layout is optimized for small memory footprint (for big zip files)
|
||||
// and quick binary-search access to the individual files.
|
||||
//
|
||||
// The serialized layout consists of a number of directory records.
|
||||
// Each directory record starts with the DirHeader structure, then
|
||||
// it has an array of DirEntry structures (sorted by name),
|
||||
// array of FileEntry structures (sorted by name) and then
|
||||
// the pool of names, followed by pad bytes to align the whole directory
|
||||
// record on 4-byte boundray.
|
||||
|
||||
namespace ZipDir
|
||||
{
|
||||
// this is the header of the instance data allocated dynamically
|
||||
// it contains the FILE* : it owns it and closes upon destruction
|
||||
struct Cache
|
||||
{
|
||||
void AddRef() { ++m_nRefCount; }
|
||||
void Release()
|
||||
{
|
||||
if (--m_nRefCount <= 0)
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
}
|
||||
int NumRefs() const { return m_nRefCount; }
|
||||
|
||||
// looks for the given file record in the Central Directory. If there's none, returns NULL.
|
||||
// if there is some, returns the pointer to it.
|
||||
// the Path must be the relative path to the file inside the Zip
|
||||
// if the file handle is passed, it will be used to find the file data offset, if one hasn't been initialized yet
|
||||
// if bFull is true, then the full information about the file is returned (the offset to the data may be unknown at this point)-
|
||||
// if needed, the file is accessed and the information is loaded
|
||||
FileEntry* FindFile (const char* szPath, bool bFullInfo = false);
|
||||
|
||||
// loads the given file into the pCompressed buffer (the actual compressed data)
|
||||
// if the pUncompressed buffer is supplied, uncompresses the data there
|
||||
// buffers must have enough memory allocated, according to the info in the FileEntry
|
||||
// NOTE: there's no need to decompress if the method is 0 (store)
|
||||
// returns 0 if successful or error code if couldn't do something
|
||||
ErrorEnum ReadFile (FileEntry* pFileEntry, void* pCompressed, void* pUncompressed);
|
||||
|
||||
// loads and unpacks the file into a newly created buffer (that must be subsequently freed with
|
||||
// Free()) Returns NULL if failed
|
||||
void* AllocAndReadFile (FileEntry* pFileEntry);
|
||||
|
||||
// frees the memory block that was previously allocated by AllocAndReadFile
|
||||
void Free (void*);
|
||||
|
||||
// refreshes information about the given file entry into this file entry
|
||||
ErrorEnum Refresh (FileEntry* pFileEntry);
|
||||
|
||||
// Return FileEntity data offset inside zip file.
|
||||
uint32 GetFileDataOffset(FileEntry* pFileEntry);
|
||||
|
||||
|
||||
// returns the root directory record;
|
||||
// through this directory record, user can traverse the whole tree
|
||||
DirHeader* GetRoot() const
|
||||
{
|
||||
return (DirHeader*)(this + 1);
|
||||
}
|
||||
|
||||
// returns the size of memory occupied by the instance referred to by this cache
|
||||
// must be exact, because it's used by CacheRW to reallocate this cache
|
||||
size_t GetSize() const;
|
||||
|
||||
// QUICK check to determine whether the file entry belongs to this object
|
||||
bool IsOwnerOf (const FileEntry* pFileEntry) const;
|
||||
|
||||
// returns the string - path to the zip file from which this object was constructed.
|
||||
// this will be "" if the object was constructed with a factory that wasn't created with FLAGS_MEMORIZE_ZIP_PATH
|
||||
const char* GetFilePath() const
|
||||
{
|
||||
return ((const char*)(this + 1)) + m_nZipPathOffset;
|
||||
}
|
||||
|
||||
// Unpak the file into a destination folder
|
||||
bool UnpakToDisk(const string& destFolder);
|
||||
|
||||
friend class CacheFactory; // the factory class creates instances of this class
|
||||
friend class CacheRW; // the Read-Write 2-way cache can modify this cache directly during write operations
|
||||
protected:
|
||||
volatile signed int m_nRefCount; // the reference count
|
||||
FILE* m_pFile; // the opened file
|
||||
|
||||
// the size of the serialized data following this instance (not including the extra fields after the serialized tree data)
|
||||
size_t m_nDataSize;
|
||||
// the offset to the path/name of the zip file relative to (char*)(this+1) pointer in bytes
|
||||
size_t m_nZipPathOffset;
|
||||
|
||||
// tells if encryption used for zip-file
|
||||
EncryptionKey m_encryptionKey;
|
||||
bool m_bEncryptHeaders;
|
||||
public:
|
||||
// initializes the instance structure
|
||||
void Construct(FILE* fNew, size_t nDataSize, const EncryptionKey& key);
|
||||
void Delete();
|
||||
private:
|
||||
bool ReadCompressedData(char* data, size_t size);
|
||||
bool UnpakToDiskInternal(ZipDir::DirHeader* dirHeader, const string& destFolder);
|
||||
|
||||
// the constructor/destructor cannot be called at all - everything will go through the factory class
|
||||
Cache() { m_nRefCount = 0; }
|
||||
~Cache(){}
|
||||
};
|
||||
|
||||
TYPEDEF_AUTOPTR(Cache);
|
||||
|
||||
typedef Cache_AutoPtr CachePtr;
|
||||
}
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_ZIPDIR_ZIPDIRCACHE_H
|
||||
@@ -1,804 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include <zlib.h>
|
||||
#include "smartptr.h"
|
||||
#include "ZipFileFormat.h"
|
||||
#include "zipdirstructures.h"
|
||||
#include "ZipDirTree.h"
|
||||
#include "ZipDirCache.h"
|
||||
#include "ZipDirCacheRW.h"
|
||||
#include "ZipDirCacheFactory.h"
|
||||
#include "ZipDirList.h"
|
||||
#include <ZipDir/ZipDir_Traits_Platform.h>
|
||||
|
||||
static uint32 g_defaultEncryptionKey[4] = { 0xc968fb67, 0x8f9b4267, 0x85399e84, 0xf9b99dc4 };
|
||||
|
||||
ZipDir::CacheFactory::CacheFactory (InitMethodEnum nInitMethod, unsigned nFlags)
|
||||
{
|
||||
m_nCDREndPos = 0;
|
||||
m_f = NULL;
|
||||
m_bBuildFileEntryMap = false; // we only need it for validation/debugging
|
||||
m_bBuildFileEntryTree = true; // we need it to actually build the optimized structure of directories
|
||||
m_bEncryptedHeaders = false;
|
||||
|
||||
m_nInitMethod = nInitMethod;
|
||||
m_nFlags = nFlags;
|
||||
}
|
||||
|
||||
ZipDir::CacheFactory::~CacheFactory()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
ZipDir::CachePtr ZipDir::CacheFactory::New (const char* szFile, const uint32 key[4])
|
||||
{
|
||||
m_encryptionKey = EncryptionKey(g_defaultEncryptionKey);
|
||||
if (key)
|
||||
{
|
||||
m_encryptionKey = EncryptionKey(key);
|
||||
}
|
||||
|
||||
Clear();
|
||||
m_f = nullptr;
|
||||
azfopen(&m_f, szFile, "rb");
|
||||
if (m_f)
|
||||
{
|
||||
return MakeCache (szFile);
|
||||
}
|
||||
Clear();
|
||||
THROW_ZIPDIR_ERROR(ZD_ERROR_IO_FAILED, "Cannot open file in binary mode for reading, probably missing file");
|
||||
return 0;
|
||||
/*
|
||||
if (!m_f)
|
||||
THROW_ZIPDIR_ERROR(ZD_ERROR_IO_FAILED,"Cannot open file in binary mode for reading, probably missing file");
|
||||
try
|
||||
{
|
||||
return MakeCache (szFile);
|
||||
}
|
||||
catch(Error)
|
||||
{
|
||||
Clear();
|
||||
throw;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
ZipDir::CacheRWPtr ZipDir::CacheFactory::NewRW(const char* szFileName, size_t fileAlignment, bool encrypted, const uint32* key)
|
||||
{
|
||||
m_encryptionKey = EncryptionKey(g_defaultEncryptionKey);
|
||||
if (key)
|
||||
{
|
||||
m_encryptionKey = EncryptionKey(key);
|
||||
}
|
||||
|
||||
CacheRWPtr pCache = new CacheRW(encrypted, m_encryptionKey);
|
||||
|
||||
// opens the given zip file and connects to it. Creates a new file if no such file exists
|
||||
// if successful, returns true.
|
||||
if (!(m_nFlags & FLAGS_DONT_MEMORIZE_ZIP_PATH))
|
||||
{
|
||||
pCache->m_strFilePath = szFileName;
|
||||
}
|
||||
|
||||
if (m_nFlags & FLAGS_DONT_COMPACT)
|
||||
{
|
||||
pCache->m_nFlags |= CacheRW::FLAGS_DONT_COMPACT;
|
||||
}
|
||||
|
||||
// first, try to open the file for reading or reading/writing
|
||||
if (m_nFlags & FLAGS_READ_ONLY)
|
||||
{
|
||||
m_f = nullptr;
|
||||
azfopen(&m_f, szFileName, "rb");
|
||||
pCache->m_nFlags |= CacheRW::FLAGS_CDR_DIRTY | CacheRW::FLAGS_READ_ONLY;
|
||||
|
||||
if (!m_f)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR(ZD_ERROR_IO_FAILED, "Could not open file in binary mode for reading");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_f = NULL;
|
||||
if (!(m_nFlags & FLAGS_CREATE_NEW))
|
||||
{
|
||||
m_f = nullptr;
|
||||
azfopen(&m_f, szFileName, "r+b");
|
||||
}
|
||||
|
||||
bool bOpenForWriting = true;
|
||||
|
||||
if (m_f)
|
||||
{
|
||||
// get file size
|
||||
fseek(m_f, 0, SEEK_END);
|
||||
size_t nFileSize = AZ_TRAIT_CRYCOMMONTOOLS_FTELL(m_f);
|
||||
fseek(m_f, 0, SEEK_SET);
|
||||
|
||||
if (nFileSize)
|
||||
{
|
||||
if (!ReadCacheRW(*pCache))
|
||||
{
|
||||
fclose(m_f);
|
||||
m_f = NULL;
|
||||
|
||||
THROW_ZIPDIR_ERROR(ZD_ERROR_IO_FAILED, "Could not read archive");
|
||||
return 0;
|
||||
}
|
||||
bOpenForWriting = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if file has 0 bytes (e.g. crash during saving) we don't want to open it
|
||||
assert(0); // you can ignore, the system shold handle this gracefully
|
||||
}
|
||||
}
|
||||
|
||||
if (bOpenForWriting)
|
||||
{
|
||||
m_f = nullptr;
|
||||
azfopen(&m_f, szFileName, "w+b");
|
||||
if (m_f)
|
||||
{
|
||||
// there's no such file, but we'll create one. We'll need to write out the CDR here
|
||||
pCache->m_lCDROffset = 0;
|
||||
pCache->m_nFlags |= CacheRW::FLAGS_CDR_DIRTY;
|
||||
}
|
||||
pCache->m_fileAlignment = fileAlignment;
|
||||
}
|
||||
|
||||
if (!m_f)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR(ZD_ERROR_IO_FAILED, "Could not open file in binary mode for appending (read/write)");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// give the cache the file handle:
|
||||
pCache->m_pFile = m_f;
|
||||
// the factory doesn't own it after that
|
||||
m_f = NULL;
|
||||
|
||||
return pCache;
|
||||
}
|
||||
|
||||
bool ZipDir::CacheFactory::ReadCacheRW (CacheRW& rwCache)
|
||||
{
|
||||
m_bBuildFileEntryTree = true;
|
||||
if (!Prepare())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// since it's open for R/W, we need to know exactly how much space
|
||||
// we have for each file to use the gaps efficiently
|
||||
FileEntryList Adjuster (&m_treeFileEntries, m_CDREnd.lCDROffset);
|
||||
Adjuster.RefreshEOFOffsets();
|
||||
|
||||
m_treeFileEntries.Swap(rwCache.m_treeDir);
|
||||
m_CDR_buffer.swap(rwCache.m_CDR_buffer); // CDR Buffer contain actually the string pool for the tree directory.
|
||||
m_unifiedNameBuffer.swap(rwCache.m_unifiedNameBuffer); // string pool for unified names
|
||||
|
||||
// very important: we need this offset to be able to add to the zip file
|
||||
rwCache.m_lCDROffset = m_CDREnd.lCDROffset;
|
||||
|
||||
if (m_bEncryptedHeaders != rwCache.m_bEncryptedHeaders)
|
||||
{
|
||||
// force to relink and update all headers on close
|
||||
rwCache.m_nFlags |= ZipDir::CacheRW::FLAGS_UNCOMPACTED;
|
||||
rwCache.m_bHeadersEncryptedOnClose = rwCache.m_bEncryptedHeaders;
|
||||
rwCache.m_bEncryptedHeaders = m_bEncryptedHeaders;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// reads everything and prepares the maps
|
||||
bool ZipDir::CacheFactory::Prepare ()
|
||||
{
|
||||
if (!FindCDREnd())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_bEncryptedHeaders = (m_CDREnd.nDisk & (1 << 15)) != 0;
|
||||
m_CDREnd.nDisk = m_CDREnd.nDisk & 0x7fff;
|
||||
|
||||
// we don't support multivolume archives
|
||||
if (m_CDREnd.nDisk != 0
|
||||
|| m_CDREnd.nCDRStartDisk != 0
|
||||
|| m_CDREnd.numEntriesOnDisk != m_CDREnd.numEntriesTotal)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR(ZD_ERROR_UNSUPPORTED, "Multivolume archive detected. Current version of ZipDir does not support multivolume archives");
|
||||
return false;
|
||||
}
|
||||
|
||||
// if the central directory offset or size are out of range,
|
||||
// the CDREnd record is probably corrupt
|
||||
if (m_CDREnd.lCDROffset > m_nCDREndPos
|
||||
|| m_CDREnd.lCDRSize > m_nCDREndPos
|
||||
|| m_CDREnd.lCDROffset + m_CDREnd.lCDRSize > m_nCDREndPos)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR (ZD_ERROR_DATA_IS_CORRUPT, "The central directory offset or size are out of range, the pak is probably corrupt, try to repair or delete the file");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!BuildFileEntryMap())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// the number of parsed files MUST be the declared number of entries
|
||||
// in the central directory
|
||||
if (m_bBuildFileEntryMap && m_CDREnd.numEntriesTotal != m_mapFileEntries.size())
|
||||
{
|
||||
THROW_ZIPDIR_ERROR (ZD_ERROR_CDR_IS_CORRUPT, "The number of parsed files does not match the declared number of entries in the central directory, the pak is probably corrupt, try to repair or delete the file");
|
||||
}
|
||||
|
||||
const size_t numFilesFound = m_treeFileEntries.NumFilesTotal();
|
||||
if (m_bBuildFileEntryTree && m_CDREnd.numEntriesTotal != numFilesFound)
|
||||
{
|
||||
const size_t numDirsFound = m_treeFileEntries.NumDirsTotal();
|
||||
|
||||
// Other zip tools create entries for directories.
|
||||
// These entires don't have representation in our tree.
|
||||
// FIXME: Proper calculation of entry count should be implemented.
|
||||
if (m_CDREnd.numEntriesTotal != numFilesFound + numDirsFound)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR (ZD_ERROR_CDR_IS_CORRUPT, "The number of parsed files does not match the declared number of entries in the central directory. The pak does not appear to be corrupt, but perhaps there are some duplicated or missing file entries, try to repair the file");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ZipDir::CachePtr ZipDir::CacheFactory::MakeCache (const char* szFile)
|
||||
{
|
||||
if (!Prepare())
|
||||
{
|
||||
return CachePtr();
|
||||
}
|
||||
|
||||
// initializes this object from the given tree, which is a convenient representation of the file tree
|
||||
size_t nSizeRequired = m_treeFileEntries.GetSizeSerialized();
|
||||
size_t nSizeZipPath = 1; // we need to remember the terminating 0
|
||||
if (!(m_nFlags & FLAGS_DONT_MEMORIZE_ZIP_PATH))
|
||||
{
|
||||
nSizeZipPath += strlen(szFile);
|
||||
}
|
||||
// allocate and initialize the memory that'll be the root now
|
||||
size_t nCacheInstanceSize = sizeof(Cache) + nSizeRequired + nSizeZipPath;
|
||||
|
||||
Cache* pCacheInstance = (Cache*)malloc(nCacheInstanceSize); // Do not use pools for this allocation
|
||||
pCacheInstance->Construct(m_f, nSizeRequired, m_encryptionKey);
|
||||
CachePtr cache = pCacheInstance;
|
||||
m_f = NULL; // we don't own the file anymore - it's in possession of the cache instance
|
||||
|
||||
// try to serialize into the memory
|
||||
#if !defined(NDEBUG)
|
||||
size_t nSizeSerialized =
|
||||
#endif
|
||||
m_treeFileEntries.Serialize (cache->GetRoot());
|
||||
|
||||
assert (nSizeSerialized == nSizeRequired);
|
||||
|
||||
char* pZipPath = ((char*)(pCacheInstance + 1)) + nSizeRequired;
|
||||
|
||||
if (!(m_nFlags & FLAGS_DONT_MEMORIZE_ZIP_PATH))
|
||||
{
|
||||
memcpy (pZipPath, szFile, nSizeZipPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
pZipPath[0] = '\0';
|
||||
}
|
||||
|
||||
Clear();
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
void ZipDir::CacheFactory::Clear()
|
||||
{
|
||||
if (m_f)
|
||||
{
|
||||
fclose (m_f);
|
||||
}
|
||||
m_nCDREndPos = 0;
|
||||
memset (&m_CDREnd, 0, sizeof(m_CDREnd));
|
||||
m_mapFileEntries.clear();
|
||||
m_treeFileEntries.Clear();
|
||||
m_bEncryptedHeaders = false;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// searches for CDREnd record in the given file
|
||||
bool ZipDir::CacheFactory::FindCDREnd()
|
||||
{
|
||||
// this buffer will be used to find the CDR End record
|
||||
// the additional bytes are required to store the potential tail of the CDREnd structure
|
||||
// when moving the window to the next position in the file
|
||||
char pReservedBuffer[g_nCDRSearchWindowSize + sizeof(ZipFile::CDREnd) - 1];
|
||||
|
||||
Seek (0, SEEK_END);
|
||||
unsigned long nFileSize = Tell();
|
||||
|
||||
if (nFileSize < sizeof(ZipFile::CDREnd))
|
||||
{
|
||||
THROW_ZIPDIR_ERROR (ZD_ERROR_NO_CDR, "The file is too small, it doesn't even contain the CDREnd structure. Please check and delete the file. Truncated files are not deleted automatically");
|
||||
return false;
|
||||
}
|
||||
|
||||
// this will point to the place where the buffer was loaded
|
||||
unsigned int nOldBufPos = nFileSize;
|
||||
// start scanning well before the end of the file to avoid reading beyond the end
|
||||
|
||||
unsigned int nScanPos = nFileSize - sizeof(ZipFile::CDREnd);
|
||||
|
||||
m_CDREnd.lSignature = 0; // invalid signature as the flag of not-found CDR End structure
|
||||
while (true)
|
||||
{
|
||||
unsigned int nNewBufPos; // the new buf pos
|
||||
char* pWindow = pReservedBuffer; // the window pointer into which data will be read (takes into account the possible tail-of-CDREnd)
|
||||
if (nOldBufPos <= g_nCDRSearchWindowSize)
|
||||
{
|
||||
// the old buffer position doesn't let us read the full search window size
|
||||
// therefore the new buffer pos will be 0 (instead of negative beyond the start of the file)
|
||||
// and the window pointer will be closer tot he end of the buffer because the end of the buffer
|
||||
// contains the data from the previous iteration (possibly)
|
||||
nNewBufPos = 0;
|
||||
pWindow = pReservedBuffer + g_nCDRSearchWindowSize - (nOldBufPos - nNewBufPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
nNewBufPos = nOldBufPos - g_nCDRSearchWindowSize;
|
||||
assert (nNewBufPos > 0);
|
||||
}
|
||||
|
||||
// since dealing with 32bit unsigned, check that filesize is bigger than
|
||||
// CDREnd plus comment before the following check occurs.
|
||||
if (nFileSize > (sizeof(ZipFile::CDREnd) + 0xFFFF))
|
||||
{
|
||||
// if the new buffer pos is beyond 64k limit for the comment size
|
||||
if (nNewBufPos < (unsigned int)(nFileSize - sizeof(ZipFile::CDREnd) - 0xFFFF))
|
||||
{
|
||||
nNewBufPos = nFileSize - sizeof(ZipFile::CDREnd) - 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
// if there's nothing to search
|
||||
if (nNewBufPos >= nOldBufPos)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR (ZD_ERROR_NO_CDR, "Cannot find Central Directory Record in pak. This is either not a pak file, or a pak file without Central Directory. It does not mean that the data is permanently lost, but it may be severely damaged. Please repair the file with external tools, there may be enough information left to recover the file completely"); // we didn't find anything
|
||||
return false;
|
||||
}
|
||||
|
||||
// seek to the start of the new window and read it
|
||||
Seek (nNewBufPos);
|
||||
Read (pWindow, nOldBufPos - nNewBufPos);
|
||||
|
||||
while (nScanPos >= nNewBufPos)
|
||||
{
|
||||
ZipFile::CDREnd* pEnd = (ZipFile::CDREnd*)(pWindow + nScanPos - nNewBufPos);
|
||||
if (pEnd->lSignature == pEnd->SIGNATURE)
|
||||
{
|
||||
if (pEnd->nCommentLength == nFileSize - nScanPos - sizeof(ZipFile::CDREnd))
|
||||
{
|
||||
// the comment length is exactly what we expected
|
||||
m_CDREnd = *pEnd;
|
||||
m_nCDREndPos = nScanPos;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
THROW_ZIPDIR_ERROR (ZD_ERROR_DATA_IS_CORRUPT, "Central Directory Record is followed by a comment of inconsistent length. This might be a minor misconsistency, please try to repair the file. However, it is dangerous to open the file because I will have to guess some structure offsets, which can lead to permanent unrecoverable damage of the archive content");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (nScanPos == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
--nScanPos;
|
||||
}
|
||||
|
||||
if (m_CDREnd.lSignature == m_CDREnd.SIGNATURE)
|
||||
{
|
||||
return true; // we've found it
|
||||
}
|
||||
|
||||
nOldBufPos = nNewBufPos;
|
||||
memmove (pReservedBuffer + g_nCDRSearchWindowSize, pWindow, sizeof(ZipFile::CDREnd) - 1);
|
||||
}
|
||||
THROW_ZIPDIR_ERROR (ZD_ERROR_UNEXPECTED, "The program flow may not have possibly lead here. This error is unexplainable"); // we shouldn't be here
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// uses the found CDREnd to scan the CDR and probably the Zip file itself
|
||||
// builds up the m_mapFileEntries
|
||||
bool ZipDir::CacheFactory::BuildFileEntryMap()
|
||||
{
|
||||
Seek (m_CDREnd.lCDROffset);
|
||||
|
||||
if (m_CDREnd.lCDRSize == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
DynArray<char>& pBuffer = m_CDR_buffer; // Use persistent buffer.
|
||||
|
||||
pBuffer.resize(m_CDREnd.lCDRSize + 1); // Allocate one more because we use this memory as a strings pool.
|
||||
|
||||
if (pBuffer.empty()) // couldn't allocate enough memory for temporary copy of CDR
|
||||
{
|
||||
THROW_ZIPDIR_ERROR (ZD_ERROR_NO_MEMORY, "Not enough memory to cache Central Directory record for fast initialization. This error may not happen on non-console systems");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calculate buffer size for unified filenames
|
||||
const size_t headersSize = sizeof(ZipFile::CDRFileHeader) * m_CDREnd.numEntriesTotal;
|
||||
const size_t terminatingZeros = m_CDREnd.numEntriesTotal;
|
||||
if (headersSize > m_CDREnd.lCDRSize + terminatingZeros)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR (ZD_ERROR_CORRUPTED_DATA, "Number of entries in Central Directory seems to be wrong");
|
||||
return false;
|
||||
}
|
||||
const size_t nameBufferSize = m_CDREnd.lCDRSize + terminatingZeros - headersSize; // numEntriesTotal for terminating zeroes
|
||||
|
||||
// Allocate buffer for unified filenames
|
||||
m_unifiedNameBuffer.resize(nameBufferSize);
|
||||
if (m_unifiedNameBuffer.empty() && nameBufferSize != 0)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR (ZD_ERROR_NO_MEMORY, "Not enough memory to allocate unified names buffer");
|
||||
return false;
|
||||
}
|
||||
char* pUnifiedName = m_unifiedNameBuffer.empty() ? 0 : &m_unifiedNameBuffer[0];
|
||||
const char* const pUnifiedNameEnd = pUnifiedName + m_unifiedNameBuffer.size();
|
||||
|
||||
ReadHeaderData(&pBuffer[0], m_CDREnd.lCDRSize);
|
||||
|
||||
// now we've read the complete CDR - parse it.
|
||||
ZipFile::CDRFileHeader* pFile = (ZipFile::CDRFileHeader*)(&pBuffer[0]);
|
||||
const char* const pEndOfData = &pBuffer[0] + m_CDREnd.lCDRSize;
|
||||
const char* const pEndOfBuffer = &pBuffer[0] + pBuffer.size();
|
||||
char* pFileName;
|
||||
|
||||
// check signature of first entry
|
||||
if ((const char*)(pFile + 1) <= pEndOfData)
|
||||
{
|
||||
if (pFile->lSignature != pFile->SIGNATURE)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR (ZD_ERROR_CDR_IS_CORRUPT, m_bEncryptedHeaders
|
||||
? "Signature of CDR entry is corrupt. Wrong decryption key was used or archive is corrupt."
|
||||
: "Signature of CDR entry is corrupt. Archive is corrupt.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
while ((pFileName = (char*)(pFile + 1)) <= pEndOfData)
|
||||
{
|
||||
// Hacky way to use CDR memory block as a string pool.
|
||||
pFile->lSignature = 0; // Force signature to always be 0 (First byte of signature maybe a zero termination of the previous file filename).
|
||||
|
||||
if (pFile->nVersionNeeded > 20)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR (ZD_ERROR_UNSUPPORTED, "Reading file header with unsupported version (nVersionNeeded > 20).");
|
||||
return false;
|
||||
}
|
||||
//if (pFile->lSignature != pFile->SIGNATURE) // Timur, Dont compare signatures as signatue in memory can be overwritten by the code below
|
||||
//break;
|
||||
// the end of this file record
|
||||
const char* pEndOfRecord = (pFileName + pFile->nFileNameLength + pFile->nExtraFieldLength + pFile->nFileCommentLength);
|
||||
// if the record overlaps with the End Of CDR structure, something is wrong
|
||||
if (pEndOfRecord > pEndOfData)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR (ZD_ERROR_CDR_IS_CORRUPT, "Central Directory record is either corrupt, or truncated, or missing. Cannot read the archive directory");
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Analyze advanced section.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SExtraZipFileData extra;
|
||||
const char* pExtraField = (pFileName + pFile->nFileNameLength);
|
||||
const char* pExtraEnd = pExtraField + pFile->nExtraFieldLength;
|
||||
while (pExtraField < pExtraEnd)
|
||||
{
|
||||
const char* pAttrData = pExtraField + sizeof(ZipFile::ExtraFieldHeader);
|
||||
ZipFile::ExtraFieldHeader& hdr = *(ZipFile::ExtraFieldHeader*)pExtraField;
|
||||
switch (hdr.headerID)
|
||||
{
|
||||
case ZipFile::EXTRA_NTFS:
|
||||
{
|
||||
extra.nLastModifyTime = *(uint64*)(pAttrData + sizeof(ZipFile::ExtraNTFSHeader));
|
||||
//uint64 accTime = *(uint64*)(pAttrData + sizeof(ZipFile::ExtraNTFSHeader) + 8);
|
||||
//uint64 crtTime = *(uint64*)(pAttrData + sizeof(ZipFile::ExtraNTFSHeader) + 16);
|
||||
}
|
||||
break;
|
||||
}
|
||||
pExtraField += sizeof(ZipFile::ExtraFieldHeader) + hdr.dataSize;
|
||||
}
|
||||
|
||||
bool bDirectory = false;
|
||||
if (pFile->nFileNameLength > 0 && (pFileName[pFile->nFileNameLength - 1] == '/' || pFileName[pFile->nFileNameLength - 1] == '\\'))
|
||||
{
|
||||
bDirectory = true;
|
||||
}
|
||||
|
||||
if (!bDirectory)
|
||||
{
|
||||
const size_t fileNameLen = pFile->nFileNameLength;
|
||||
pFileName[fileNameLen] = 0; // Not standard!, may overwrite signature of the next memory record data in zip.
|
||||
|
||||
// generate unified name
|
||||
if (pFileName + fileNameLen + 1 > pEndOfBuffer ||
|
||||
pUnifiedName + fileNameLen + 1 > pUnifiedNameEnd)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR (ZD_ERROR_CORRUPTED_DATA, "Filename length exceeds estimated size. Try to repair the archive.");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < fileNameLen + 1; i++)
|
||||
{
|
||||
pUnifiedName[i] = ::tolower(pFileName[i]);
|
||||
}
|
||||
|
||||
// put this entry into the map
|
||||
AddFileEntry (pFileName, pUnifiedName, pFile, extra);
|
||||
|
||||
pUnifiedName += fileNameLen + 1;
|
||||
}
|
||||
|
||||
// move to the next file
|
||||
pFile = (ZipFile::CDRFileHeader*)pEndOfRecord;
|
||||
}
|
||||
|
||||
// finished reading CDR
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// give the CDR File Header entry, reads the local file header to validate
|
||||
// and determine where the actual file lies
|
||||
void ZipDir::CacheFactory::AddFileEntry (char* strFilePath, char* strUnifiedPath, const ZipFile::CDRFileHeader* pFileHeader, const SExtraZipFileData& extra)
|
||||
{
|
||||
if (pFileHeader->lLocalHeaderOffset > m_CDREnd.lCDROffset)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR (ZD_ERROR_CDR_IS_CORRUPT, "Central Directory contains file descriptors pointing outside the archive file boundaries. The archive file is either truncated or damaged. Please try to repair the file"); // the file offset is beyond the CDR: impossible
|
||||
return;
|
||||
}
|
||||
|
||||
if (pFileHeader->nMethod == ZipFile::METHOD_STORE && pFileHeader->desc.lSizeUncompressed != pFileHeader->desc.lSizeCompressed)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR (ZD_ERROR_VALIDATION_FAILED, "File with STORE compression method declares its compressed size not matching its uncompressed size. File descriptor is inconsistent, archive content may be damaged, please try to repair the archive");
|
||||
return;
|
||||
}
|
||||
|
||||
FileEntry fileEntry (*pFileHeader, extra);
|
||||
|
||||
if ((m_bEncryptedHeaders || m_nInitMethod >= ZD_INIT_FULL) && pFileHeader->desc.lSizeCompressed)
|
||||
{
|
||||
InitDataOffset(fileEntry, pFileHeader);
|
||||
}
|
||||
|
||||
if (m_bBuildFileEntryMap)
|
||||
{
|
||||
m_mapFileEntries.insert (FileEntryMap::value_type(strFilePath, fileEntry));
|
||||
}
|
||||
|
||||
if (m_bBuildFileEntryTree)
|
||||
{
|
||||
m_treeFileEntries.Add(strFilePath, strUnifiedPath, fileEntry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// initializes the actual data offset in the file in the fileEntry structure
|
||||
// searches to the local file header, reads it and calculates the actual offset in the file
|
||||
void ZipDir::CacheFactory::InitDataOffset (FileEntry& fileEntry, const ZipFile::CDRFileHeader* pFileHeader)
|
||||
{
|
||||
// make sure it's the same file and the fileEntry structure is properly initialized
|
||||
assert (fileEntry.nFileHeaderOffset == pFileHeader->lLocalHeaderOffset);
|
||||
|
||||
/*
|
||||
// without validation, it would be like this:
|
||||
ErrorEnum nError = Refresh(&fileEntry);
|
||||
if (nError != ZD_ERROR_SUCCESS)
|
||||
THROW_ZIPDIR_ERROR(nError,"Cannot refresh file entry. Probably corrupted file header inside zip file");
|
||||
*/
|
||||
|
||||
|
||||
if (m_bEncryptedHeaders)
|
||||
{
|
||||
// ignore local header
|
||||
fileEntry.nFileDataOffset = pFileHeader->lLocalHeaderOffset + sizeof(ZipFile::LocalFileHeader) + pFileHeader->nFileNameLength + pFileHeader->nExtraFieldLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
Seek(pFileHeader->lLocalHeaderOffset);
|
||||
// read the local file header and the name (for validation) into the buffer
|
||||
DynArray<char>pBuffer;
|
||||
unsigned nBufferLength = sizeof(ZipFile::LocalFileHeader) + pFileHeader->nFileNameLength;
|
||||
pBuffer.resize(nBufferLength);
|
||||
Read (&pBuffer[0], nBufferLength);
|
||||
|
||||
// validate the local file header (compare with the CDR file header - they should contain basically the same information)
|
||||
const ZipFile::LocalFileHeader* pLocalFileHeader = (const ZipFile::LocalFileHeader*)&pBuffer[0];
|
||||
if (pFileHeader->desc != pLocalFileHeader->desc
|
||||
|| pFileHeader->nMethod != pLocalFileHeader->nMethod
|
||||
|| pFileHeader->nFileNameLength != pLocalFileHeader->nFileNameLength
|
||||
// for a tough validation, we can compare the timestamps of the local and central directory entries
|
||||
// but we won't do that for backward compatibility with ZipDir
|
||||
//|| pFileHeader->nLastModDate != pLocalFileHeader->nLastModDate
|
||||
//|| pFileHeader->nLastModTime != pLocalFileHeader->nLastModTime
|
||||
)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR (ZD_ERROR_VALIDATION_FAILED, "The local file header descriptor doesn't match the basic parameters declared in the global file header in the file. The archive content is misconsistent and may be damaged. Please try to repair the archive");
|
||||
return;
|
||||
}
|
||||
|
||||
// now compare the local file name with the one recorded in CDR: they must match.
|
||||
if (azmemicmp((const char*)&pBuffer[sizeof(ZipFile::LocalFileHeader)], (const char*)pFileHeader + 1, pFileHeader->nFileNameLength))
|
||||
{
|
||||
// either file name, or the extra field do not match
|
||||
THROW_ZIPDIR_ERROR(ZD_ERROR_VALIDATION_FAILED, "The local file header contains file name which does not match the file name of the global file header. The archive content is misconsistent with its directory. Please repair the archive");
|
||||
return;
|
||||
}
|
||||
|
||||
fileEntry.nFileDataOffset = pFileHeader->lLocalHeaderOffset + sizeof(ZipFile::LocalFileHeader) + pLocalFileHeader->nFileNameLength + pLocalFileHeader->nExtraFieldLength;
|
||||
}
|
||||
|
||||
if (fileEntry.nFileDataOffset >= m_nCDREndPos)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR(ZD_ERROR_VALIDATION_FAILED, "The global file header declares the file which crosses the boundaries of the archive. The archive is either corrupted or truncated, please try to repair it");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_nInitMethod >= ZD_INIT_VALIDATE)
|
||||
{
|
||||
Validate (fileEntry);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// reads the file pointed by the given header and entry (they must be coherent)
|
||||
// and decompresses it; then calculates and validates its CRC32
|
||||
void ZipDir::CacheFactory::Validate(const FileEntry& fileEntry)
|
||||
{
|
||||
DynArray<char> pBuffer;
|
||||
// validate the file contents
|
||||
// allocate memory for both the compressed data and uncompressed data
|
||||
pBuffer.resize(fileEntry.desc.lSizeCompressed + fileEntry.desc.lSizeUncompressed);
|
||||
char* pUncompressed = &pBuffer[fileEntry.desc.lSizeCompressed];
|
||||
char* pCompressed = &pBuffer[0];
|
||||
|
||||
assert (fileEntry.nFileDataOffset != FileEntry::INVALID_DATA_OFFSET);
|
||||
Seek(fileEntry.nFileDataOffset);
|
||||
|
||||
Read(pCompressed, fileEntry.desc.lSizeCompressed);
|
||||
|
||||
if (fileEntry.nMethod == ZipFile::METHOD_DEFLATE_AND_ENCRYPT)
|
||||
{
|
||||
ZipDir::Decrypt(pCompressed, fileEntry.desc.lSizeCompressed, m_encryptionKey);
|
||||
}
|
||||
|
||||
unsigned long nDestSize = fileEntry.desc.lSizeUncompressed;
|
||||
int nError = Z_OK;
|
||||
if (fileEntry.nMethod)
|
||||
{
|
||||
nError = ZipRawUncompress (pUncompressed, &nDestSize, pCompressed, fileEntry.desc.lSizeCompressed);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (fileEntry.desc.lSizeCompressed == fileEntry.desc.lSizeUncompressed);
|
||||
memcpy (pUncompressed, pCompressed, fileEntry.desc.lSizeUncompressed);
|
||||
}
|
||||
switch (nError)
|
||||
{
|
||||
case Z_OK:
|
||||
break;
|
||||
case Z_MEM_ERROR:
|
||||
THROW_ZIPDIR_ERROR(ZD_ERROR_ZLIB_NO_MEMORY, "ZLib reported out-of-memory error");
|
||||
return;
|
||||
case Z_BUF_ERROR:
|
||||
THROW_ZIPDIR_ERROR(ZD_ERROR_ZLIB_CORRUPTED_DATA, "ZLib reported compressed stream buffer error");
|
||||
return;
|
||||
case Z_DATA_ERROR:
|
||||
THROW_ZIPDIR_ERROR(ZD_ERROR_ZLIB_CORRUPTED_DATA, "ZLib reported compressed stream data error");
|
||||
return;
|
||||
default:
|
||||
THROW_ZIPDIR_ERROR(ZD_ERROR_ZLIB_FAILED, "ZLib reported an unexpected unknown error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (nDestSize != fileEntry.desc.lSizeUncompressed)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR(ZD_ERROR_CORRUPTED_DATA, "Uncompressed stream doesn't match the size of uncompressed file stored in the archive file headers");
|
||||
return;
|
||||
}
|
||||
|
||||
uLong uCRC32 = crc32(0L, Z_NULL, 0);
|
||||
uCRC32 = crc32(uCRC32, (Bytef*)pUncompressed, nDestSize);
|
||||
if (uCRC32 != fileEntry.desc.lCRC32)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR(ZD_ERROR_CRC32_CHECK, "Uncompressed stream CRC32 check failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// extracts the file path from the file header with subsequent information
|
||||
// may, or may not, put all letters to lower-case (depending on whether the system is to be case-sensitive or not)
|
||||
// it's the responsibility of the caller to ensure that the file name is in readable valid memory
|
||||
char* ZipDir::CacheFactory::GetFilePath (const char* pFileName, ZipFile::ushort nFileNameLength)
|
||||
{
|
||||
static char strResult[_MAX_PATH];
|
||||
assert(nFileNameLength < _MAX_PATH);
|
||||
memcpy(strResult, pFileName, nFileNameLength);
|
||||
strResult[nFileNameLength] = 0;
|
||||
for (int i = 0; i < nFileNameLength; i++)
|
||||
{
|
||||
strResult[i] = ::tolower(strResult[i]);
|
||||
}
|
||||
|
||||
return strResult;
|
||||
}
|
||||
|
||||
// seeks in the file relative to the starting position
|
||||
void ZipDir::CacheFactory::Seek (ZipFile::ulong nPos, int nOrigin) // throw
|
||||
{
|
||||
if (AZ_TRAIT_CRYCOMMONTOOLS_FSEEK(m_f, nPos, nOrigin))
|
||||
{
|
||||
THROW_ZIPDIR_ERROR(ZD_ERROR_IO_FAILED, "Cannot fseek() to the new position in the file. This is unexpected error and should not happen under any circumstances. Perhaps some network or disk failure error has caused this");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long ZipDir::CacheFactory::Tell () // throw
|
||||
{
|
||||
AZ::s64 nPos = AZ_TRAIT_CRYCOMMONTOOLS_FTELL(m_f);
|
||||
if (nPos == -1)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR(ZD_ERROR_IO_FAILED, "Cannot ftell() position in the archive. This is unexpected error and should not happen under any circumstances. Perhaps some network or disk failure error has caused this");
|
||||
return 0;
|
||||
}
|
||||
return (unsigned long)nPos;
|
||||
}
|
||||
|
||||
void ZipDir::CacheFactory::Read (void* pDest, unsigned nSize) // throw
|
||||
{
|
||||
if (fread (pDest, nSize, 1, m_f) != 1)
|
||||
{
|
||||
THROW_ZIPDIR_ERROR(ZD_ERROR_IO_FAILED, "Cannot fread() a portion of data from archive");
|
||||
}
|
||||
}
|
||||
|
||||
void ZipDir::CacheFactory::ReadHeaderData (void* pDest, unsigned nSize) // throw
|
||||
{
|
||||
Read(pDest, nSize);
|
||||
|
||||
if (m_bEncryptedHeaders)
|
||||
{
|
||||
ZipDir::Decrypt((char*)pDest, nSize, m_encryptionKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
// This is the class that can read the directory from Zip file,
|
||||
// and store it into the directory cache
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_ZIPDIR_ZIPDIRCACHEFACTORY_H
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_ZIPDIR_ZIPDIRCACHEFACTORY_H
|
||||
#pragma once
|
||||
|
||||
|
||||
namespace ZipDir
|
||||
{
|
||||
class CacheRW;
|
||||
TYPEDEF_AUTOPTR(CacheRW);
|
||||
typedef CacheRW_AutoPtr CacheRWPtr;
|
||||
|
||||
// an instance of this class is temporarily created on stack to initialize the CZipFile instance
|
||||
class CacheFactory
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
// open RW cache in read-only mode
|
||||
FLAGS_READ_ONLY = 1,
|
||||
// do not compact RW-cached zip upon destruction
|
||||
FLAGS_DONT_COMPACT = 1 << 1,
|
||||
// if this is set, then the zip paths won't be memorized in the cache objects
|
||||
FLAGS_DONT_MEMORIZE_ZIP_PATH = 1 << 2,
|
||||
// if this is set, the archive will be created anew (the existing file will be overwritten)
|
||||
FLAGS_CREATE_NEW = 1 << 3
|
||||
};
|
||||
|
||||
// initializes the internal structures
|
||||
// nFlags can have FLAGS_READ_ONLY flag, in this case the object will be opened only for reading
|
||||
CacheFactory (InitMethodEnum nInitMethod, unsigned nFlags = 0);
|
||||
~CacheFactory();
|
||||
|
||||
// the new function creates a new cache
|
||||
CachePtr New(const char* szFileName, const uint32 decryptionKey[4]);// throw (ErrorEnum);
|
||||
|
||||
CacheRWPtr NewRW(const char* szFileName, size_t fileAlignment, bool encrypted, const uint32 encryptionKey[4]);
|
||||
|
||||
protected:
|
||||
// reads the zip file into the file entry tree.
|
||||
bool ReadCacheRW (CacheRW& rwCache);
|
||||
|
||||
// creates from the m_f file
|
||||
// reserves the given number of bytes for future expansion of the object
|
||||
// upon return, pReserve contains the actual number of bytes that were allocated (more might have been allocated)
|
||||
CachePtr MakeCache (const char* szFile);
|
||||
|
||||
// this sets the window size of the blocks of data read from the end of the file to find the Central Directory Record
|
||||
// since normally there are no
|
||||
enum
|
||||
{
|
||||
g_nCDRSearchWindowSize = 0x100
|
||||
};
|
||||
|
||||
void Clear();
|
||||
|
||||
// reads everything and prepares the maps
|
||||
bool Prepare();
|
||||
|
||||
// searches for CDREnd record in the given file
|
||||
bool FindCDREnd();// throw(ErrorEnum);
|
||||
|
||||
// uses the found CDREnd to scan the CDR and probably the Zip file itself
|
||||
// builds up the m_mapFileEntries
|
||||
bool BuildFileEntryMap();// throw (ErrorEnum);
|
||||
|
||||
// give the CDR File Header entry, reads the local file header to validate and determine where
|
||||
// the actual file lies
|
||||
// This function can actually modify strFilePath and strUnifiedPath variables, make sure you use copies of real paths.
|
||||
void AddFileEntry (char* strFilePath, char* strUnifiedPath, const ZipFile::CDRFileHeader* pFileHeader, const SExtraZipFileData& extra);// throw (ErrorEnum);
|
||||
|
||||
// extracts the file path from the file header with subsequent information
|
||||
// may, or may not, put all letters to lower-case (depending on whether the system is to be case-sensitive or not)
|
||||
// it's the responsibility of the caller to ensure that the file name is in readable valid memory
|
||||
char* GetFilePath (const ZipFile::CDRFileHeader* pFileHeader)
|
||||
{
|
||||
return GetFilePath((const char*)(pFileHeader + 1), pFileHeader->nFileNameLength);
|
||||
}
|
||||
// extracts the file path from the file header with subsequent information
|
||||
// may, or may not, put all letters to lower-case (depending on whether the system is to be case-sensitive or not)
|
||||
// it's the responsibility of the caller to ensure that the file name is in readable valid memory
|
||||
char* GetFilePath (const ZipFile::LocalFileHeader* pFileHeader)
|
||||
{
|
||||
return GetFilePath((const char*)(pFileHeader + 1), pFileHeader->nFileNameLength);
|
||||
}
|
||||
// extracts the file path from the file header with subsequent information
|
||||
// may, or may not, put all letters to lower-case (depending on whether the system is to be case-sensitive or not)
|
||||
// it's the responsibility of the caller to ensure that the file name is in readable valid memory
|
||||
char* GetFilePath (const char* pFileName, ZipFile::ushort nFileNameLength);
|
||||
|
||||
// validates (if the init method has the corresponding value) the given file/header
|
||||
void Validate(const FileEntry& fileEntry);
|
||||
|
||||
// initializes the actual data offset in the file in the fileEntry structure
|
||||
// searches to the local file header, reads it and calculates the actual offset in the file
|
||||
void InitDataOffset (FileEntry& fileEntry, const ZipFile::CDRFileHeader* pFileHeader);
|
||||
|
||||
// seeks in the file relative to the starting position
|
||||
void Seek (ZipFile::ulong nPos, int nOrigin = SEEK_SET); // throw
|
||||
unsigned long Tell (); // throw
|
||||
void Read (void* pDest, unsigned nSize); // throw
|
||||
void ReadHeaderData (void* pDest, unsigned nSize);// throw
|
||||
protected:
|
||||
|
||||
FILE* m_f;
|
||||
InitMethodEnum m_nInitMethod;
|
||||
unsigned m_nFlags;
|
||||
ZipFile::CDREnd m_CDREnd;
|
||||
|
||||
unsigned m_nCDREndPos; // position of the CDR End in the file
|
||||
|
||||
// Map: Relative file path => file entry info
|
||||
typedef std::map<string, ZipDir::FileEntry> FileEntryMap;
|
||||
FileEntryMap m_mapFileEntries;
|
||||
|
||||
FileEntryTree m_treeFileEntries;
|
||||
|
||||
DynArray<char> m_CDR_buffer;
|
||||
DynArray<char> m_unifiedNameBuffer;
|
||||
|
||||
EncryptionKey m_encryptionKey;
|
||||
bool m_bEncryptedHeaders;
|
||||
bool m_bBuildFileEntryMap;
|
||||
bool m_bBuildFileEntryTree;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_ZIPDIR_ZIPDIRCACHEFACTORY_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,283 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Declaration of the class that will keep the ZipDir Cache object
|
||||
// and will provide all its services to access Zip file, plus it will
|
||||
// provide services to write to the zip file efficiently
|
||||
// Time to time, the contained Cache object will be recreated during
|
||||
// an archive add operation
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SimpleStringPool.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
struct PackFileJob;
|
||||
namespace ZipDir
|
||||
{
|
||||
struct FileDataRecord;
|
||||
TYPEDEF_AUTOPTR(FileDataRecord);
|
||||
typedef FileDataRecord_AutoPtr FileDataRecordPtr;
|
||||
|
||||
static constexpr int TARGET_MIN_TEST_COMPRESS_BYTES = 128 * 1024;
|
||||
|
||||
struct IReporter
|
||||
{
|
||||
virtual void ReportAdded(const char* filename) = 0;
|
||||
virtual void ReportMissing(const char* filename) = 0;
|
||||
virtual void ReportUpToDate(const char* filename) = 0;
|
||||
virtual void ReportSkipped(const char* filename) = 0;
|
||||
virtual void ReportFailed(const char* filename, const char* error) = 0;
|
||||
virtual void ReportSpeed(double bytesPerSecond) = 0;
|
||||
};
|
||||
|
||||
struct ISplitter
|
||||
{
|
||||
// Arguments:
|
||||
// total - the current size of the pak
|
||||
// add - the size of the file to add
|
||||
// sub - the size of the old version of the file which will be removed from the pak
|
||||
// Return:
|
||||
// true if adding the current file to the current pak is still permitted.
|
||||
virtual bool CheckWriteLimit(size_t total, size_t add, size_t sub) const = 0;
|
||||
|
||||
// Arguments:
|
||||
// total - the current size of the pak
|
||||
// add - the size of the file to add
|
||||
// sub - the size of the old version of the file which will be removed from the pak
|
||||
// offset - the position of the first file which has not been added to the pak
|
||||
// in the array passed to "UpdateMultipleFiles()"
|
||||
virtual void SetLastFile(size_t total, size_t add, size_t sub, int offset) = 0;
|
||||
};
|
||||
|
||||
struct IEncryptPredicate
|
||||
{
|
||||
virtual ~IEncryptPredicate() = default;
|
||||
virtual bool Match(const char* filename) = 0;
|
||||
};
|
||||
|
||||
class CacheRW
|
||||
{
|
||||
public:
|
||||
enum EncryptionChange
|
||||
{
|
||||
ENCRYPT,
|
||||
DECRYPT
|
||||
};
|
||||
// the size of the buffer that's using during re-linking the zip file
|
||||
enum
|
||||
{
|
||||
g_nSizeRelinkBuffer = 128 * 1024 * 1024, // 128 Mbytes
|
||||
g_nMaxItemsRelinkBuffer = 1024 // max number of files to read before (without) writing
|
||||
};
|
||||
|
||||
void AddRef();
|
||||
void Release();
|
||||
|
||||
|
||||
CacheRW(bool encryptHeaders, const EncryptionKey& encryptionKey);
|
||||
~CacheRW();
|
||||
|
||||
bool IsValid () const
|
||||
{
|
||||
return m_pFile != NULL;
|
||||
}
|
||||
|
||||
static char* UnifyPath(char* const str, const char* pPath);
|
||||
static char* ToUnixPath(char* const str, const char* pPath);
|
||||
char* AllocPath(const char* pPath);
|
||||
|
||||
// opens the given zip file and connects to it. Creates a new file if no such file exists
|
||||
// if successful, returns true.
|
||||
//ErrorEnum Open (CMTSafeHeap* pHeap, InitMethodEnum nInitMethod, unsigned nFlags, const char* szFile);
|
||||
|
||||
// Adds a new file to the zip or update an existing one
|
||||
// adds a directory (creates several nested directories if needed)
|
||||
ErrorEnum UpdateFile(const char* szRelativePath, void* pUncompressed, unsigned nSize, unsigned nCompressionMethod, int nCompressionLevel, int64 modTime);
|
||||
|
||||
// Sets if Archive should be encrypted or decrypted on close.
|
||||
bool EncryptArchive(EncryptionChange change, IEncryptPredicate* encryptContentPredicate, int* numChanged, int* numSkipped);
|
||||
|
||||
// Adds or updates a bunch of files. Creates directories if needed. Multithreaded when numExtraThreads > 0
|
||||
bool UpdateMultipleFiles(const char** realFilenames, const char** filenamesInZip, size_t fileCount,
|
||||
int compressionLevel, bool encryptContent, size_t zipMaxSize, int sourceMinSize, int sourceMaxSize,
|
||||
unsigned numExtraThreads, ZipDir::IReporter* reporter, ZipDir::ISplitter* splitter = nullptr, bool useFastestDecompressionCodec = false);
|
||||
|
||||
// Adds a new file to the zip or update an existing one if it is not compressed - just stored - start a big file
|
||||
ErrorEnum StartContinuousFileUpdate(const char* szRelativePath, unsigned nSize);
|
||||
|
||||
// Adds a new file to the zip or update an existing's segment if it is not compressed - just stored
|
||||
// adds a directory (creates several nested directories if needed)
|
||||
// Arguments:
|
||||
// nOverwriteSeekPos - 0xffffffff means the seek pos should not be overwritten
|
||||
ErrorEnum UpdateFileContinuousSegment (const char* szRelativePath, unsigned nSize, void* pUncompressed, unsigned nSegmentSize, unsigned nOverwriteSeekPos);
|
||||
|
||||
ErrorEnum UpdateFileCRC(const char* szRelativePath, unsigned dwCRC32);
|
||||
|
||||
// deletes the file from the archive
|
||||
ErrorEnum RemoveFile(const char* szRelativePath);
|
||||
|
||||
// deletes the directory, with all its descendants (files and subdirs)
|
||||
ErrorEnum RemoveDir(const char* szRelativePath);
|
||||
|
||||
// deletes all files and directories in this archive
|
||||
ErrorEnum RemoveAll();
|
||||
|
||||
// closes the current zip file
|
||||
void Close();
|
||||
|
||||
FileEntry* FindFile(const char* szPath, bool bFullInfo = false);
|
||||
|
||||
ErrorEnum ReadFile(FileEntry* pFileEntry, void* pCompressed, void* pUncompressed);
|
||||
|
||||
void* AllocAndReadFile (FileEntry* pFileEntry);
|
||||
|
||||
void Free (void* p)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
// refreshes information about the given file entry into this file entry
|
||||
ErrorEnum Refresh (FileEntry* pFileEntry);
|
||||
|
||||
// returns the size of memory occupied by the instance of this cache
|
||||
size_t GetSize() const;
|
||||
|
||||
// returns the compressed size of all the entries
|
||||
size_t GetCompressedSize() const;
|
||||
|
||||
// returns the total size of memory occupied by the instance of this cache and all the compressed files
|
||||
size_t GetTotalFileSize() const;
|
||||
|
||||
// returns the total size of space occupied on disk by the instance of this cache and all the compressed files
|
||||
size_t GetTotalFileSizeOnDiskSoFar();
|
||||
|
||||
// QUICK check to determine whether the file entry belongs to this object
|
||||
bool IsOwnerOf (const FileEntry* pFileEntry) const
|
||||
{
|
||||
return m_treeDir.IsOwnerOf(pFileEntry);
|
||||
}
|
||||
|
||||
// returns the string - path to the zip file from which this object was constructed.
|
||||
// this will be "" if the object was constructed with a factory that wasn't created with FLAGS_MEMORIZE_ZIP_PATH
|
||||
const char* GetFilePath() const
|
||||
{
|
||||
return m_strFilePath.c_str();
|
||||
}
|
||||
|
||||
FileEntryTree* GetRoot()
|
||||
{
|
||||
return &m_treeDir;
|
||||
}
|
||||
|
||||
const FileEntryTree* GetRoot() const
|
||||
{
|
||||
return &m_treeDir;
|
||||
}
|
||||
|
||||
// writes the CDR to the disk
|
||||
bool WriteCDR() {return WriteCDR(m_pFile, m_bEncryptedHeaders); }
|
||||
bool WriteCDR(FILE* fTarget, bool encryptHeaders);
|
||||
|
||||
bool RelinkZip();
|
||||
protected:
|
||||
bool RelinkZip(FILE* fTmp);
|
||||
// writes out the file data in the queue into the given file. Empties the queue
|
||||
bool WriteZipFiles(std::vector<FileDataRecordPtr>& queFiles, FILE* fTmp);
|
||||
// generates random file name
|
||||
string GetRandomName(int nAttempt);
|
||||
|
||||
bool ReadCompressedData(char* data, size_t size);
|
||||
bool WriteCompressedData(const char* data, size_t size, bool encrypt, FILE* file);
|
||||
bool WriteNullData(size_t size);
|
||||
|
||||
void StorePackedFile(PackFileJob* job);
|
||||
protected:
|
||||
|
||||
friend class CacheFactory;
|
||||
volatile signed int m_nRefCount; // the reference count
|
||||
FileEntryTree m_treeDir;
|
||||
FILE* m_pFile;
|
||||
string m_strFilePath;
|
||||
|
||||
// offset to the start of CDR in the file,even if there's no CDR there currently
|
||||
// when a new file is added, it can start from here, but this value will need to be updated then
|
||||
ZipFile::ulong m_lCDROffset;
|
||||
|
||||
CSimpleStringPool m_tempStringPool;
|
||||
|
||||
enum
|
||||
{
|
||||
// if this is set, the file needs to be compacted before it can be used by
|
||||
// all standard zip tools, because gaps between file datas can be present
|
||||
FLAGS_UNCOMPACTED = 1 << 0,
|
||||
// if this is set, the CDR needs to be written to the file
|
||||
FLAGS_CDR_DIRTY = 1 << 1,
|
||||
// if this is set, the file is opened in read-only mode. no write operations are to be performed
|
||||
FLAGS_READ_ONLY = 1 << 2,
|
||||
// when this is set, compact operation is not performed
|
||||
FLAGS_DONT_COMPACT = 1 << 3
|
||||
};
|
||||
unsigned m_nFlags;
|
||||
size_t m_fileAlignment;
|
||||
|
||||
// CDR buffer.
|
||||
DynArray<char> m_CDR_buffer;
|
||||
// unified names buffer
|
||||
DynArray<char> m_unifiedNameBuffer;
|
||||
|
||||
EncryptionKey m_encryptionKey;
|
||||
bool m_bEncryptedHeaders;
|
||||
bool m_bHeadersEncryptedOnClose;
|
||||
};
|
||||
|
||||
TYPEDEF_AUTOPTR(CacheRW);
|
||||
typedef CacheRW_AutoPtr CacheRWPtr;
|
||||
|
||||
// creates and if needed automatically destroys the file entry
|
||||
class FileEntryTransactionAdd
|
||||
{
|
||||
class CacheRW* m_pCache;
|
||||
char m_szPath[_MAX_PATH];
|
||||
FileEntry* m_pFileEntry;
|
||||
bool m_bComitted;
|
||||
public:
|
||||
operator FileEntry* () {
|
||||
return m_pFileEntry;
|
||||
}
|
||||
operator bool() const{
|
||||
return m_pFileEntry != NULL;
|
||||
}
|
||||
FileEntry* operator -> () {return m_pFileEntry; }
|
||||
FileEntryTransactionAdd(class CacheRW* pCache, char* szPath, char* szUnifiedPath)
|
||||
: m_pCache(pCache)
|
||||
, m_bComitted (false)
|
||||
{
|
||||
// we need to copy path, because original one will be destroyed by FileEntryTree::Add call
|
||||
cry_strcpy(m_szPath, szUnifiedPath);
|
||||
m_pFileEntry = m_pCache->GetRoot()->Add(szPath, szUnifiedPath);
|
||||
}
|
||||
~FileEntryTransactionAdd()
|
||||
{
|
||||
if (m_pFileEntry && !m_bComitted)
|
||||
{
|
||||
m_pCache->RemoveFile(m_szPath);
|
||||
}
|
||||
}
|
||||
void Commit()
|
||||
{
|
||||
m_bComitted = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,246 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
|
||||
#include "smartptr.h"
|
||||
#include "ZipFileFormat.h"
|
||||
#include "zipdirstructures.h"
|
||||
#include "ZipDirCache.h"
|
||||
#include "ZipDirFind.h"
|
||||
#include "StringHelpers.h"
|
||||
|
||||
bool ZipDir::FindFile::FindFirst (const char* szWildcard)
|
||||
{
|
||||
if (!PreFind (szWildcard))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// finally, this is the name of the file
|
||||
m_nFileEntry = 0;
|
||||
return SkipNonMatchingFiles();
|
||||
}
|
||||
|
||||
bool ZipDir::FindDir::FindFirst (const char* szWildcard)
|
||||
{
|
||||
if (!PreFind (szWildcard))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// finally, this is the name of the file
|
||||
m_nDirEntry = 0;
|
||||
return SkipNonMatchingDirs();
|
||||
}
|
||||
|
||||
// matches the file wilcard in the m_szWildcard to the given file/dir name
|
||||
// this takes into account the fact that xxx. is the alias name for xxx
|
||||
bool ZipDir::FindData::MatchWildcard(const char* szName)
|
||||
{
|
||||
if (StringHelpers::MatchesWildcards(szName, m_szWildcard))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// check if the file object name contains extension sign (.)
|
||||
const char* p;
|
||||
for (p = szName; *p && *p != '.'; ++p)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*p)
|
||||
{
|
||||
// there's an extension sign in the object, but it wasn't matched..
|
||||
assert (*p == '.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// no extension sign - add it
|
||||
char szAlias[_MAX_PATH + 2];
|
||||
size_t nLength = p - szName;
|
||||
if (nLength > _MAX_PATH)
|
||||
{
|
||||
nLength = _MAX_PATH;
|
||||
}
|
||||
memcpy (szAlias, szName, nLength);
|
||||
szAlias[nLength] = '.'; // add the alias
|
||||
szAlias[nLength + 1] = '\0'; // terminate the string
|
||||
return StringHelpers::MatchesWildcards(szAlias, m_szWildcard);
|
||||
}
|
||||
|
||||
|
||||
ZipDir::FileEntry* ZipDir::FindFile::FindExact (const char* szPath)
|
||||
{
|
||||
if (!PreFind (szPath))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FileEntry* pFileEntry = m_pDirHeader->FindFileEntry(m_szWildcard);
|
||||
if (pFileEntry)
|
||||
{
|
||||
m_nFileEntry = (unsigned)(pFileEntry - m_pDirHeader->GetFileEntry(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pDirHeader = NULL; // we didn't find it, fail the search
|
||||
}
|
||||
return pFileEntry;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// after this call returns successfully (with true returned), the m_szWildcard
|
||||
// contains the file name/wildcard and m_pDirHeader contains the directory where
|
||||
// the file (s) are to be found
|
||||
bool ZipDir::FindData::PreFind (const char* szWildcard)
|
||||
{
|
||||
if (!m_pRoot)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// start the search from the root
|
||||
m_pDirHeader = m_pRoot;
|
||||
|
||||
// for each path dir name, copy it into the buffer and try to find the subdirectory
|
||||
const char* pPath = szWildcard;
|
||||
for (;; )
|
||||
{
|
||||
char* pName = m_szWildcard;
|
||||
|
||||
// at first we'll use the wildcard memory to save the directory names
|
||||
for (; *pPath && *pPath != '/' && *pPath != '\\' && pName < m_szWildcard + sizeof(m_szWildcard) - 1; ++pPath, ++pName)
|
||||
{
|
||||
*pName = ::tolower(*pPath);
|
||||
}
|
||||
*pName = '\0';
|
||||
|
||||
if (*pPath)
|
||||
{
|
||||
if (*pPath != '/' && *pPath != '\\')
|
||||
{
|
||||
return false;//ZD_ERROR_NAME_TOO_LONG;
|
||||
}
|
||||
// this is the name of the directory
|
||||
DirEntry* pDirEntry = m_pDirHeader->FindSubdirEntry(m_szWildcard);
|
||||
if (!pDirEntry)
|
||||
{
|
||||
m_pDirHeader = NULL; // finish the search
|
||||
return false;
|
||||
}
|
||||
m_pDirHeader = pDirEntry->GetDirectory();
|
||||
++pPath;
|
||||
assert(m_pDirHeader);
|
||||
}
|
||||
else
|
||||
{
|
||||
// finally, this is the name of the file (or directory)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// goes on to the next entry
|
||||
bool ZipDir::FindFile::FindNext ()
|
||||
{
|
||||
if (m_pDirHeader && m_nFileEntry < m_pDirHeader->numFiles)
|
||||
{
|
||||
++m_nFileEntry;
|
||||
return SkipNonMatchingFiles();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// goes on to the next entry
|
||||
bool ZipDir::FindDir::FindNext ()
|
||||
{
|
||||
if (m_pDirHeader && m_nDirEntry < m_pDirHeader->numDirs)
|
||||
{
|
||||
++m_nDirEntry;
|
||||
return SkipNonMatchingDirs();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ZipDir::FindFile::SkipNonMatchingFiles()
|
||||
{
|
||||
assert(m_pDirHeader && m_nFileEntry <= m_pDirHeader->numFiles);
|
||||
|
||||
for (; m_nFileEntry < m_pDirHeader->numFiles; ++m_nFileEntry)
|
||||
{
|
||||
if (MatchWildcard(GetFileName()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// we didn't find anything other file else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ZipDir::FindDir::SkipNonMatchingDirs()
|
||||
{
|
||||
assert(m_pDirHeader && m_nDirEntry <= m_pDirHeader->numDirs);
|
||||
|
||||
for (; m_nDirEntry < m_pDirHeader->numDirs; ++m_nDirEntry)
|
||||
{
|
||||
if (MatchWildcard(GetDirName()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// we didn't find anything other file else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
ZipDir::FileEntry* ZipDir::FindFile::GetFileEntry()
|
||||
{
|
||||
return m_pDirHeader && m_nFileEntry < m_pDirHeader->numFiles ? m_pDirHeader->GetFileEntry(m_nFileEntry) : NULL;
|
||||
}
|
||||
ZipDir::DirEntry* ZipDir::FindDir::GetDirEntry()
|
||||
{
|
||||
return m_pDirHeader && m_nDirEntry < m_pDirHeader->numDirs ? m_pDirHeader->GetSubdirEntry(m_nDirEntry) : NULL;
|
||||
}
|
||||
|
||||
const char* ZipDir::FindFile::GetFileName ()
|
||||
{
|
||||
if (m_pDirHeader && m_nFileEntry < m_pDirHeader->numFiles)
|
||||
{
|
||||
const char* pNamePool = m_pDirHeader->GetNamePool();
|
||||
return m_pDirHeader->GetFileEntry(m_nFileEntry)->GetName(pNamePool);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ""; // default name
|
||||
}
|
||||
}
|
||||
|
||||
const char* ZipDir::FindDir::GetDirName ()
|
||||
{
|
||||
if (m_pDirHeader && m_nDirEntry < m_pDirHeader->numDirs)
|
||||
{
|
||||
const char* pNamePool = m_pDirHeader->GetNamePool();
|
||||
return m_pDirHeader->GetSubdirEntry(m_nDirEntry)->GetName(pNamePool);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ""; // default name
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user