Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
@@ -0,0 +1,120 @@
/*
* 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_PLATFORM_ANDROID
// Hardware traits ...
#define AZ_TRAIT_USE_PLATFORM_SIMD_SCALAR 1
#define AZ_TRAIT_USE_PLATFORM_SIMD_NEON 0
#define AZ_TRAIT_USE_PLATFORM_SIMD_SSE 0
// OS traits ...
#define AZ_TRAIT_OS_ALLOW_MULTICAST 1
#define AZ_TRAIT_OS_ALLOW_UNLIMITED_PATH_COMPONENT_LENGTH 1
#define AZ_TRAIT_OS_CAN_SET_FILES_WRITABLE 0
#define AZ_TRAIT_OS_DEFAULT_PAGE_SIZE (64 * 1024)
#define AZ_TRAIT_OS_DELETE_THROW noexcept
#define AZ_TRAIT_OS_DLL_EXPORT_CLANG __attribute__ ((visibility ("default")))
#define AZ_TRAIT_OS_DLL_IMPORT_CLANG __attribute__ ((visibility ("default")))
#define AZ_TRAIT_OS_ATTRIBUTE_MARK_USED UNUSED_TRAIT
#define AZ_TRAIT_OS_DYNAMIC_LIBRARY_EXTENSION ".so"
#define AZ_TRAIT_OS_DYNAMIC_LIBRARY_PREFIX "lib"
#define AZ_TRAIT_OS_EXECUTABLE_EXTENSION ""
#define AZ_TRAIT_OS_HAS_CRITICAL_SECTION_SPIN_COUNT 0
#define AZ_TRAIT_OS_HAS_DLL_SUPPORT 1
#define AZ_TRAIT_OS_HAS_MMAP 0
#define AZ_TRAIT_OS_HPHA_MEMORYBLOCKBYTESIZE (150 * 1024 * 1024)
#define AZ_TRAIT_OS_IS_HOST_OS_PLATFORM 0
#define AZ_TRAIT_OS_MEMORY_ALWAYS_NEW_DELETE_SUPPORT_ARRAYS 0
#define AZ_TRAIT_OS_MEMORY_INSTRUMENTATION 0
#define AZ_TRAIT_OS_MEMORY_MAX_ALLOCATOR_SIZE ((size_t)2 * 1024 * 1024 * 1024)
#define AZ_TRAIT_OS_PATH_SEPARATOR '/'
#define AZ_TRAIT_OS_PLATFORM_APPLE 0
#define AZ_TRAIT_OS_PLATFORM_NAME "Android"
#define AZ_TRAIT_OS_PLATFORM_CFG_NAME "android"
#define AZ_TRAIT_OS_PLATFORM_CODENAME AZ_TRAIT_OS_PLATFORM_NAME
#define AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER "android"
#define AZ_TRAIT_OS_STACK_FRAMES_PRINT 0
#define AZ_TRAIT_OS_STACK_FRAMES_TRACE 0
#define AZ_TRAIT_OS_STACK_FRAMES_VALID 1
#define AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS 0
#define AZ_TRAIT_OS_USE_WINDOWS_SET_EVENT 0
#define AZ_TRAIT_OS_USE_WINDOWS_SOCKETS 0
#define AZ_TRAIT_OS_USE_WINDOWS_THREADS 0
#define AZ_TRAIT_OS_USE_WINDOWS_MUTEX 0
#define AZ_TRAIT_SUPPORT_IPC 0
// Compiler traits ...
#define AZ_TRAIT_COMPILER_DEFINE_AZSWNPRINTF_AS_SWPRINTF 1
#define AZ_TRAIT_COMPILER_DEFINE_FS_ERRNO_TYPE 1
#define AZ_TRAIT_COMPILER_DEFINE_FS_STAT_TYPE 0
#define AZ_TRAIT_COMPILER_DEFINE_GETCURRENTPROCESSID 1
#define AZ_TRAIT_COMPILER_DEFINE_REFGUID 0
#define AZ_TRAIT_COMPILER_DEFINE_SASSERTDATA_TYPE 1
#define AZ_TRAIT_COMPILER_DEFINE_WCSICMP 1
#define AZ_TRAIT_COMPILER_INT64_T_IS_LONG 1
#define AZ_TRAIT_COMPILER_OPTIMIZE_MISSING_DEFAULT_SWITCH_CASE 0
#define AZ_TRAIT_COMPILER_PASS_4PLUS_VECTOR_PARAMETERS_BY_VALUE 1
#define AZ_TRAIT_COMPILER_THREAD_LOCAL __thread
#define AZ_TRAIT_COMPILER_USE_STATIC_STORAGE_FOR_NON_POD_STATICS 0
#define AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL 1
// Misc ...
#define AZ_TRAIT_COMMAND_LINE_OPTION_PREFIX "-"
#define AZ_TRAIT_CTIME_GMTIME(tm_ptr, time_t_ptr) gmtime_r(time_t_ptr, tm_ptr)
#define AZ_TRAIT_CTIME_LOCALTIME(tm_ptr, time_t_ptr) localtime_r(time_t_ptr, tm_ptr)
#define AZ_TRAIT_CVARS_ENABLED_FOR_RELEASE_BUILDS 1
#define AZ_TRAIT_DENY_ASSETPROCESSOR_LOOPBACK 0
#define AZ_TRAIT_DOES_NOT_SUPPORT_FILE_DISK_OFFSET 0
#define AZ_TRAIT_HEAPSCHEMA_COMPILE_MALLINFO 0
#define AZ_TRAIT_IS_ABS_PATH_IF_COLON_FOUND_ANYWHERE 0
#define AZ_TRAIT_JSON_CLANG_IGNORE_UNKNOWN_WARNING 0
#define AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS 0
#define AZ_TRAIT_PERF_MEMORYBENCHMARK_IS_AVAILABLE 0
#define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING 0
#define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING_INTERVAL_MS 0
#define AZ_TRAIT_SCRIPT_RECORD_CALLSTACK_DEFAULT false
#define AZ_TRAIT_SEMAPHORE_HAS_NATIVE_MAX_COUNT 0
#define AZ_TRAIT_SET_JOB_PROCESSOR_ID 1
#define AZ_TRAIT_SET_STREAMER_COMPONENT_THREAD_AFFINITY_TO_USERTHREADS 0
#define AZ_TRAIT_SHOW_IGNORE_ALL_ASSERTS_OPTION 1
#define AZ_TRAIT_SKIP_CRYINTERLOCKED 0
#define AZ_TRAIT_SUPPORTS_MICROSOFT_PPL 0
#define AZ_TRAIT_SYSTEMFILE_INVALID_HANDLE nullptr
#define AZ_TRAIT_SYSTEMFILE_FSYNC_IS_DEFINED 1
#define AZ_TRAIT_SYSTEMFILE_UNIX_LIKE_PLATFORM_IS_WRITEABLE_DEFINED_ELSEWHERE 0
#define AZ_TRAIT_TEST_ROOT_FOLDER "/sdcard/Android/data/com.lumberyard.tests/files"
#define AZ_TRAIT_TEST_SUPPORT_DLOPEN 0
#define AZ_TRAIT_TEST_SUPPORT_LOADLIBRARY 0
#define AZ_TRAIT_TEST_SUPPORT_MODULE_LOADING 0
#define AZ_TRAIT_THREAD_AFFINITY_MASK_ALLTHREADS (-1)
#define AZ_TRAIT_THREAD_AFFINITY_MASK_MAINTHREAD AZ_TRAIT_THREAD_AFFINITY_MASK_ALLTHREADS
#define AZ_TRAIT_THREAD_AFFINITY_MASK_RENDERTHREAD AZ_TRAIT_THREAD_AFFINITY_MASK_ALLTHREADS
#define AZ_TRAIT_THREAD_AFFINITY_MASK_WORKERTHREADS AZ_TRAIT_THREAD_AFFINITY_MASK_ALLTHREADS
#define AZ_TRAIT_THREAD_AFFINITY_MASK_ASSET_PROCESSOR_CONNECTION_THREAD 4
#define AZ_TRAIT_THREAD_HARDWARE_CONCURRENCY_RETURN_VALUE static_cast<unsigned int>(sysconf(_SC_NPROCESSORS_ONLN));
#define AZ_TRAIT_UNITTEST_NON_PREALLOCATED_HPHA_TEST 0
#define AZ_TRAIT_UNITTEST_USE_TEST_RUNNER_ENVIRONMENT 1
#define AZ_TRAIT_USE_ASSET_CACHE_FOLDER 0
#define AZ_TRAIT_USE_CRY_SIGNAL_HANDLER 0
#define AZ_TRAIT_USE_POSIX_STRERROR_R 1
#define AZ_TRAIT_USE_SECURE_CRT_FUNCTIONS 0
#define AZ_TRAIT_USE_WINDOWS_FILE_API 0
#define AZ_TRAIT_UUID_SUPPORTS_GUID_CONVERSION 0
#define AZ_TRAIT_USE_ERRNO_T_TYPEDEF 1
#define AZ_TRAIT_USE_POSIX_TEMP_FOLDER 0
// Legacy traits ...
#define AZ_TRAIT_LEGACY_CRYCOMMON_USE_WINDOWS_STUBS 1
#define AZ_TRAIT_LEGACY_CRYPAK_UNIX_LIKE_FILE_SYSTEM 1
#define AZ_TRAIT_LEGACY_CRYSYSTEM_DEFINE_DLLMAIN 0
@@ -0,0 +1,14 @@
/*
* 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/AzCore_Traits_Android.h>
@@ -0,0 +1,29 @@
/*
* 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 <AzCore/Debug/Trace.h>
#include <android/log.h>
namespace AZ
{
namespace Debug
{
namespace Platform
{
void OutputToDebugger([[maybe_unused]] const char* window, [[maybe_unused]] const char* message)
{
__android_log_print(ANDROID_LOG_INFO, window, message);
}
}
}
}
@@ -0,0 +1,14 @@
/*
* 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/Default/AzCore/IO/Streamer/StreamerContext_Default.h>
@@ -0,0 +1,377 @@
/*
* 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 <AzCore/IO/SystemFile.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/IO/FileIOEventBus.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/PlatformIncl.h>
#include <AzCore/std/string/wildcard.h>
#include <AzCore/Utils/Utils.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <dirent.h>
#include <AzCore/Android/APKFileHandler.h>
#include <AzCore/Android/Utils.h>
namespace AZ::IO
{
namespace UnixLikePlatformUtil
{
bool CanCreateDirRecursive(char* dirPath)
{
if (AZ::Android::Utils::IsApkPath(dirPath))
{
return false;
}
return true;
}
}
namespace
{
static const SystemFile::FileHandleType PlatformSpecificInvalidHandle = AZ_TRAIT_SYSTEMFILE_INVALID_HANDLE;
}
bool SystemFile::PlatformOpen(int mode, int platformFlags)
{
const char* openMode = nullptr;
if ((mode & SF_OPEN_READ_ONLY) == SF_OPEN_READ_ONLY)
{
openMode = "r";
}
else if ((mode & SF_OPEN_WRITE_ONLY) == SF_OPEN_WRITE_ONLY)
{
if ((mode & SF_OPEN_APPEND) == SF_OPEN_APPEND)
{
openMode = "a+";
}
else if (mode & (SF_OPEN_TRUNCATE | SF_OPEN_CREATE_NEW | SF_OPEN_CREATE))
{
openMode = "w+";
}
else
{
openMode = "w";
}
}
else if ((mode & SF_OPEN_READ_WRITE) == SF_OPEN_READ_WRITE)
{
if ((mode & SF_OPEN_APPEND) == SF_OPEN_APPEND)
{
openMode = "a+";
}
else if (mode & (SF_OPEN_TRUNCATE | SF_OPEN_CREATE_NEW | SF_OPEN_CREATE))
{
openMode = "w+";
}
else
{
openMode = "r+";
}
}
else
{
EBUS_EVENT(FileIOEventBus, OnError, this, nullptr, EINVAL);
return false;
}
bool createPath = false;
if (mode & (SF_OPEN_CREATE_NEW | SF_OPEN_CREATE))
{
createPath = (mode & SF_OPEN_CREATE_PATH) == SF_OPEN_CREATE_PATH;
}
bool isApkFile = AZ::Android::Utils::IsApkPath(m_fileName);
if (createPath)
{
if (isApkFile)
{
EBUS_EVENT(FileIOEventBus, OnError, this, nullptr, ENOSPC);
return false;
}
CreatePath(m_fileName);
}
int errorCode = 0;
if (isApkFile)
{
AZ::u64 size = 0;
m_handle = AZ::Android::APKFileHandler::Open(m_fileName, openMode, size);
errorCode = EACCES; // general error when a file can't be opened from inside the APK
}
else
{
m_handle = fopen(m_fileName, openMode);
errorCode = errno;
}
if (m_handle == PlatformSpecificInvalidHandle)
{
EBUS_EVENT(FileIOEventBus, OnError, this, nullptr, errorCode);
return false;
}
return true;
}
void SystemFile::PlatformClose()
{
if (m_handle != PlatformSpecificInvalidHandle)
{
fclose(m_handle);
m_handle = PlatformSpecificInvalidHandle;
}
}
namespace Platform::Internal
{
void FindFilesOnDisk(const char* filter, const SystemFile::FindFileCB& cb)
{
// Split the directory of the path filter from the filename portion
AZ::IO::PathView filterPath(filter);
AZ::IO::FixedMaxPathString filterDir{ filterPath.ParentPath().Native() };
AZStd::string_view fileFilter{ filterPath.Filename().Native() };
DIR* dir = opendir(filterDir.c_str());
if (dir != nullptr)
{
// clear the errno state so we can distinguish between real errors and end of stream
errno = 0;
struct dirent* entry = readdir(dir);
// List all the other files in the directory.
while (entry != nullptr)
{
if (AZStd::wildcard_match(fileFilter, entry->d_name))
{
cb(entry->d_name, (entry->d_type & DT_DIR) == 0);
}
entry = readdir(dir);
}
int lastError = errno;
if (lastError != 0)
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, filter, lastError);
}
closedir(dir);
}
else
{
int lastError = errno;
if (lastError != ENOENT)
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, filter, 0);
}
}
}
void FindFilesInApk(const char* filter, const SystemFile::FindFileCB& cb)
{
// Separate the directory from the filename portion of the filter
AZ::IO::PathView filterPath(AZ::Android::Utils::StripApkPrefix(filter));
AZ::IO::FixedMaxPathString filterDir{ filterPath.ParentPath().Native() };
AZStd::string_view fileFilter{ filterPath.Filename().Native() };
// Construct a wrapper function around the SystemFile::FindFileCB parameter
// as the APKFileHandler does not pass into the callback a second parameter indicating
// whether the found file is directory
auto ParseDirectoryFindFile = [&cb, &fileFilter](const char* filename)
{
const bool isFile = !AZ::Android::APKFileHandler::IsDirectory(filename);
if (AZStd::wildcard_match(fileFilter, filename))
{
// Let the user provided callback determine if continuing to iterate over files
// in the APK is allowed
return cb(filename, isFile);
}
// Return true to keep ParseDirectory iterating over files when the file filter doesn't match
return true;
};
AZ::Android::APKFileHandler::ParseDirectory(filterDir.c_str(), ParseDirectoryFindFile);
}
}
namespace Platform
{
using FileHandleType = SystemFile::FileHandleType;
void FindFiles(const char* filter, SystemFile::FindFileCB cb)
{
if (AZ::Android::Utils::IsApkPath(filter))
{
Platform::Internal::FindFilesInApk(filter, cb);
}
else
{
Platform::Internal::FindFilesOnDisk(filter, cb);
}
}
void Seek(FileHandleType handle, const SystemFile* systemFile, SizeType offset, SystemFile::SeekMode mode)
{
if (handle != PlatformSpecificInvalidHandle)
{
off_t result = fseeko(handle, static_cast<off_t>(offset), mode);
if (result != 0)
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, errno);
}
}
}
SystemFile::SizeType Tell(FileHandleType handle, const SystemFile* systemFile)
{
if (handle != PlatformSpecificInvalidHandle)
{
off_t result = ftello(handle);
if (result == (off_t)-1)
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, errno);
return 0;
}
return aznumeric_cast<SizeType>(result);
}
return 0;
}
bool Eof(FileHandleType handle, const SystemFile*)
{
if (handle != PlatformSpecificInvalidHandle)
{
return (feof(handle) != 0);
}
return false;
}
AZ::u64 ModificationTime(FileHandleType handle, const SystemFile* systemFile)
{
if (handle != PlatformSpecificInvalidHandle)
{
struct stat statResult;
if (stat(systemFile->Name(), &statResult) != 0)
{
return 0;
}
return aznumeric_cast<AZ::u64>(statResult.st_mtime);
}
return 0;
}
SystemFile::SizeType Read(FileHandleType handle, const SystemFile* systemFile, SizeType byteSize, void* buffer)
{
if (handle != PlatformSpecificInvalidHandle)
{
size_t bytesToRead = static_cast<size_t>(byteSize);
AZ::Android::APKFileHandler::SetNumBytesToRead(bytesToRead);
size_t bytesRead = fread(buffer, 1, bytesToRead, handle);
if (bytesRead != bytesToRead && ferror(handle))
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, errno);
return 0;
}
return bytesRead;
}
return 0;
}
SystemFile::SizeType Write(FileHandleType handle, const SystemFile* systemFile, const void* buffer, SizeType byteSize)
{
if (handle != PlatformSpecificInvalidHandle)
{
size_t bytesToWrite = static_cast<size_t>(byteSize);
size_t bytesWritten = fwrite(buffer, 1, bytesToWrite, handle);
if (bytesWritten != bytesToWrite && ferror(handle))
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, errno);
return 0;
}
return bytesWritten;
}
return 0;
}
void Flush(FileHandleType handle, const SystemFile* systemFile)
{
if (handle != PlatformSpecificInvalidHandle)
{
if (fflush(handle) != 0)
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, errno);
}
}
}
SystemFile::SizeType Length(FileHandleType handle, const SystemFile* systemFile)
{
if (handle != PlatformSpecificInvalidHandle)
{
const char* fileName = systemFile->Name();
if (AZ::Android::Utils::IsApkPath(fileName))
{
int fileSize = AZ::Android::APKFileHandler::FileLength(fileName);
return static_cast<SizeType>(fileSize);
}
else
{
struct stat fileStat;
if (stat(fileName, &fileStat) < 0)
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, 0);
return 0;
}
return static_cast<SizeType>(fileStat.st_size);
}
}
return 0;
}
bool Exists(const char* fileName)
{
if (AZ::Android::Utils::IsApkPath(fileName))
{
return AZ::Android::APKFileHandler::DirectoryOrFileExists(fileName);
}
else
{
return access(fileName, F_OK) == 0;
}
}
} // namespace AZ::IO::Platform
} // namespace AZ::IO
@@ -0,0 +1,111 @@
/*
* 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 <limits.h>
#include <cstdio>
#include <fcntl.h>
#include <unistd.h>
namespace AZ
{
namespace IO
{
namespace Internal
{
using SizeType = AZ::u64;
using FileHandleType = FILE*;
}
namespace PosixInternal
{
enum class OpenFlags : int
{
Append = O_APPEND, // Moves the file pointer to the end of the file before every write operation.
Create = O_CREAT, // Creates a file and opens it for writing. Has no effect if the file specified by filename exists. PermissionMode is required.
#ifdef O_TMPFILE
Temporary = O_TMPFILE, // Applies only when used with CREAT. Creates a file as temporary; the file is deleted when the last file descriptor is closed. PermissionMode equired when CREAT is specified.
#else
Temporary = 0, // (Not applicable for this platform) Applies only when used with CREAT. Creates a file as temporary; the file is deleted when the last file descriptor is closed. PermissionMode equired when CREAT is specified.
#endif
Exclusive = O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
Truncate = O_TRUNC, // Opens a file and truncates it to zero length; the file must have write permission. Cannot be specified with RDONLY.
// Note: The TRUNC flag destroys the contents of the specified file.
ReadOnly = O_RDONLY, // Opens a file for reading only. Cannot be specified with RDWR or WRONLY.
WriteOnly = O_WRONLY, // Opens a file for writing only. Cannot be specified with RDONLY or RDWR.
ReadWrite = O_RDWR, // Opens a file for both reading and writing. Cannot be specified with RDONLY or WRONLY.
// Windows-specific
NoInherit = 0, // (Not applicable in unix) Prevents creation of a shared file descriptor.
Random = 0, // (Not applicable in unix) Specifies that caching is optimized for, but not restricted to, random access from disk.
Sequential = 0, // (Not applicable in unix) Specifies that caching is optimized for, but not restricted to, sequential access from disk.
Binary = 0, // (Not applicable in unix) Opens the file in binary(untranslated) mode. (See fopen for a description of binary mode.)
Text = 0, // (Not applicable in unix) Opens a file in text(translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.)
U16Text = 0, // (Not applicable in unix) Opens a file in Unicode UTF-16 mode.
U8Text = 0, // (Not applicable in unix) Opens a file in Unicode UTF-8 mode.
WText = 0, // (Not applicable in unix) Opens a file in Unicode mode.
// Unix-specific
Async = O_ASYNC, // Enable signal-driven I/O: generate a signal (SIGIO by default, but this can be changed via fcntl(2)) when input or output becomes possible on this file descriptor. This feature is available only for terminals, pseudoterminals, sockets, and (since Linux 2.6) pipes and FIFOs.
Direct = O_DIRECT, // Try to minimize cache effects of the I/O to and from this file. In general this will degrade performance, but it is useful in special situations, such as when applications do their own caching.
Directory = O_DIRECTORY, // If pathname is not a directory, cause the open to fail.
NoFollow = O_NOFOLLOW, // If the trailing component (i.e., basename) of pathname is a symbolic link, then the open fails, with the error ELOOP. Symbolic links in earlier components of the pathname will still be followed.
#ifdef O_NOATIME
NoAccessTime = O_NOATIME, // Do not update the file last access time.
#else
NoAccessTime = 0, // (Not applicable for this platform) Do not update the file last access time.
#endif
#ifdef O_PATH
Path = O_PATH, // Obtain a file descriptor that can be used for two purposes: to indicate a location in the filesystem tree and to perform operations that act purely at the file descriptor level.
#else
Path = 0, // (Not applicable for this platform) Obtain a file descriptor that can be used for two purposes: to indicate a location in the filesystem tree and to perform operations that act purely at the file descriptor level.
#endif
};
AZ_DEFINE_ENUM_BITWISE_OPERATORS(OpenFlags);
enum class PermissionModeFlags : int
{
None = 0,
Read = S_IRUSR,
Write = S_IWUSR
};
AZ_DEFINE_ENUM_BITWISE_OPERATORS(PermissionModeFlags);
inline int Open(const char* const fileName, OpenFlags openFlags,
PermissionModeFlags newFilePermissions = PermissionModeFlags::None)
{
return open(fileName, static_cast<int>(openFlags), static_cast<int>(newFilePermissions));
}
inline int Close(int fileDescriptor)
{
return close(fileDescriptor);
}
inline int Read(int fileDescriptor, void* data, size_t size)
{
return read(fileDescriptor, data, size);
}
inline int Write(int fileDescriptor, const void* data, size_t size)
{
return write(fileDescriptor, data, size);
}
int Dup(int fileDescriptor);
int Dup2(int fileDescriptorSource, int fileDescriptorDestination);
} // namespace AZ::IO::PosixInternal
} // namespace AZ::IO
} // namespace AZ
@@ -0,0 +1,14 @@
/*
* 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/IO/SystemFile_Android.h>
@@ -0,0 +1,14 @@
/*
* 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/Unimplemented/AzCore/IPC/SharedMemory_Unimplemented.h>
@@ -0,0 +1,17 @@
/*
* 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
#if AZ_TRAIT_USE_PLATFORM_SIMD_NEON
# include <arm_neon.h>
#endif
@@ -0,0 +1,14 @@
/*
* 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/Internal/MathTypes_Android.h>
@@ -0,0 +1,15 @@
/*
* 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/AzCore/Math/Random_UnixLike.h>
@@ -0,0 +1,24 @@
/*
* 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 <AzCore/base.h>
namespace AZ
{
namespace Platform
{
size_t GetHeapCapacity()
{
return 0;
}
}
}
@@ -0,0 +1,14 @@
/*
* 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/AzCore/Memory/OSAllocator_UnixLike.h>
@@ -0,0 +1,14 @@
/*
* 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/Unimplemented/AzCore/Memory/OverrunDetectionAllocator_Unimplemented.h>
@@ -0,0 +1,35 @@
/*
* 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 <AzCore/std/string/osstring.h>
#include <dlfcn.h>
namespace AZ
{
namespace Platform
{
void GetModulePath(AZ::OSString& path)
{
}
void* OpenModule(const AZ::OSString& fileName, bool&)
{
// Android 19 does not have RTLD_NOLOAD but it should be OK since only the Editor expects to reopen modules
return dlopen(fileName.c_str(), RTLD_NOW);
}
void ConstructModuleFullFileName(const AZ::OSString& path, const AZ::OSString& fileName, AZ::OSString& fullPath)
{
fullPath = path + fileName;
}
}
}
@@ -0,0 +1,58 @@
/*
* 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 <AzCore/NativeUI/NativeUISystemComponent.h>
#include <AzCore/Android/JNI/JNI.h>
#include <AzCore/Android/JNI/Object.h>
#include <AzCore/Android/JNI/scoped_ref.h>
#include <AzCore/Android/AndroidEnv.h>
#include <AzCore/Android/Utils.h>
namespace AZ
{
namespace NativeUI
{
AZStd::string NativeUISystemComponent::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector<AZStd::string>& options) const
{
AZ::Android::JNI::Object object("com/amazon/lumberyard/NativeUI/LumberyardNativeUI");
object.RegisterStaticMethod("DisplayDialog", "(Landroid/app/Activity;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V");
object.RegisterStaticMethod("GetUserSelection", "()Ljava/lang/String;");
JNIEnv* env = AZ::Android::JNI::GetEnv();
AZ::Android::JNI::scoped_ref<jobjectArray> joptions(static_cast<jobjectArray>(env->NewObjectArray(options.size(), env->FindClass("java/lang/String"), env->NewStringUTF(""))));
for (int i = 0; i < options.size(); i++)
{
env->SetObjectArrayElement(joptions.get(), i, env->NewStringUTF(options[i].c_str()));
}
AZ::Android::JNI::scoped_ref<jstring> jtitle(AZ::Android::JNI::ConvertStringToJstring(title));
AZ::Android::JNI::scoped_ref<jstring> jmessage(AZ::Android::JNI::ConvertStringToJstring(message));
object.InvokeStaticVoidMethod("DisplayDialog", AZ::Android::Utils::GetActivityRef(), jtitle.get(), jmessage.get(), joptions.get());
AZStd::string userSelection = "";
while (userSelection.empty())
{
userSelection = object.InvokeStaticStringMethod("GetUserSelection");
}
for (int i = 0; i < options.size(); i++)
{
jstring str = static_cast<jstring>(env->GetObjectArrayElement(joptions.get(), i));
env->DeleteLocalRef(str);
}
return userSelection;
}
}
}
@@ -0,0 +1,17 @@
/*
* 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
namespace AZ
{
static const PlatformID g_currentPlatform = PlatformID::PLATFORM_ANDROID_64;
}
@@ -0,0 +1,14 @@
/*
* 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/PlatformId/PlatformId_Android.h>
@@ -0,0 +1,14 @@
/*
* 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/Unimplemented/AzCore/PlatformIncl_Unimplemented.h>
@@ -0,0 +1,14 @@
/*
* 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/AzCore/Socket/AzSocket_UnixLike.h"
@@ -0,0 +1,14 @@
/*
* 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/AzCore/Socket/AzSocket_fwd_UnixLike.h"
@@ -0,0 +1,77 @@
/*
* 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 <AzCore/Utils/Utils.h>
#include <AzCore/PlatformIncl.h>
#include <AzCore/Android/AndroidEnv.h>
#include <AzCore/Android/Utils.h>
#include <AzCore/std/optional.h>
#include <AzCore/std/string/fixed_string.h>
namespace AZ
{
namespace Utils
{
void RequestAbnormalTermination()
{
abort();
}
void NativeErrorMessageBox(const char*, const char*) {}
GetExecutablePathReturnType GetExecutablePath(char* exeStorageBuffer, size_t exeStorageSize)
{
GetExecutablePathReturnType result;
result.m_pathIncludesFilename = false;
const char* privateStoragePath = AZ::Android::AndroidEnv::Get()->GetAppPrivateStoragePath();
if(exeStorageSize > strlen(privateStoragePath))
{
azstrcpy(exeStorageBuffer, exeStorageSize, privateStoragePath);
}
else
{
result.m_pathStored = ExecutablePathResult::BufferSizeNotLargeEnough;
}
return result;
}
// Android attempts to find a bootstrap.cfg file within the public storage for an application
// in non-release builds.
// If a bootstrap.cfg file is not found in the public storage, it is then searched for
// within the APK itself
AZStd::optional<AZStd::fixed_string<MaxPathLength>> GetDefaultAppRootPath()
{
const char* appRoot = AZ::Android::Utils::FindAssetsDirectory();
return appRoot ? AZStd::make_optional<AZStd::fixed_string<MaxPathLength>>(appRoot) : AZStd::nullopt;
}
AZStd::optional<AZStd::fixed_string<MaxPathLength>> ConvertToAbsolutePath(AZStd::string_view path)
{
AZStd::fixed_string<MaxPathLength> absolutePath;
AZStd::fixed_string<MaxPathLength> srcPath{ path };
if (AZ::Android::Utils::IsApkPath(srcPath.c_str()))
{
return srcPath;
}
if(char* result = realpath(srcPath.c_str(), absolutePath.data()); result)
{
// Fix the size value of the fixed string by calculating the c-string length using char traits
absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
return absolutePath;
}
return AZStd::nullopt;
}
}
}
@@ -0,0 +1,12 @@
/*
* 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
@@ -0,0 +1,14 @@
/*
* 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/base_Android.h>
@@ -0,0 +1,39 @@
/*
* 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 <pthread.h>
#include <semaphore.h>
#include <sys/time.h>
namespace AZStd
{
// Mutex
using native_mutex_data_type = pthread_mutex_t;
using native_mutex_handle_type = pthread_mutex_t*;
using native_recursive_mutex_data_type = pthread_mutex_t;
using native_recursive_mutex_handle_type = pthread_mutex_t*;
// Condition variable
using native_cond_var_data_type = pthread_cond_t;
using native_cond_var_handle_type = pthread_cond_t*;
// Semaphore
using native_semaphore_data_type = sem_t;
using native_semaphore_handle_type = sem_t*;
// Thread
using native_thread_id_type = pthread_t;
static constexpr pthread_t native_thread_invalid_id = LONG_MIN;
using native_thread_data_type = pthread_t;
using native_thread_handle_type = pthread_t;
}
@@ -0,0 +1,14 @@
/*
* 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/std/parallel/config_Android.h>
@@ -0,0 +1,15 @@
/*
* 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/AzCore/std/parallel/internal/time_UnixLike.h>
#include <../Common/UnixLike/AzCore/std/parallel/internal/condition_variable_UnixLike.h>
@@ -0,0 +1,14 @@
/*
* 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/AzCore/std/parallel/internal/mutex_UnixLike.h>
@@ -0,0 +1,14 @@
/*
* 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/AzCore/std/parallel/internal/semaphore_UnixLike.h>
@@ -0,0 +1,44 @@
/*
* 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 <AzCore/std/parallel/thread.h>
#include <sched.h>
#include <errno.h>
namespace AZStd
{
namespace Platform
{
void NameCurrentThread(const char*)
{
// Threads are named in PostCreateThread on Android
}
void PreCreateSetThreadAffinity(int , pthread_attr_t&)
{
// Unimplemented on Android
}
void SetThreadPriority(int priority, pthread_attr_t&)
{
// (not supported at v r10d)
AZ_Warning("System", priority <= 0, "Thread priorities %d not supported on Android!\n", priority);
(void)priority;
}
void PostCreateThread(pthread_t tId, const char* name, int)
{
pthread_setname_np(tId, name);
}
}
}
@@ -0,0 +1,14 @@
/*
* 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/AzCore/std/parallel/internal/thread_UnixLike.h>
@@ -0,0 +1,14 @@
/*
* 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/Clang/AzCore/std/string/fixed_string_Clang.inl>
@@ -0,0 +1,16 @@
#
# 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.
#
# Platform specific cmake file for configuring target compiler/link properties
# based on the active platform
# NOTE: functions in cmake are global, therefore adding functions to this file
# is being avoided to prevent overriding functions declared in other targets platfrom
# specific cmake files
@@ -0,0 +1,93 @@
#
# 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
AzCore/PlatformId/PlatformId_Platform.h
AzCore/PlatformId/PlatformId_Android.h
../Common/UnixLike/AzCore/std/parallel/internal/condition_variable_UnixLike.h
../Common/UnixLike/AzCore/std/parallel/internal/mutex_UnixLike.h
../Common/UnixLike/AzCore/std/parallel/internal/semaphore_UnixLike.h
../Common/UnixLike/AzCore/std/parallel/internal/thread_UnixLike.cpp
../Common/UnixLike/AzCore/std/parallel/internal/thread_UnixLike.h
../Common/UnixLike/AzCore/std/parallel/internal/time_UnixLike.h
AzCore/std/parallel/internal/condition_variable_Platform.h
AzCore/std/parallel/internal/mutex_Platform.h
AzCore/std/parallel/internal/semaphore_Platform.h
AzCore/std/parallel/internal/thread_Android.cpp
AzCore/std/parallel/internal/thread_Platform.h
AzCore/std/parallel/config_Android.h
AzCore/std/parallel/config_Platform.h
AzCore/std/string/fixed_string_Platform.inl
../Common/Clang/AzCore/std/string/fixed_string_Clang.inl
../Common/Unimplemented/AzCore/PlatformIncl_Unimplemented.h
../Common/UnixLike/AzCore/Platform_UnixLike.cpp
AzCore/PlatformIncl_Platform.h
../Common/Unimplemented/AzCore/Debug/StackTracer_Unimplemented.cpp
../Common/UnixLike/AzCore/Debug/Trace_UnixLike.cpp
AzCore/Debug/Trace_Android.cpp
../Common/Default/AzCore/IO/Streamer/StreamerConfiguration_Default.cpp
../Common/Default/AzCore/IO/Streamer/StreamerContext_Default.cpp
../Common/Default/AzCore/IO/Streamer/StreamerContext_Default.h
../Common/UnixLike/AzCore/IO/SystemFile_UnixLike.cpp
../Common/UnixLike/AzCore/IO/Internal/SystemFileUtils_UnixLike.h
../Common/UnixLike/AzCore/IO/Internal/SystemFileUtils_UnixLike.cpp
AzCore/IO/Streamer/StreamerContext_Platform.h
AzCore/IO/SystemFile_Android.cpp
AzCore/IO/SystemFile_Android.h
AzCore/IO/SystemFile_Platform.h
AzCore/IPC/SharedMemory_Platform.h
../Common/Unimplemented/AzCore/Memory/OverrunDetectionAllocator_Unimplemented.h
../Common/UnixLike/AzCore/Memory/OSAllocator_UnixLike.h
AzCore/Memory/HeapSchema_Android.cpp
AzCore/Memory/OSAllocator_Platform.h
AzCore/Memory/OverrunDetectionAllocator_Platform.h
../Common/Default/AzCore/Module/Internal/ModuleManagerSearchPathTool_Default.cpp
AzCore/Math/Internal/MathTypes_Android.h
AzCore/Math/Random_Platform.h
../Common/UnixLike/AzCore/Math/Random_UnixLike.cpp
../Common/UnixLike/AzCore/Math/Random_UnixLike.h
../Common/UnixLike/AzCore/Module/DynamicModuleHandle_UnixLike.cpp
AzCore/Module/DynamicModuleHandle_Android.cpp
AzCore/NativeUI/NativeUISystemComponent_Android.cpp
../Common/UnixLike/AzCore/Socket/AzSocket_fwd_UnixLike.h
../Common/UnixLike/AzCore/Socket/AzSocket_UnixLike.cpp
../Common/UnixLike/AzCore/Socket/AzSocket_UnixLike.h
AzCore/Socket/AzSocket_fwd_Platform.h
AzCore/Socket/AzSocket_Platform.h
../Common/UnixLike/AzCore/std/time_UnixLike.cpp
AzCore/Utils/Utils_Android.cpp
../../AzCore/Android/AndroidEnv.cpp
../../AzCore/Android/AndroidEnv.h
../../AzCore/Android/APKFileHandler.cpp
../../AzCore/Android/APKFileHandler.h
../../AzCore/Android/ApiLevel.h
../../AzCore/Android/Utils.cpp
../../AzCore/Android/Utils.h
../../AzCore/Android/JNI/JNI.cpp
../../AzCore/Android/JNI/JNI.h
../../AzCore/Android/JNI/Object.h
../../AzCore/Android/JNI/Object_fwd.h
../../AzCore/Android/JNI/scoped_ref.h
../../AzCore/Android/JNI/shared_ref.h
../../AzCore/Android/JNI/Signature.h
../../AzCore/Android/JNI/Internal/ClassName.h
../../AzCore/Android/JNI/Internal/JStringUtils.h
../../AzCore/Android/JNI/Internal/JStringUtils_impl.h
../../AzCore/Android/JNI/Internal/Object_impl.h
../../AzCore/Android/JNI/Internal/Signature_impl.h
)
if (LY_TEST_PROJECT)
ly_add_source_properties(
SOURCES AzCore/Android/Utils.cpp
PROPERTY COMPILE_DEFINITIONS
VALUES LY_NO_ASSETS
)
endif()
@@ -0,0 +1,20 @@
#
# 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.
#
# Platform specific cmake file for configuring target compiler/link properties
# based on the active platform
# NOTE: functions in cmake are global, therefore adding functions to this file
# is being avoided to prevent overriding functions declared in other targets platfrom
# specific cmake files
if(LY_ENABLE_RAD_TELEMETRY)
set(LY_COMPILE_DEFINITIONS PUBLIC AZ_PROFILE_TELEMETRY)
endif()
@@ -0,0 +1,14 @@
/*
* 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/Default/AzCore/IO/Streamer/StreamerContext_Default.h>
@@ -0,0 +1,82 @@
/*
* 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 <AzCore/Debug/Trace.h>
#include <assert.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
namespace AZ
{
namespace Debug
{
namespace Platform
{
#if defined(AZ_ENABLE_DEBUG_TOOLS)
// Apple Technical Q&A QA1361
// https://developer.apple.com/library/mac/qa/qa1361/_index.html
// Returns true if the current process is being debugged (either
// running under the debugger or has a debugger attached post facto).
bool IsDebuggerPresent()
{
int junk;
int mib[4];
struct kinfo_proc info;
size_t size;
// Initialize the flags so that, if sysctl fails for some bizarre
// reason, we get a predictable result.
info.kp_proc.p_flag = 0;
// Initialize mib, which tells sysctl the info we want, in this case
// we're looking for information about a specific process ID.
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = getpid();
// Call sysctl.
size = sizeof(info);
junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
assert(junk == 0);
// We're being debugged if the P_TRACED flag is set.
return ((info.kp_proc.p_flag & P_TRACED) != 0);
}
void HandleExceptions(bool)
{}
void DebugBreak()
{
raise(SIGINT);
}
#endif // AZ_ENABLE_DEBUG_TOOLS
void Terminate(int exitCode)
{
_exit(exitCode);
}
void OutputToDebugger(const char*, const char*)
{
}
}
}
}
@@ -0,0 +1,68 @@
/*
* 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 <AzCore/IO/FileIO.h>
#include <AzCore/IO/FileIOEventBus.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/std/string/wildcard.h>
#include <../Common/UnixLike/AzCore/IO/Internal/SystemFileUtils_UnixLike.h>
#include <errno.h>
#include <sys/types.h>
#include <dirent.h>
namespace AZ::IO::Platform
{
void FindFiles(const char* filter, SystemFile::FindFileCB cb)
{
// Separate the directory from the filename portion of the filter
AZ::IO::PathView filterPath(filter);
AZ::IO::FixedMaxPathString filterDir{ filterPath.ParentPath().Native() };
AZStd::string_view fileFilter{ filterPath.Filename().Native() };
DIR* dir = opendir(filterDir.c_str());
if (dir != nullptr)
{
// clear the errno state so we can distinguish between real errors and end of stream
errno = 0;
struct dirent* entry = readdir(dir);
// List all the other files in the directory.
while (entry != nullptr)
{
if (AZStd::wildcard_match(fileFilter, entry->d_name))
{
cb(entry->d_name, (entry->d_type & DT_DIR) == 0);
}
entry = readdir(dir);
}
int lastError = errno;
if (lastError != 0)
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, filter, lastError);
}
closedir(dir);
}
else
{
int lastError = errno;
if (lastError != ENOENT)
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, filter, 0);
}
}
}
}
@@ -0,0 +1,110 @@
/*
* 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 <sys/syslimits.h>
#include <fcntl.h>
#include <unistd.h>
namespace AZ
{
namespace IO
{
namespace Internal
{
using SizeType = AZ::u64;
using FileHandleType = int;
}
namespace PosixInternal
{
enum class OpenFlags : int
{
Append = O_APPEND, // Moves the file pointer to the end of the file before every write operation.
Create = O_CREAT, // Creates a file and opens it for writing. Has no effect if the file specified by filename exists. PermissionMode is required.
#ifdef O_TMPFILE
Temporary = O_TMPFILE, // Applies only when used with CREAT. Creates a file as temporary; the file is deleted when the last file descriptor is closed. PermissionMode equired when CREAT is specified.
#else
Temporary = 0, // (Not applicable for this platform) Applies only when used with CREAT. Creates a file as temporary; the file is deleted when the last file descriptor is closed. PermissionMode equired when CREAT is specified.
#endif
Exclusive = O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
Truncate = O_TRUNC, // Opens a file and truncates it to zero length; the file must have write permission. Cannot be specified with RDONLY.
// Note: The TRUNC flag destroys the contents of the specified file.
ReadOnly = O_RDONLY, // Opens a file for reading only. Cannot be specified with RDWR or WRONLY.
WriteOnly = O_WRONLY, // Opens a file for writing only. Cannot be specified with RDONLY or RDWR.
ReadWrite = O_RDWR, // Opens a file for both reading and writing. Cannot be specified with RDONLY or WRONLY.
// Windows-specific
NoInherit = 0, // (Not applicable in unix) Prevents creation of a shared file descriptor.
Random = 0, // (Not applicable in unix) Specifies that caching is optimized for, but not restricted to, random access from disk.
Sequential = 0, // (Not applicable in unix) Specifies that caching is optimized for, but not restricted to, sequential access from disk.
Binary = 0, // (Not applicable in unix) Opens the file in binary(untranslated) mode. (See fopen for a description of binary mode.)
Text = 0, // (Not applicable in unix) Opens a file in text(translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.)
U16Text = 0, // (Not applicable in unix) Opens a file in Unicode UTF-16 mode.
U8Text = 0, // (Not applicable in unix) Opens a file in Unicode UTF-8 mode.
WText = 0, // (Not applicable in unix) Opens a file in Unicode mode.
// Unix-specific
Async = O_ASYNC, // Enable signal-driven I/O: generate a signal (SIGIO by default, but this can be changed via fcntl(2)) when input or output becomes possible on this file descriptor. This feature is available only for terminals, pseudoterminals, sockets, and (since Linux 2.6) pipes and FIFOs.
Direct = 0, // Try to minimize cache effects of the I/O to and from this file. In general this will degrade performance, but it is useful in special situations, such as when applications do their own caching.
Directory = O_DIRECTORY, // If pathname is not a directory, cause the open to fail.
NoFollow = O_NOFOLLOW, // If the trailing component (i.e., basename) of pathname is a symbolic link, then the open fails, with the error ELOOP. Symbolic links in earlier components of the pathname will still be followed.
#ifdef O_NOATIME
NoAccessTime = O_NOATIME, // Do not update the file last access time.
#else
NoAccessTime = 0, // (Not applicable for this platform) Do not update the file last access time.
#endif
#ifdef O_PATH
Path = O_PATH, // Obtain a file descriptor that can be used for two purposes: to indicate a location in the filesystem tree and to perform operations that act purely at the file descriptor level.
#else
Path = 0, // (Not applicable for this platform) Obtain a file descriptor that can be used for two purposes: to indicate a location in the filesystem tree and to perform operations that act purely at the file descriptor level.
#endif
};
AZ_DEFINE_ENUM_BITWISE_OPERATORS(OpenFlags);
enum class PermissionModeFlags : int
{
None = 0,
Read = S_IRUSR,
Write = S_IWUSR
};
AZ_DEFINE_ENUM_BITWISE_OPERATORS(PermissionModeFlags);
inline int Open(const char* const fileName, OpenFlags openFlags,
PermissionModeFlags newFilePermissions = PermissionModeFlags::None)
{
return open(fileName, static_cast<int>(openFlags), static_cast<int>(newFilePermissions));
}
inline int Close(int fileDescriptor)
{
return close(fileDescriptor);
}
inline int Read(int fileDescriptor, void* data, size_t size)
{
return read(fileDescriptor, data, size);
}
inline int Write(int fileDescriptor, const void* data, size_t size)
{
return write(fileDescriptor, data, size);
}
int Dup(int fileDescriptor);
int Dup2(int fileDescriptorSource, int fileDescriptorDestination);
} // namespace AZ::IO::PosixInternal
} // namespace AZ::IO
} // namespace AZ
@@ -0,0 +1,24 @@
/*
* 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
inline void* memalign(size_t blocksize, size_t bytes)
{
void* ptr = nullptr;
int result = posix_memalign(&ptr, blocksize < sizeof(void*) ? sizeof(void*) : blocksize, bytes);
AZ_Assert(result == 0, "Posix memalign failed %d", result);
(void)result; // avoid unused variable warning
return ptr;
}
# define AZ_OS_MALLOC(byteSize, alignment) memalign(alignment, byteSize)
# define AZ_OS_FREE(pointer) ::free(pointer)
@@ -0,0 +1,49 @@
/*
* 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 <AzCore/IO/SystemFile.h> // for AZ_MAX_PATH_LEN
#include <AzCore/std/string/osstring.h>
#include <AzCore/Utils/Utils.h>
#include <dlfcn.h>
namespace AZ
{
namespace Platform
{
void GetModulePath(AZ::OSString& path)
{
char exePath[AZ_MAX_PATH_LEN];
if (AZ::Utils::GetExecutableDirectory(exePath, AZ_ARRAY_SIZE(exePath)) ==
AZ::Utils::ExecutablePathResult::Success)
{
path = exePath;
path.push_back('/');
}
}
void* OpenModule(const AZ::OSString& fileName, bool& alreadyOpen)
{
void* handle = dlopen(fileName.c_str(), RTLD_NOLOAD);
alreadyOpen = (handle != nullptr);
if (!alreadyOpen)
{
handle = dlopen(fileName.c_str(), RTLD_NOW);
}
return handle;
}
void ConstructModuleFullFileName(const AZ::OSString& path, const AZ::OSString& fileName, AZ::OSString& fullPath)
{
fullPath = path + fileName;
}
}
}
@@ -0,0 +1,36 @@
/*
* 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 <AzCore/Utils/Utils.h>
#include <AzCore/PlatformIncl.h>
#include <mach-o/dyld.h>
namespace AZ
{
namespace Utils
{
GetExecutablePathReturnType GetExecutablePath(char* exeStorageBuffer, size_t exeStorageSize)
{
GetExecutablePathReturnType result;
result.m_pathIncludesFilename = true;
// https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dyld.3.html
auto bufSize = static_cast<uint32_t>(exeStorageSize);
const int getExecutableResultCode = _NSGetExecutablePath(exeStorageBuffer, &bufSize);
if (getExecutableResultCode == -1)
{
result.m_pathStored = ExecutablePathResult::BufferSizeNotLargeEnough;
}
return result;
}
}
}
@@ -0,0 +1,40 @@
/*
* 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 <pthread.h>
#include <semaphore.h>
#include <sys/time.h>
#include <mach/mach.h>
namespace AZStd
{
// Mutex
using native_mutex_data_type = pthread_mutex_t;
using native_mutex_handle_type = pthread_mutex_t*;
using native_recursive_mutex_data_type = pthread_mutex_t;
using native_recursive_mutex_handle_type = pthread_mutex_t*;
// Condition variable
using native_cond_var_data_type = pthread_cond_t;
using native_cond_var_handle_type = pthread_cond_t*;
// Semaphore
using native_semaphore_data_type = semaphore_t;
using native_semaphore_handle_type = semaphore_t*;
// Thread
using native_thread_id_type = pthread_t;
static constexpr pthread_t native_thread_invalid_id = 0;
using native_thread_data_type = pthread_t;
using native_thread_handle_type = pthread_t;
}
@@ -0,0 +1,131 @@
/*
* 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 "time_Apple.h"
#include <AzCore/std/algorithm.h>
#include <mach/kern_return.h>
#include <unistd.h>
#include <AzCore/std/chrono/clocks.h>
/**
* This file is to be included from the semaphore.h only. It should NOT be included by the user.
*/
namespace AZStd
{
inline semaphore::semaphore(unsigned int initialCount, unsigned int maximumCount)
{
// Clamp the semaphores initial value to prevent issues with the semaphore.
int initSemCount = static_cast<int>(AZStd::min(initialCount, static_cast<unsigned int>(semaphore::MAXIMUM_COUNT)));
int result = semaphore_create(mach_task_self(), &m_semaphore, SYNC_POLICY_FIFO, initSemCount);
AZ_Assert(result == 0, "semaphore_create error %s\n", strerror(errno));
int maxSemCount = static_cast<int>(AZStd::min(maximumCount, static_cast<unsigned int>(semaphore::MAXIMUM_COUNT)));
result = semaphore_create(mach_task_self(), &m_maxCountSemaphore, SYNC_POLICY_FIFO, maxSemCount);
AZ_Assert(result == 0, "semaphore_create error for max count semaphore %s\n", strerror(errno));
}
inline semaphore::semaphore(const char* name, unsigned int initialCount, unsigned int maximumCount)
{
(void) name; // name is used only for debug, if we pass it to the semaphore it will become named semaphore
// Clamp the semaphores initial value to prevent issues with the semaphore.
int initSemCount = static_cast<int>(AZStd::min(initialCount, static_cast<unsigned int>(semaphore::MAXIMUM_COUNT)));
int result = semaphore_create(mach_task_self(), &m_semaphore, SYNC_POLICY_FIFO, initSemCount);
AZ_Assert(result == 0, "semaphore_create error %s\n", strerror(errno));
int maxSemCount = static_cast<int>(AZStd::min(maximumCount, static_cast<unsigned int>(semaphore::MAXIMUM_COUNT)));
result = semaphore_create(mach_task_self(), &m_maxCountSemaphore, SYNC_POLICY_FIFO, maxSemCount);
AZ_Assert(result == 0, "semaphore_create error for max count semaphore %s\n", strerror(errno));
}
inline semaphore::~semaphore()
{
int result = semaphore_destroy(mach_task_self(), m_semaphore);
(void) result;
AZ_Assert(result == 0, "semaphore_destroy error %s\n", strerror(errno));
result = semaphore_destroy(mach_task_self(), m_maxCountSemaphore);
AZ_Assert(result == 0, "semaphore_destroy error for max count semaphore:%s\n", strerror(errno));
}
inline void semaphore::acquire()
{
int result = semaphore_signal(m_maxCountSemaphore);
(void)result;
AZ_Assert(result == 0, "semaphore_wait error for max count semaphore: %s\n", strerror(errno));
result = semaphore_wait(m_semaphore);
AZ_Assert(result == 0, "semaphore_wait error %s\n", strerror(errno));
}
template <class Rep, class Period>
AZ_FORCE_INLINE bool semaphore::try_acquire_for(const chrono::duration<Rep, Period>& rel_time)
{
mach_timespec_t mts;
// note that in the mach kernel (Mac), semaphore_timedwait is used instead of the posix
// sem_timedwait. The major difference is that semaphore_timedwait expects a delta time
// wheras sem_timedwait expects an absolute time.
mts.tv_sec = static_cast<unsigned int>(chrono::duration_cast<chrono::seconds>(rel_time).count());
chrono::duration<Rep, Period> remainder = rel_time - chrono::seconds(mts.tv_sec);
mts.tv_nsec = static_cast<clock_res_t>(chrono::duration_cast<chrono::nanoseconds>(remainder).count());
int result = 0;
while ((result = semaphore_timedwait(m_semaphore, mts)) == -1 && errno == EINTR)
{
continue; /* Restart if interrupted by handler */
}
// semaphore_timedwait never sets errno, but returns KERN_OPERATION_TIMED_OUT
// if "Some thread-oriented operation (semaphore_wait) timed out"
// http://opensource.apple.com//source/xnu/xnu-2422.1.72/osfmk/kern/sync_sema.c
// http://opensource.apple.com/source/xnu/xnu-2422.1.72/osfmk/mach/kern_return.h
AZ_Assert(result == 0 || result == KERN_OPERATION_TIMED_OUT, "semaphore_timedwait error %d\n", result);
return result == 0;
}
template <class Clock, class Duration>
AZ_FORCE_INLINE bool semaphore::try_acquire_until(const chrono::time_point<Clock, Duration>& abs_time)
{
auto nowTime = chrono::system_clock::now();
if (nowTime >= abs_time)
{
return false; // we have already timed out.
}
auto deltaTime = abs_time - nowTime;
return try_acquire_for(deltaTime);
}
inline void semaphore::release(unsigned int releaseCount)
{
int result = semaphore_wait(m_maxCountSemaphore);
AZ_Assert(result == 0, "semaphore_wait error for max count semaphore: %s\n", strerror(errno));
while (releaseCount)
{
result = semaphore_signal(m_semaphore);
AZ_Assert(result == 0, "semaphore_signal error: %s\n", strerror(errno));
if (result != 0)
{
break; // exit on error
}
--releaseCount;
}
}
inline semaphore::native_handle_type semaphore::native_handle()
{
return &m_semaphore;
}
}
@@ -0,0 +1,67 @@
/*
* 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 <AzCore/std/parallel/thread.h>
#include <sched.h>
#include <errno.h>
#include <mach/thread_policy.h>
#include <mach/thread_act.h>
namespace AZStd
{
namespace Platform
{
void NameCurrentThread(const char* name)
{
// On Apple, we name a new thread from that thread itself
if (!name)
{
name = "AZStd thread";
}
pthread_setname_np(name);
}
void PreCreateSetThreadAffinity(int, pthread_attr_t&)
{
// Affinity set in PostCreateThread on Apple platforms
}
void SetThreadPriority(int priority, pthread_attr_t& attr)
{
if (priority == -1)
{
pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
}
else
{
struct sched_param schedParam;
memset(&schedParam, 0, sizeof(schedParam));
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
schedParam.sched_priority = priority;
pthread_attr_setschedparam(&attr, &schedParam);
}
}
void PostCreateThread(pthread_t tId, const char*, int cpuId)
{
// On Apple platforms thread affinity is set after the thread is created
if (cpuId >= 0) // TODO: add a proper mask to support more than one core that can run the thread!!!
{
mach_port_t mach_thread = pthread_mach_thread_np(tId);
thread_affinity_policy_data_t policyData = { cpuId };
thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY, (thread_policy_t)& policyData, 1);
}
}
}
}
@@ -0,0 +1,59 @@
/*
* 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 <time.h>
#include <errno.h>
#include <mach/mach.h>
#include <mach/clock.h>
#include <mach/mach_time.h>
namespace AZStd
{
namespace Internal
{
AZ_FORCE_INLINE timespec CurrentTime()
{
struct timespec ts;
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
ts.tv_sec = mts.tv_sec;
ts.tv_nsec = mts.tv_nsec;
return ts;
}
template <class Rep, class Period>
AZ_FORCE_INLINE timespec CurrentTimeAndOffset(const chrono::duration<Rep, Period>& rel_time)
{
timespec ts = CurrentTime();
chrono::seconds timeInSeconds = rel_time;
ts.tv_sec += timeInSeconds.count();
ts.tv_nsec += chrono::nanoseconds(rel_time - timeInSeconds).count();
// note that ts.tv_nsec could have overflowed 'one second' worth of nanoseconds but since CurrentTime()
// will always return under 1,000,000,000 nanoseconds and so will the subtraction above here, the
// largest the two could be is 1,999,999,999 nanoseconds when summed together, so we do not have to do
// a while loop, one subtraction is enough.
if (ts.tv_nsec >= 1000000000)
{
ts.tv_nsec -= 1000000000;
ts.tv_sec += 1;
}
return ts;
}
}
}
@@ -0,0 +1,123 @@
/*
* 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 <AzCore/std/time.h>
#include <time.h>
#include <errno.h>
#include <mach/mach.h>
#include <mach/clock.h>
#include <mach/mach_time.h>
namespace AZStd
{
AZStd::sys_time_t GetTimeTicksPerSecond()
{
// Value is in nano seconds, return number of nano seconds in one second
AZStd::sys_time_t freq = 1000000000L;
return freq;
}
AZStd::sys_time_t GetTimeNowTicks()
{
AZStd::sys_time_t timeNow;
struct timespec ts;
clock_serv_t cclock;
mach_timespec_t mts;
kern_return_t ret = host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
if (ret == KERN_SUCCESS)
{
ret = clock_get_time(cclock, &mts);
if (ret == KERN_SUCCESS)
{
ts.tv_sec = mts.tv_sec;
ts.tv_nsec = mts.tv_nsec;
}
else
{
AZ_Assert(false, "clock_get_time error: %d\n", ret);
}
mach_port_deallocate(mach_task_self(), cclock);
}
else
{
AZ_Assert(false, "clock_get_time error: %d\n", ret);
}
timeNow = ts.tv_sec * GetTimeTicksPerSecond() + ts.tv_nsec;
return timeNow;
}
AZStd::sys_time_t GetTimeNowMicroSecond()
{
AZStd::sys_time_t timeNowMicroSecond;
timeNowMicroSecond = GetTimeNowTicks() / 1000L;
return timeNowMicroSecond;
}
// time in seconds is the same as the POSIX time_t
AZStd::sys_time_t GetTimeNowSecond()
{
AZStd::sys_time_t timeNowSecond;
struct timespec ts;
clock_serv_t cclock;
mach_timespec_t mts;
kern_return_t ret = host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
if (ret == KERN_SUCCESS)
{
ret = clock_get_time(cclock, &mts);
if (ret == KERN_SUCCESS)
{
ts.tv_sec = mts.tv_sec;
ts.tv_nsec = mts.tv_nsec;
}
else
{
AZ_Assert(false, "clock_get_time error: %d\n", ret);
}
mach_port_deallocate(mach_task_self(), cclock);
}
else
{
AZ_Assert(false, "clock_get_time error: %d\n", ret);
}
timeNowSecond = ts.tv_sec;
return timeNowSecond;
}
AZ::u64 GetTimeUTCMilliSecond()
{
AZ::u64 utc;
struct timespec ts;
clock_serv_t cclock;
mach_timespec_t mts;
kern_return_t ret = host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
if (ret == KERN_SUCCESS)
{
ret = clock_get_time(cclock, &mts);
if (ret == KERN_SUCCESS)
{
ts.tv_sec = mts.tv_sec;
ts.tv_nsec = mts.tv_nsec;
}
else
{
AZ_Assert(false, "clock_get_time error: %d\n", ret);
}
mach_port_deallocate(mach_task_self(), cclock);
}
else
{
AZ_Assert(false, "clock_get_time error: %d\n", ret);
}
utc = ts.tv_sec * 1000L + ts.tv_nsec / 1000000L;
return utc;
}
}
@@ -0,0 +1,28 @@
/*
* 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
namespace AZStd
{
template<class Element, size_t MaxElementCount, class Traits>
inline decltype(auto) basic_fixed_string<Element, MaxElementCount, Traits>::format_arg(const wchar_t* format, va_list argList)
{
basic_fixed_string<wchar_t, MaxElementCount, char_traits<wchar_t>> result;
constexpr int maxBufferLength = 2048;
wchar_t buffer[maxBufferLength];
[[maybe_unused]] const int len = azvsnwprintf(buffer, maxBufferLength, format, argList);
AZ_Assert(len != -1, "azvsnwprintf failed increase the buffer size!");
result += buffer;
return result;
}
}
@@ -0,0 +1,32 @@
/*
* 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 <AzCore/IO/IStreamerTypes.h>
#include <AzCore/IO/Streamer/StreamerConfiguration.h>
namespace AZ::IO
{
bool CollectIoHardwareInformation(HardwareInformation& info, [[maybe_unused]] bool includeAllHardware)
{
// The numbers below are based on common defaults from a local hardware survey.
info.m_maxPageSize = 4096;
info.m_maxTransfer = 512_kib;
info.m_maxPhysicalSectorSize = 4096;
info.m_maxLogicalSectorSize = 512;
info.m_profile = "Generic";
return true;
}
void ReflectNative([[maybe_unused]] ReflectContext* context)
{
}
} // namespace AZ::IO
@@ -0,0 +1,37 @@
/*
* 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 "StreamerContext_Default.h"
namespace AZ::Platform
{
void StreamerContextThreadSync::Suspend()
{
auto predicate = [this]() -> bool
{
// Don't go to sleep if there's a wake up call queued
return m_threadWakeUpQueued.load(AZStd::memory_order_acquire);
};
AZStd::unique_lock<AZStd::mutex> lock(m_threadSleepLock);
m_threadSleepCondition.wait(lock, predicate);
m_threadWakeUpQueued.store(false, AZStd::memory_order_release);
}
void StreamerContextThreadSync::Resume()
{
AZStd::unique_lock<AZStd::mutex> lock(m_threadSleepLock);
m_threadWakeUpQueued.store(true, AZStd::memory_order_release);
m_threadSleepCondition.notify_one();
}
} // namespace AZ::Platform
@@ -0,0 +1,33 @@
/*
* 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/PlatformIncl.h>
#include <AzCore/std/parallel/mutex.h>
#include <AzCore/std/parallel/condition_variable.h>
namespace AZ::Platform
{
class StreamerContextThreadSync
{
public:
void Suspend();
void Resume();
private:
AZStd::mutex m_threadSleepLock;
AZStd::atomic<bool> m_threadWakeUpQueued{ false }; //!< Whether or not there's a wake up call queued.
AZStd::condition_variable m_threadSleepCondition;
};
} // namespace AZ::Platform
@@ -0,0 +1,31 @@
/*
* 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 <AzCore/Module/Internal/ModuleManagerSearchPathTool.h>
namespace AZ
{
namespace Internal
{
ModuleManagerSearchPathTool::ModuleManagerSearchPathTool()
{
}
ModuleManagerSearchPathTool::~ModuleManagerSearchPathTool()
{
}
void ModuleManagerSearchPathTool::SetModuleSearchPath(const AZ::DynamicModuleDescriptor&)
{
}
} // namespace Internal
} // namespace AZ
@@ -0,0 +1,30 @@
/*
* 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
namespace AZStd
{
template<class Element, size_t MaxElementCount, class Traits>
inline decltype(auto) basic_fixed_string<Element, MaxElementCount, Traits>::format_arg(const wchar_t* format, va_list argList)
{
basic_fixed_string<wchar_t, MaxElementCount, char_traits<wchar_t>> result;
int len = _vscwprintf(format, argList);
if (len > 0)
{
result.resize(len);
len = azvsnwprintf(result.data(), result.capacity() + 1, format, argList);
AZ_Assert(len == static_cast<int>(result.size()), "azvsnwprintf failed!");
}
return result;
}
}
@@ -0,0 +1,163 @@
/*
* 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
#ifdef AZ_PROFILE_TELEMETRY
/*!
* ProfileTelemetry.h provides a RAD Telemetry specific implementation of the AZ_PROFILE_FUNCTION, AZ_PROFILE_SCOPE, and AZ_PROFILE_SCOPE_DYNAMIC performance instrumentation markers
*/
#define TM_API_PTR g_radTmApi
#include <rad_tm.h>
#include <AzCore/Math/Color.h>
namespace ProfileTelemetryInternal
{
inline constexpr tm_uint32 ConvertColor(uint32_t rgba)
{
return
((rgba >> 24) & 0x000000ff) | // move byte 3 to byte 0
((rgba << 8) & 0x00ff0000) | // move byte 1 to byte 2
((rgba >> 8) & 0x0000ff00) | // move byte 2 to byte 1
((rgba << 24) & 0xff000000); // byte 0 to byte 3
}
inline constexpr tm_uint32 ConvertColor(const AZ::Color& color)
{
return ConvertColor(color.ToU32());
}
}
#define AZ_PROFILE_CAT_TO_RAD_CAPFLAGS(category) (static_cast<AZ::Debug::ProfileCategoryPrimitiveType>(1) << static_cast<AZ::Debug::ProfileCategoryPrimitiveType>(category))
// Helpers
#define AZ_INTERNAL_PROF_VERIFY_CAT(category) static_assert(category < AZ::Debug::ProfileCategory::Count, "Invalid profile category")
#define AZ_INTERNAL_PROF_MEMORY_CAT_TO_FLAGS(category) (AZ_PROFILE_CAT_TO_RAD_CAPFLAGS(category) | \
AZ_PROFILE_CAT_TO_RAD_CAPFLAGS(AZ::Debug::ProfileCategory::MemoryReserved))
#define AZ_INTERNAL_PROF_VERIFY_INTERVAL_ID(id) static_assert(sizeof(id) <= sizeof(tm_uint64), "Interval id must be a unique value no larger than 64-bits")
#define AZ_INTERNAL_PROF_TM_FUNC_VERIFY_CAT(category, flags) \
AZ_INTERNAL_PROF_VERIFY_CAT(category); \
tmFunction(AZ_PROFILE_CAT_TO_RAD_CAPFLAGS(category), flags)
#define AZ_INTERNAL_PROF_TM_ZONE_VERIFY_CAT(category, flags, ...) \
AZ_INTERNAL_PROF_VERIFY_CAT(category); \
tmZone(AZ_PROFILE_CAT_TO_RAD_CAPFLAGS(category), flags, __VA_ARGS__)
// AZ_PROFILE_FUNCTION
#define AZ_PROFILE_FUNCTION(category) \
AZ_INTERNAL_PROF_TM_FUNC_VERIFY_CAT(category, TMZF_NONE)
#define AZ_PROFILE_FUNCTION_STALL(category) \
AZ_INTERNAL_PROF_TM_FUNC_VERIFY_CAT(category, TMZF_STALL)
#define AZ_PROFILE_FUNCTION_IDLE(category) \
AZ_INTERNAL_PROF_TM_FUNC_VERIFY_CAT(category, TMZF_IDLE)
// AZ_PROFILE_SCOPE
#define AZ_PROFILE_SCOPE(category, name) \
AZ_INTERNAL_PROF_TM_ZONE_VERIFY_CAT(category, TMZF_NONE, name)
#define AZ_PROFILE_SCOPE_STALL(category, name) \
AZ_INTERNAL_PROF_TM_ZONE_VERIFY_CAT(category, TMZF_STALL, name)
#define AZ_PROFILE_SCOPE_IDLE(category, name) \
AZ_INTERNAL_PROF_TM_ZONE_VERIFY_CAT(category, TMZF_IDLE, name)
// AZ_PROFILE_SCOPE_DYNAMIC
// For profiling events with dynamic scope names
// Note: the first variable argument must be a const format string
// Usage: AZ_PROFILE_SCOPE_DYNAMIC(AZ::Debug::ProfileCategory, <printf style const format string>, format args...)
#define AZ_PROFILE_SCOPE_DYNAMIC(category, ...) \
AZ_INTERNAL_PROF_TM_ZONE_VERIFY_CAT(category, TMZF_NONE, __VA_ARGS__)
#define AZ_PROFILE_SCOPE_STALL_DYNAMIC(category, ...) \
AZ_INTERNAL_PROF_TM_ZONE_VERIFY_CAT(category, TMZF_STALL, __VA_ARGS__)
#define AZ_PROFILE_SCOPE_IDLE_DYNAMIC(category, ...) \
AZ_INTERNAL_PROF_TM_ZONE_VERIFY_CAT(category, TMZF_IDLE, __VA_ARGS__)
// AZ_PROFILE_EVENT_BEGIN/END
// For profiling events that do not start and stop in the same scope (they MUST start/stop on the same thread)
// ALWAYS favor using scoped events (AZ_PROFILE_FUNCTION, AZ_PROFILE_SCOPE) as debugging an unmatched begin/end can be challenging
#define AZ_PROFILE_EVENT_BEGIN(category, name) \
AZ_INTERNAL_PROF_VERIFY_CAT(category); \
tmEnter(AZ_PROFILE_CAT_TO_RAD_CAPFLAGS(category), TMZF_NONE, name)
#define AZ_PROFILE_EVENT_END(category) \
AZ_INTERNAL_PROF_VERIFY_CAT(category); \
tmLeave(AZ_PROFILE_CAT_TO_RAD_CAPFLAGS(category))
// AZ_PROFILE_INTERVAL (mapped to Telemetry Timespan APIs)
// Note: using C-style casting as we allow either pointers or integral types as IDs
#define AZ_PROFILE_INTERVAL_START(category, id, ...) \
AZ_INTERNAL_PROF_VERIFY_CAT(category); \
AZ_INTERNAL_PROF_VERIFY_INTERVAL_ID(id); \
tmBeginTimeSpan(AZ_PROFILE_CAT_TO_RAD_CAPFLAGS(category), (tm_uint64)(id), TMZF_NONE, __VA_ARGS__)
#define AZ_PROFILE_INTERVAL_START_COLORED(category, id, color, ...) \
AZ_INTERNAL_PROF_VERIFY_CAT(category); \
AZ_INTERNAL_PROF_VERIFY_INTERVAL_ID(id); \
tmBeginColoredTimeSpan(AZ_PROFILE_CAT_TO_RAD_CAPFLAGS(category), (tm_uint64)(id), 0, ProfileTelemetryInternal::ConvertColor(color), TMZF_NONE, __VA_ARGS__)
#define AZ_PROFILE_INTERVAL_END(category, id) \
AZ_INTERNAL_PROF_VERIFY_CAT(category); \
AZ_INTERNAL_PROF_VERIFY_INTERVAL_ID(id); \
tmEndTimeSpan(AZ_PROFILE_CAT_TO_RAD_CAPFLAGS(category), (tm_uint64)(id))
// AZ_PROFILE_INTERVAL_SCOPED
// Scoped interval event that implicitly starts and ends in the same scope
// Note: using C-style casting as we allow either pointers or integral types as IDs
// Note: the first variable argument must be a const format string
// Usage: AZ_PROFILE_INTERVAL_SCOPED(AZ::Debug::ProfileCategory, <unique interval id>, <printf style const format string>, format args...)
#define AZ_PROFILE_INTERVAL_SCOPED(category, id, ...) \
AZ_INTERNAL_PROF_VERIFY_CAT(category); \
AZ_INTERNAL_PROF_VERIFY_INTERVAL_ID(id); \
tmTimeSpan(AZ_PROFILE_CAT_TO_RAD_CAPFLAGS(category), (tm_uint64)(id), TM_MIN_TIME_SPAN_TRACK_ID + static_cast<AZ::Debug::ProfileCategoryPrimitiveType>(category), 0, TMZF_NONE, __VA_ARGS__)
// AZ_PROFILE_DATAPOINT (mapped to tmPlot APIs)
// Note: data points can have static or dynamic names, if using a dynamic name the first variable argument must be a const format string
// Usage: AZ_PROFILE_DATAPOINT(AZ::Debug::ProfileCategory, <printf style const format string>, format args...)
#define AZ_PROFILE_DATAPOINT(category, value, ...) \
AZ_INTERNAL_PROF_VERIFY_CAT(category); \
tmPlot(AZ_PROFILE_CAT_TO_RAD_CAPFLAGS(category), TM_PLOT_UNITS_REAL, TM_PLOT_DRAW_LINE, static_cast<double>(value), __VA_ARGS__)
#define AZ_PROFILE_DATAPOINT_PERCENT(category, value, ...) \
AZ_INTERNAL_PROF_VERIFY_CAT(category); \
tmPlot(AZ_PROFILE_CAT_TO_RAD_CAPFLAGS(category), TM_PLOT_UNITS_PERCENTAGE_DIRECT, TM_PLOT_DRAW_LINE, static_cast<double>(value), __VA_ARGS__)
// AZ_PROFILE_MEMORY_ALLOC
#define AZ_PROFILE_MEMORY_ALLOC(category, address, size, context) \
AZ_INTERNAL_PROF_VERIFY_CAT(category); \
tmAlloc(AZ_INTERNAL_PROF_MEMORY_CAT_TO_FLAGS(category), address, size, context)
#define AZ_PROFILE_MEMORY_ALLOC_EX(category, filename, lineNumber, address, size, context) \
AZ_INTERNAL_PROF_VERIFY_CAT(category); \
tmAllocEx(AZ_INTERNAL_PROF_MEMORY_CAT_TO_FLAGS(category), filename, lineNumber, address, size, context)
#define AZ_PROFILE_MEMORY_FREE(category, address) \
AZ_INTERNAL_PROF_VERIFY_CAT(category); \
tmFree(AZ_INTERNAL_PROF_MEMORY_CAT_TO_FLAGS(category), address)
#define AZ_PROFILE_MEMORY_FREE_EX(category, filename, lineNumber, address) \
AZ_INTERNAL_PROF_VERIFY_CAT(category); \
tmFreeEx(AZ_INTERNAL_PROF_MEMORY_CAT_TO_FLAGS(category), filename, lineNumber, address)
#endif
@@ -0,0 +1,53 @@
/*
* 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
#ifdef AZ_PROFILE_TELEMETRY
#include <AzCore/base.h>
#include <AzCore/Debug/Profiler.h>
#include <AzCore/Debug/ProfilerBus.h>
#include <AzCore/EBus/EBus.h>
struct tm_api;
namespace RADTelemetry
{
class ProfileTelemetryRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
virtual ~ProfileTelemetryRequests() = default;
virtual void ToggleEnabled() = 0;
virtual void SetAddress(const char* address, AZ::u16 port) = 0;
virtual void SetCaptureMask(AZ::Debug::ProfileCategoryPrimitiveType mask) = 0;
virtual void SetFrameAdvanceType(AZ::Debug::ProfileFrameAdvanceType type) = 0;
virtual AZ::Debug::ProfileCategoryPrimitiveType GetCaptureMask() = 0;
virtual AZ::Debug::ProfileCategoryPrimitiveType GetDefaultCaptureMask() = 0;
virtual tm_api* GetApiInstance() = 0;
};
using ProfileTelemetryRequestBus = AZ::EBus<ProfileTelemetryRequests>;
}
#endif
@@ -0,0 +1,60 @@
/*
* 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 <AzCore/Debug/StackTracer.h>
namespace AZ
{
namespace Debug
{
unsigned int StackRecorder::Record(StackFrame*, unsigned int, unsigned int, void*)
{
return false;
}
void SymbolStorage::LoadModuleData(const void*, unsigned int)
{}
void SymbolStorage::StoreModuleInfoData(void*, unsigned int)
{}
unsigned int SymbolStorage::GetNumLoadedModules()
{
return 0;
}
const SymbolStorage::ModuleInfo* SymbolStorage::GetModuleInfo(unsigned int)
{
return 0;
}
void SymbolStorage::RegisterModuleListeners()
{
}
void SymbolStorage::UnregisterModuleListeners()
{
}
void SymbolStorage::SetMapFilename(const char*)
{
}
const char* SymbolStorage::GetMapFilename()
{
return 0;
}
void SymbolStorage::DecodeFrames(const StackFrame*, unsigned int, StackLine*)
{}
}
}
@@ -0,0 +1,112 @@
/*
* 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/IPC/SharedMemory_Common.h>
namespace AZ
{
class SharedMemory_Unimplemented : public SharedMemory_Common
{
private:
static void Unimplemented()
{
AZ_Assert(false, "SharedMemory not implemented on this platform!");
}
protected:
static int GetLastError()
{
Unimplemented();
return 0;
}
bool IsReady() const
{
Unimplemented();
return false;
}
bool IsMapHandleValid() const
{
Unimplemented();
return false;
}
CreateResult Create(const char* name, unsigned int size, bool openIfCreated)
{
AZ_UNUSED(name);
AZ_UNUSED(size);
AZ_UNUSED(openIfCreated);
Unimplemented();
return CreateResult::CreateFailed;
}
bool Open(const char* name)
{
AZ_UNUSED(name);
Unimplemented();
return false;
}
void Close()
{
Unimplemented();
}
bool Map(AccessMode mode, unsigned int size)
{
AZ_UNUSED(mode);
AZ_UNUSED(size);
Unimplemented();
return false;
}
bool UnMap()
{
Unimplemented();
return false;
}
void lock()
{
Unimplemented();
}
bool try_lock()
{
Unimplemented();
return false;
}
void unlock()
{
Unimplemented();
}
bool IsLockAbandoned()
{
Unimplemented();
return false;
}
bool IsWaitFailed() const
{
Unimplemented();
return false;
}
void* m_globalMutex = nullptr;
};
using SharedMemory_Platform = SharedMemory_Unimplemented;
}
@@ -0,0 +1,65 @@
/*
* 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 <AzCore/Memory/OverrunDetectionAllocator.h>
namespace AZ
{
namespace Internal
{
static const int ODS_PAGE_SIZE = 4096;
static const int ODS_PAGE_SHIFT = 12;
static const int ODS_PAGES_PER_ALLOCATION = 1;
static const int ODS_PAGES_PER_ALLOCATION_SHIFT = 0;
static const int ODS_ALLOCATION_SIZE = ODS_PAGE_SIZE * ODS_PAGES_PER_ALLOCATION;
class UnimplementedOverrunDetectionSchema : public OverrunDetectionSchema::PlatformAllocator
{
public:
virtual SystemInformation GetSystemInformation() override
{
SystemInformation result;
return result;
}
virtual void* ReserveBytes(size_t amount) override
{
AZ_UNUSED(amount);
AZ_Assert(false, "No implementation of OverrunDetectionSchema for this platform");
return nullptr;
}
virtual void ReleaseReservedBytes(void* base) override
{
AZ_UNUSED(base);
AZ_Assert(false, "No implementation of OverrunDetectionSchema for this platform");
}
virtual void* CommitBytes(void* base, size_t amount) override
{
AZ_UNUSED(base);
AZ_UNUSED(amount);
AZ_Assert(false, "No implementation of OverrunDetectionSchema for this platform");
return nullptr;
}
virtual void DecommitBytes(void* base, size_t amount) override
{
AZ_UNUSED(base);
AZ_UNUSED(amount);
AZ_Assert(false, "No implementation of OverrunDetectionSchema for this platform");
}
};
using PlatformOverrunDetectionSchema = UnimplementedOverrunDetectionSchema;
}
}
@@ -0,0 +1,23 @@
/*
* 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 <AzCore/Module/DynamicModuleHandle.h>
namespace AZ
{
AZStd::unique_ptr<DynamicModuleHandle> DynamicModuleHandle::Create(const char*)
{
AZ_Assert(false, "Dynamic modules are not supported on this platform");
return nullptr;
}
} // namespace AZ
@@ -0,0 +1,27 @@
/*
* 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 <AzCore/NativeUI/NativeUISystemComponent.h>
namespace AZ
{
namespace NativeUI
{
AZStd::string NativeUISystemComponent::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector<AZStd::string>& options) const
{
AZ_UNUSED(title);
AZ_UNUSED(message);
AZ_UNUSED(options);
return "";
}
}
}
@@ -0,0 +1,13 @@
/*
* 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
@@ -0,0 +1,137 @@
/*
* 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 <AzCore/Debug/StackTracer.h>
#include <AzCore/Math/MathUtils.h>
#include <AzCore/std/parallel/config.h>
#include <cxxabi.h>
#include <inttypes.h>
#include <signal.h>
#include <cstdio>
#include <cstdlib>
#define UNW_LOCAL_ONLY
#include <libunwind.h>
#include <AzCore/std/parallel/mutex.h>
using namespace AZ;
using namespace AZ::Debug;
AZStd::mutex g_mutex; /// All dbg help functions are single threaded, so we need to control the access.
void SymbolStorage::RegisterModuleListeners()
{
}
void SymbolStorage::UnregisterModuleListeners()
{
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Stack Recorder
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//=========================================================================
// Record
// [7/29/2009]
//=========================================================================
unsigned int
StackRecorder::Record(StackFrame* frames, unsigned int maxNumOfFrames, unsigned int suppressCount /* = 0 */, void* nativeThread /*= NULL*/)
{
int count = 0;
unw_cursor_t cursor;
unw_context_t context;
// Initialize cursor to current frame for local unwinding.
unw_getcontext(&context);
unw_init_local(&cursor, &context);
int skip = static_cast<int>((suppressCount == 0) ? 1 : suppressCount); // Skip at least this function
while ((unw_step(&cursor) > 0) && (count < maxNumOfFrames))
{
unw_word_t offset, pc;
unw_get_reg(&cursor, UNW_REG_IP, &pc);
if (pc == 0)
{
break;
}
else if (--skip < 0)
{
frames[count++].m_programCounter = pc;
}
}
// Clear reset of the buffer
for (int i = count; i < maxNumOfFrames; ++i)
{
frames[i].m_programCounter = 0;
}
return count;
}
void
SymbolStorage::DecodeFrames(const StackFrame* frames, unsigned int numFrames, StackLine* textLines)
{
int count = 0;
unw_cursor_t cursor;
unw_context_t context;
g_mutex.lock();
// Initialize cursor to current frame for local unwinding.
unw_getcontext(&context);
unw_init_local(&cursor, &context);
for (unsigned int i = 0; i < numFrames; ++i)
{
if (frames[i].IsValid())
{
unw_set_reg(&cursor, UNW_REG_IP, frames[i].m_programCounter);
SymbolStorage::StackLine& textLine = textLines[count++];
textLine[0] = 0;
unw_word_t offset;
char sym[1024] = { '\0' };
if (unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0)
{
char* nameptr = sym;
int status = 0;
char* demangled = abi::__cxa_demangle(sym, nullptr, nullptr, &status);
if (status == 0)
{
nameptr = demangled;
}
::std::snprintf(textLine, AZ_ARRAY_SIZE(textLine), "%s (+0x%" PRIxPTR ") [0x%" PRIxPTR "]",
nameptr, (uintptr_t)offset, frames[i].m_programCounter);
::std::free(demangled);
}
else
{
::std::snprintf(textLine, AZ_ARRAY_SIZE(textLine), "%s", " -- error: unable to obtain symbol name for this frame");
}
}
}
// Empty rest of the buffer so we don't print junk
for (unsigned int i = count; i < numFrames; ++i)
{
textLines[i][0] = '\0';
}
g_mutex.unlock();
}
@@ -0,0 +1,82 @@
/*
* 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 <AzCore/IO/SystemFile.h>
#include <AzCore/std/string/string_view.h>
#include <ctype.h>
#include <signal.h>
#include <unistd.h>
namespace AZ
{
namespace Debug
{
namespace Platform
{
#if defined(AZ_ENABLE_DEBUG_TOOLS)
bool performDebuggerDetection()
{
AZ::IO::SystemFile processStatusFile;
if (!processStatusFile.Open("/proc/self/status", AZ::IO::SystemFile::SF_OPEN_READ_ONLY))
{
return false;
}
char buffer[4096];
AZ::IO::SystemFile::SizeType numRead = processStatusFile.Read(sizeof(buffer), buffer);
const AZStd::string_view processStatusView(buffer, buffer + numRead);
constexpr AZStd::string_view tracerPidString = "TracerPid:";
const size_t tracerPidOffset = processStatusView.find(tracerPidString);
if (tracerPidOffset == AZStd::string_view::npos)
{
return false;
}
for (size_t i = tracerPidOffset; i < numRead; ++i)
{
if (!::isspace(processStatusView[i]))
{
return processStatusView[i] != '0';
}
}
return false;
}
bool IsDebuggerPresent()
{
static bool s_detectionPerformed = false;
static bool s_debuggerDetected = false;
if (!s_detectionPerformed)
{
s_debuggerDetected = performDebuggerDetection();
s_detectionPerformed = true;
}
return s_debuggerDetected;
}
void HandleExceptions(bool)
{}
void DebugBreak()
{
raise(SIGINT);
}
#endif // AZ_ENABLE_DEBUG_TOOLS
void Terminate(int exitCode)
{
_exit(exitCode);
}
}
}
}
@@ -0,0 +1,93 @@
/*
* 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 "SystemFileUtils_UnixLike.h"
namespace AZ
{
namespace IO
{
namespace Internal
{
bool FormatAndPeelOffWildCardExtension(const char* sourcePath, char* filePath, size_t filePathSize, char* extensionPath, size_t extensionSize, bool keepWildcard)
{
if (sourcePath == nullptr || filePath == nullptr || extensionPath == nullptr || filePathSize == 0 || extensionSize == 0)
{
AZ_Error("AZ::IO::Internal", false, "FormatAndPeelOffWildCardExtension: One or more parameters was invalid.");
return false;
}
const char* pSrcPath = sourcePath;
char* pDestPath = filePath;
size_t destinationSize = filePathSize;
unsigned numFileChars = 0;
unsigned numExtensionChars = 0;
unsigned* pNumDestChars = &numFileChars;
bool bIsWildcardExtension = false;
while (*pSrcPath)
{
char srcChar = *pSrcPath++;
// Skip '*' and '.'
if ((!bIsWildcardExtension && srcChar != '*') || (bIsWildcardExtension && srcChar != '.' && (keepWildcard || srcChar != '*')))
{
unsigned numChars = *pNumDestChars;
pDestPath[numChars++] = srcChar;
*pNumDestChars = numChars;
--destinationSize;
if (destinationSize == 0)
{
AZ_Error(
"AZ::IO::Internal",
false,
"Error splitting sourcePath '%s' into filePath and extension, %s length is larger than storage size %d.",
sourcePath,
bIsWildcardExtension ? "extensionPath" : "filePath",
bIsWildcardExtension ? extensionSize : filePathSize);
return false;
}
}
// Wild-card extension is separate
if (srcChar == '*')
{
bIsWildcardExtension = true;
pDestPath = extensionPath;
destinationSize = extensionSize;
pNumDestChars = &numExtensionChars;
if (keepWildcard)
{
unsigned numChars = *pNumDestChars;
pDestPath[numChars++] = srcChar;
*pNumDestChars = numChars;
--destinationSize;
if (destinationSize == 0)
{
AZ_Error(
"AZ::IO::Internal",
false,
"Error splitting sourcePath '%s' into filePath and extension, extensionPath length is larger than storage size %d.",
sourcePath,
extensionSize);
return false;
}
}
}
}
// Close strings
filePath[numFileChars] = 0;
extensionPath[numExtensionChars] = 0;
return true;
}
}
}
}
@@ -0,0 +1,29 @@
/*
* 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/base.h>
/**
* This file is to be included from UnixLike SystemFile implementations only. It should NOT be included by the user.
*/
namespace AZ
{
namespace IO
{
namespace Internal
{
bool FormatAndPeelOffWildCardExtension(const char* sourcePath, char* filePath, size_t filePathSize, char* extensionPath, size_t extensionSize, bool keepWildcard = false);
}
}
}
@@ -0,0 +1,237 @@
/*
* 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 <AzCore/IO/SystemFile.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/IO/FileIOEventBus.h>
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/PlatformIncl.h>
#include <AzCore/Utils/Utils.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <dirent.h>
namespace AZ::IO
{
const char* SystemFile::GetNullFilename()
{
return "/dev/null";
}
namespace UnixLikePlatformUtil
{
// Platform specific helpers
bool CanCreateDirRecursive(char* dirPath);
}
namespace
{
//=========================================================================
// Internal utility to create a folder hierarchy recursively without
// any additional string copies.
// If this function fails (returns false), the error will be available
// via errno on Unix platforms
//=========================================================================
bool CreateDirRecursive(char* dirPath)
{
if (!UnixLikePlatformUtil::CanCreateDirRecursive(dirPath))
{
// Our current platform has told us we have failed
return false;
}
int result = mkdir(dirPath, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
if (result == 0)
{
return true; // Created without error
}
else if (result == -1)
{
// If result == -1, the error is stored in errno
// http://pubs.opengroup.org/onlinepubs/007908799/xsh/mkdir.html
result = errno;
}
if (result == ENOTDIR || result == ENOENT)
{
// try to create our parent hierarchy
for (size_t i = strlen(dirPath); i > 0; --i)
{
if (dirPath[i] == '/' || dirPath[i] == '\\')
{
char delimiter = dirPath[i];
dirPath[i] = 0; // null-terminate at the previous slash
bool ret = CreateDirRecursive(dirPath);
dirPath[i] = delimiter; // restore slash
if (ret)
{
// now that our parent is created, try to create again
return mkdir(dirPath, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0;
}
return false;
}
}
// if we reach here then there was no parent folder to create, so we failed for other reasons
}
else if (result == EEXIST)
{
struct stat s;
if (stat(dirPath, &s) == 0)
{
return s.st_mode & S_IFDIR;
}
}
return false;
}
}
namespace Platform
{
AZ::u64 ModificationTime(const char* fileName)
{
struct stat statResult;
if (stat(fileName, &statResult) != 0)
{
return 0;
}
return aznumeric_cast<AZ::u64>(statResult.st_mtime);
}
SystemFile::SizeType Length(const char* fileName)
{
SizeType len = 0;
SystemFile f;
if (f.Open(fileName, SystemFile::SF_OPEN_READ_ONLY))
{
len = f.Length();
f.Close();
}
return len;
}
bool Delete(const char* fileName)
{
int result = remove(fileName);
if (result != 0)
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, fileName, result);
return false;
}
return true;
}
bool Rename(const char* sourceFileName, const char* targetFileName, bool overwrite)
{
int result = rename(sourceFileName, targetFileName);
if (result)
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, sourceFileName, result);
return false;
}
return true;
}
#if !(AZ_TRAIT_SYSTEMFILE_UNIX_LIKE_PLATFORM_IS_WRITEABLE_DEFINED_ELSEWHERE)
bool IsWritable(const char* sourceFileName)
{
return (access(sourceFileName, W_OK) == 0);
}
#endif // !(AZ_TRAIT_SYSTEMFILE_UNIX_LIKE_PLATFORM_IS_WRITEABLE_DEFINED_ELSEWHERE)
bool SetWritable(const char* sourceFileName, bool writable)
{
struct stat s;
if (stat(sourceFileName, &s) == 0)
{
int permissions = (s.st_mode & S_IRWXU) | (s.st_mode & S_IRWXO) | (s.st_mode & S_IRWXG);
if (writable)
{
if (s.st_mode & S_IWUSR)
{
return true;
}
return chmod(sourceFileName, permissions | S_IWUSR) == 0;
}
else
{
if (s.st_mode & S_IRWXG)
{
return chmod(sourceFileName, permissions & ~(S_IWUSR)) == 0;
}
else
{
// file is already writeable
return true;
}
}
}
return false;
}
bool CreateDir(const char* dirName)
{
if (dirName)
{
char dirPath[AZ_MAX_PATH_LEN];
if (strlen(dirName) > AZ_MAX_PATH_LEN)
{
return false;
}
azstrcpy(dirPath, AZ_MAX_PATH_LEN, dirName);
bool success = CreateDirRecursive(dirPath);
if (!success)
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, dirName, errno);
}
return success;
}
return false;
}
bool DeleteDir(const char* dirName)
{
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::DeleteDir(util) - %s", dirName);
if (dirName)
{
return rmdir(dirName) == 0;
}
return false;
}
} // namespace AZ::IO::Platform
namespace PosixInternal
{
int Dup(int fileDescriptor)
{
return dup(fileDescriptor);
}
int Dup2(int fileDescriptorSource, int fileDescriptorDestination)
{
return dup2(fileDescriptorSource, fileDescriptorDestination);
}
} // namespace AZ::IO::PosixInternal
} // namespace AZ::IO
@@ -0,0 +1,108 @@
/*
* 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 <fcntl.h>
#include <unistd.h>
namespace AZ
{
namespace IO
{
namespace Internal
{
using SizeType = AZ::u64;
using FileHandleType = int;
}
namespace PosixInternal
{
enum class OpenFlags : int
{
Append = O_APPEND, // Moves the file pointer to the end of the file before every write operation.
Create = O_CREAT, // Creates a file and opens it for writing. Has no effect if the file specified by filename exists. PermissionMode is required.
#ifdef O_TMPFILE
Temporary = O_TMPFILE, // Applies only when used with CREAT. Creates a file as temporary; the file is deleted when the last file descriptor is closed. PermissionMode equired when CREAT is specified.
#else
Temporary = 0, // (Not applicable for this platform) Applies only when used with CREAT. Creates a file as temporary; the file is deleted when the last file descriptor is closed. PermissionMode equired when CREAT is specified.
#endif
Exclusive = O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
Truncate = O_TRUNC, // Opens a file and truncates it to zero length; the file must have write permission. Cannot be specified with RDONLY.
// Note: The TRUNC flag destroys the contents of the specified file.
ReadOnly = O_RDONLY, // Opens a file for reading only. Cannot be specified with RDWR or WRONLY.
WriteOnly = O_WRONLY, // Opens a file for writing only. Cannot be specified with RDONLY or RDWR.
ReadWrite = O_RDWR, // Opens a file for both reading and writing. Cannot be specified with RDONLY or WRONLY.
// Windows-specific
NoInherit = 0, // (Not applicable in unix) Prevents creation of a shared file descriptor.
Random = 0, // (Not applicable in unix) Specifies that caching is optimized for, but not restricted to, random access from disk.
Sequential = 0, // (Not applicable in unix) Specifies that caching is optimized for, but not restricted to, sequential access from disk.
Binary = 0, // (Not applicable in unix) Opens the file in binary(untranslated) mode. (See fopen for a description of binary mode.)
Text = 0, // (Not applicable in unix) Opens a file in text(translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.)
U16Text = 0, // (Not applicable in unix) Opens a file in Unicode UTF-16 mode.
U8Text = 0, // (Not applicable in unix) Opens a file in Unicode UTF-8 mode.
WText = 0, // (Not applicable in unix) Opens a file in Unicode mode.
// Unix-specific
Async = O_ASYNC, // Enable signal-driven I/O: generate a signal (SIGIO by default, but this can be changed via fcntl(2)) when input or output becomes possible on this file descriptor. This feature is available only for terminals, pseudoterminals, sockets, and (since Linux 2.6) pipes and FIFOs.
Direct = O_DIRECT, // Try to minimize cache effects of the I/O to and from this file. In general this will degrade performance, but it is useful in special situations, such as when applications do their own caching.
Directory = O_DIRECTORY, // If pathname is not a directory, cause the open to fail.
NoFollow = O_NOFOLLOW, // If the trailing component (i.e., basename) of pathname is a symbolic link, then the open fails, with the error ELOOP. Symbolic links in earlier components of the pathname will still be followed.
#ifdef O_NOATIME
NoAccessTime = O_NOATIME, // Do not update the file last access time.
#else
NoAccessTime = 0, // (Not applicable for this platform) Do not update the file last access time.
#endif
#ifdef O_PATH
Path = O_PATH, // Obtain a file descriptor that can be used for two purposes: to indicate a location in the filesystem tree and to perform operations that act purely at the file descriptor level.
#else
Path = 0, // (Not applicable for this platform) Obtain a file descriptor that can be used for two purposes: to indicate a location in the filesystem tree and to perform operations that act purely at the file descriptor level.
#endif
};
AZ_DEFINE_ENUM_BITWISE_OPERATORS(OpenFlags);
enum class PermissionModeFlags : int
{
None = 0,
Read = S_IRUSR,
Write = S_IWUSR
};
AZ_DEFINE_ENUM_BITWISE_OPERATORS(PermissionModeFlags);
inline int Open(const char* const fileName, OpenFlags openFlags,
PermissionModeFlags newFilePermissions = PermissionModeFlags::None)
{
return open(fileName, static_cast<int>(openFlags), static_cast<int>(newFilePermissions));
}
inline int Close(int fileDescriptor)
{
return close(fileDescriptor);
}
inline int Read(int fileDescriptor, void* data, size_t size)
{
return read(fileDescriptor, data, size);
}
inline int Write(int fileDescriptor, const void* data, size_t size)
{
return write(fileDescriptor, data, size);
}
int Dup(int fileDescriptor);
int Dup2(int fileDescriptorSource, int fileDescriptorDestination);
} // namespace AZ::IO::PosixInternal
} // namespace AZ::IO
} // namespace AZ
@@ -0,0 +1,48 @@
/*
* 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 "Random_UnixLike.h"
#include <AzCore/PlatformIncl.h>
#include <AzCore/Debug/Trace.h>
namespace AZ
{
BetterPseudoRandom_UnixLike::BetterPseudoRandom_UnixLike()
{
m_generatorHandle = fopen("/dev/urandom", "r");
}
BetterPseudoRandom_UnixLike::~BetterPseudoRandom_UnixLike()
{
if (m_generatorHandle)
{
fclose(m_generatorHandle);
}
}
bool BetterPseudoRandom_UnixLike::GetRandom(void* data, size_t dataSize)
{
if (!m_generatorHandle)
{
return false;
}
if (fread(data, 1, dataSize, m_generatorHandle) != dataSize)
{
AZ_TracePrintf("System", "Failed to read %d bytes from /dev/urandom!", dataSize);
fclose(m_generatorHandle);
m_generatorHandle = nullptr;
return false;
}
return true;
}
}
@@ -0,0 +1,41 @@
/*
* 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 <stdio.h>
namespace AZ
{
/**
* Provides a better yet more computationally costly random implementation.
* To be used in less frequent scenarios, i.e. to get a good seed.
*/
class BetterPseudoRandom_UnixLike
{
public:
BetterPseudoRandom_UnixLike();
~BetterPseudoRandom_UnixLike();
/// Fills a buffer with random data, if true is returned. Otherwise the random generator fails to generate random numbers.
bool GetRandom(void* data, size_t dataSize);
/// Template helper for value types \ref GetRandom
template<class T>
bool GetRandom(T& value) { return GetRandom(&value, sizeof(T)); }
private:
FILE* m_generatorHandle;
};
using BetterPseudoRandom_Platform = BetterPseudoRandom_UnixLike;
}
@@ -0,0 +1,17 @@
/*
* 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 <malloc.h>
# define AZ_OS_MALLOC(byteSize, alignment) ::memalign(alignment, byteSize)
# define AZ_OS_FREE(pointer) ::free(pointer)
@@ -0,0 +1,143 @@
/*
* 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 <AzCore/Module/DynamicModuleHandle.h>
#include <AzCore/IO/SystemFile.h> // for AZ_MAX_PATH_LEN
#include <AzCore/Memory/OSAllocator.h>
#include <dlfcn.h>
#include <libgen.h>
namespace AZ
{
namespace Platform
{
void GetModulePath(AZ::OSString& path);
void* OpenModule(const AZ::OSString& fileName, bool& alreadyOpen);
void ConstructModuleFullFileName(const AZ::OSString& path, const AZ::OSString& fileName, AZ::OSString& fullPath);
}
class DynamicModuleHandleUnixLike
: public DynamicModuleHandle
{
public:
AZ_CLASS_ALLOCATOR(DynamicModuleHandleUnixLike, OSAllocator, 0)
DynamicModuleHandleUnixLike(const char* fullFileName)
: DynamicModuleHandle(fullFileName)
, m_handle(nullptr)
{
AZ::OSString path;
AZ::OSString fileName;
AZ::OSString fullPath = "";
AZ::OSString::size_type finalSlash = m_fileName.find_last_of("/");
if (finalSlash != AZ::OSString::npos)
{
// Path up to and including final slash
path = m_fileName.substr(0, finalSlash + 1);
// Everything after the final slash
// If m_fileName ends in /, the end result is path/lib.dylib, which just fails to load.
fileName = m_fileName.substr(finalSlash + 1);
}
else
{
// If no slash found, assume empty path, only file name
path = "";
Platform::GetModulePath(path);
fileName = m_fileName;
}
if (fileName.substr(0, 3) != AZ_TRAIT_OS_DYNAMIC_LIBRARY_PREFIX)
{
fileName = AZ_TRAIT_OS_DYNAMIC_LIBRARY_PREFIX + fileName;
}
size_t extensionLen = strlen(AZ_TRAIT_OS_DYNAMIC_LIBRARY_EXTENSION);
if (fileName.substr(fileName.length() - extensionLen, extensionLen) != AZ_TRAIT_OS_DYNAMIC_LIBRARY_EXTENSION)
{
fileName = fileName + AZ_TRAIT_OS_DYNAMIC_LIBRARY_EXTENSION;
}
Platform::ConstructModuleFullFileName(path, fileName, fullPath);
m_fileName = fullPath;
}
~DynamicModuleHandleUnixLike() override
{
Unload();
}
LoadStatus LoadModule() override
{
AZ::Debug::Trace::Printf("Module", "Attempting to load module:%s\n", m_fileName.c_str());
bool alreadyOpen = false;
m_handle = Platform::OpenModule(m_fileName, alreadyOpen);
if(m_handle)
{
if (alreadyOpen)
{
AZ::Debug::Trace::Printf("Module", "Success! System already had it opened.\n");
// We want to return LoadSuccess and not AlreadyLoaded
// because the system may have already loaded the DLL (because
// it is a dependency of another library we have loaded) but
// we have not run our initialization routine on it. Returning
// AlreadyLoaded stops us from running the initialization
// routine that results in a cascade of failures and potential
// crash.
return LoadStatus::LoadSuccess;
}
else
{
AZ::Debug::Trace::Printf("Module", "Success!\n");
return LoadStatus::LoadSuccess;
}
}
else
{
AZ::Debug::Trace::Printf("Module", "Failed with error:\n%s\n", dlerror());
return LoadStatus::LoadFailure;
}
}
bool UnloadModule() override
{
bool result = false;
if (m_handle)
{
result = dlclose(m_handle) == 0 ? true : false;
m_handle = 0;
}
return result;
}
bool IsLoaded() const override
{
return m_handle ? true : false;
}
void* GetFunctionAddress(const char* functionName) const override
{
return dlsym(m_handle, functionName);
}
void* m_handle;
};
// Implement the module creation function
AZStd::unique_ptr<DynamicModuleHandle> DynamicModuleHandle::Create(const char* fullFileName)
{
return AZStd::unique_ptr<DynamicModuleHandle>(aznew DynamicModuleHandleUnixLike(fullFileName));
}
} // namespace AZ
@@ -0,0 +1,15 @@
/*
* 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 <unistd.h>
@@ -0,0 +1,48 @@
/*
* 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 <AzCore/Platform.h>
#include <AzCore/PlatformIncl.h>
#include <AzCore/std/time.h>
#include <sys/types.h>
#include <unistd.h>
namespace AZ
{
namespace Platform
{
ProcessId GetCurrentProcessId()
{
return static_cast<ProcessId>(::getpid());
}
MachineId GetLocalMachineId()
{
if (s_machineId == 0)
{
// In specialized server situations, SetLocalMachineId() should be used, with whatever criteria works best in that environment
// A proper implementation for each supported system will be needed instead of this temporary measure to avoid collision in the small scale.
// On a larger scale, the odds of two people getting in here at the same millisecond will go up drastically, and we'll have the same issue again,
// though far less reproducible, for duplicated EntityId's across a network.
s_machineId = static_cast<AZ::u32>(AZStd::GetTimeUTCMilliSecond() & 0xffffffff);
if (s_machineId == 0)
{
s_machineId = 1;
AZ_Warning("System", false, "0 machine ID is reserved!");
}
}
return s_machineId;
}
} // namespace Platform
}
@@ -0,0 +1,386 @@
/*
* 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 <AzCore/Socket/AzSocket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define INVALID_SOCKET (-1)
#define closesocket(_s) close(_s)
#define GetInternalSocketError errno
typedef int SOCKET;
typedef AZ::u32 AZSOCKLEN;
namespace AZ
{
namespace AzSock
{
AZ::s32 TranslateOSError(AZ::s32 oserror)
{
AZ::s32 error;
#define TRANSLATE(_from, _to) case (_from): error = static_cast<AZ::s32>(_to); break;
switch (oserror)
{
TRANSLATE(0, AzSockError::eASE_NO_ERROR);
TRANSLATE(EACCES, AzSockError::eASE_EACCES);
TRANSLATE(EADDRINUSE, AzSockError::eASE_EADDRINUSE);
TRANSLATE(EADDRNOTAVAIL, AzSockError::eASE_EADDRNOTAVAIL);
TRANSLATE(EAFNOSUPPORT, AzSockError::eASE_EAFNOSUPPORT);
TRANSLATE(EALREADY, AzSockError::eASE_EALREADY);
TRANSLATE(EBADF, AzSockError::eASE_EBADF);
TRANSLATE(ECONNABORTED, AzSockError::eASE_ECONNABORTED);
TRANSLATE(ECONNREFUSED, AzSockError::eASE_ECONNREFUSED);
TRANSLATE(ECONNRESET, AzSockError::eASE_ECONNRESET);
TRANSLATE(EFAULT, AzSockError::eASE_EFAULT);
TRANSLATE(EHOSTDOWN, AzSockError::eASE_EHOSTDOWN);
TRANSLATE(EINPROGRESS, AzSockError::eASE_EINPROGRESS);
TRANSLATE(EINTR, AzSockError::eASE_EINTR);
TRANSLATE(EINVAL, AzSockError::eASE_EINVAL);
TRANSLATE(EISCONN, AzSockError::eASE_EISCONN);
TRANSLATE(EMFILE, AzSockError::eASE_EMFILE);
TRANSLATE(EMSGSIZE, AzSockError::eASE_EMSGSIZE);
TRANSLATE(ENETUNREACH, AzSockError::eASE_ENETUNREACH);
TRANSLATE(ENOBUFS, AzSockError::eASE_ENOBUFS);
TRANSLATE(ENOPROTOOPT, AzSockError::eASE_ENOPROTOOPT);
TRANSLATE(ENOTCONN, AzSockError::eASE_ENOTCONN);
TRANSLATE(EOPNOTSUPP, AzSockError::eASE_EOPNOTSUPP);
TRANSLATE(EPROTONOSUPPORT, AzSockError::eASE_EAFNOSUPPORT);
TRANSLATE(ETIMEDOUT, AzSockError::eASE_ETIMEDOUT);
TRANSLATE(ETOOMANYREFS, AzSockError::eASE_ETOOMANYREFS);
TRANSLATE(EWOULDBLOCK, AzSockError::eASE_EWOULDBLOCK);
default:
AZ_TracePrintf("AzSock", "AzSocket could not translate OS error code %x, treating as miscellaneous.\n", oserror);
error = static_cast<AZ::s32>(AzSockError::eASE_MISC_ERROR);
break;
}
#undef TRANSLATE
return error;
}
AZ::s32 TranslateSocketOption(AzSocketOption opt)
{
AZ::s32 value;
#define TRANSLATE(_from, _to) case (_from): value = (_to); break;
switch (opt)
{
TRANSLATE(AzSocketOption::REUSEADDR, SO_REUSEADDR);
TRANSLATE(AzSocketOption::KEEPALIVE, SO_KEEPALIVE);
TRANSLATE(AzSocketOption::LINGER, SO_LINGER);
default:
AZ_TracePrintf("AzSock", "AzSocket option %x not yet supported", opt);
value = 0;
break;
}
#undef TRANSLATE
return value;
}
AZSOCKET HandleInvalidSocket(SOCKET sock)
{
AZSOCKET azsock = static_cast<AZSOCKET>(sock);
if (sock == INVALID_SOCKET)
{
azsock = TranslateOSError(GetInternalSocketError);
}
return azsock;
}
AZ::s32 HandleSocketError(AZ::s32 socketError)
{
if (socketError == SOCKET_ERROR)
{
socketError = TranslateOSError(GetInternalSocketError);
}
return socketError;
}
const char* GetStringForError(AZ::s32 errorNumber)
{
AzSockError errorCode = AzSockError(errorNumber);
#define CASE_RETSTRING(errorEnum) case errorEnum: { return #errorEnum; }
switch (errorCode)
{
CASE_RETSTRING(AzSockError::eASE_NO_ERROR);
CASE_RETSTRING(AzSockError::eASE_SOCKET_INVALID);
CASE_RETSTRING(AzSockError::eASE_EACCES);
CASE_RETSTRING(AzSockError::eASE_EADDRINUSE);
CASE_RETSTRING(AzSockError::eASE_EADDRNOTAVAIL);
CASE_RETSTRING(AzSockError::eASE_EAFNOSUPPORT);
CASE_RETSTRING(AzSockError::eASE_EALREADY);
CASE_RETSTRING(AzSockError::eASE_EBADF);
CASE_RETSTRING(AzSockError::eASE_ECONNABORTED);
CASE_RETSTRING(AzSockError::eASE_ECONNREFUSED);
CASE_RETSTRING(AzSockError::eASE_ECONNRESET);
CASE_RETSTRING(AzSockError::eASE_EFAULT);
CASE_RETSTRING(AzSockError::eASE_EHOSTDOWN);
CASE_RETSTRING(AzSockError::eASE_EINPROGRESS);
CASE_RETSTRING(AzSockError::eASE_EINTR);
CASE_RETSTRING(AzSockError::eASE_EINVAL);
CASE_RETSTRING(AzSockError::eASE_EISCONN);
CASE_RETSTRING(AzSockError::eASE_EMFILE);
CASE_RETSTRING(AzSockError::eASE_EMSGSIZE);
CASE_RETSTRING(AzSockError::eASE_ENETUNREACH);
CASE_RETSTRING(AzSockError::eASE_ENOBUFS);
CASE_RETSTRING(AzSockError::eASE_ENOPROTOOPT);
CASE_RETSTRING(AzSockError::eASE_ENOTCONN);
CASE_RETSTRING(AzSockError::eASE_ENOTINITIALISED);
CASE_RETSTRING(AzSockError::eASE_EOPNOTSUPP);
CASE_RETSTRING(AzSockError::eASE_EPIPE);
CASE_RETSTRING(AzSockError::eASE_EPROTONOSUPPORT);
CASE_RETSTRING(AzSockError::eASE_ETIMEDOUT);
CASE_RETSTRING(AzSockError::eASE_ETOOMANYREFS);
CASE_RETSTRING(AzSockError::eASE_EWOULDBLOCK);
CASE_RETSTRING(AzSockError::eASE_EWOULDBLOCK_CONN);
CASE_RETSTRING(AzSockError::eASE_MISC_ERROR);
}
#undef CASE_RETSTRING
return "(invalid)";
}
AZ::u32 HostToNetLong(AZ::u32 hstLong)
{
return htonl(hstLong);
}
AZ::u32 NetToHostLong(AZ::u32 netLong)
{
return ntohl(netLong);
}
AZ::u16 HostToNetShort(AZ::u16 hstShort)
{
return htons(hstShort);
}
AZ::u16 NetToHostShort(AZ::u16 netShort)
{
return ntohs(netShort);
}
AZ::s32 GetHostName(AZStd::string& hostname)
{
AZ::s32 result = 0;
hostname.clear();
char name[256];
result = HandleSocketError(gethostname(name, AZ_ARRAY_SIZE(name)));
if (result == static_cast<AZ::s32>(AzSockError::eASE_NO_ERROR))
{
hostname = name;
}
return result;
}
AZSOCKET Socket()
{
return Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
}
AZSOCKET Socket(AZ::s32 af, AZ::s32 type, AZ::s32 protocol)
{
return HandleInvalidSocket(socket(af, type, protocol));
}
AZ::s32 SetSockOpt(AZSOCKET sock, AZ::s32 level, AZ::s32 optname, const char* optval, AZ::s32 optlen)
{
AZSOCKLEN length(optlen);
return HandleSocketError(setsockopt(sock, level, optname, optval, length));
}
AZ::s32 SetSocketOption(AZSOCKET sock, AzSocketOption opt, bool enable)
{
AZ::u32 val = enable ? 1 : 0;
return SetSockOpt(sock, SOL_SOCKET, TranslateSocketOption(opt), reinterpret_cast<const char*>(&val), sizeof(val));
}
AZ::s32 EnableTCPNoDelay(AZSOCKET sock, bool enable)
{
AZ::u32 val = enable ? 1 : 0;
return SetSockOpt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<const char*>(&val), sizeof(val));
}
AZ::s32 SetSocketBlockingMode(AZSOCKET sock, bool blocking)
{
AZ::s32 flags = ::fcntl(sock, F_GETFL);
flags &= ~O_NONBLOCK;
flags |= (blocking ? 0 : O_NONBLOCK);
return ::fcntl(sock, F_SETFL, flags);
}
AZ::s32 CloseSocket(AZSOCKET sock)
{
return HandleSocketError(closesocket(sock));
}
AZ::s32 Shutdown(AZSOCKET sock, AZ::s32 how)
{
return HandleSocketError(shutdown(sock, how));
}
AZ::s32 GetSockName(AZSOCKET sock, AzSocketAddress& addr)
{
AZSOCKADDR sAddr;
AZSOCKLEN sAddrLen = sizeof(AZSOCKADDR);
memset(&sAddr, 0, sAddrLen);
AZ::s32 result = HandleSocketError(getsockname(sock, &sAddr, &sAddrLen));
addr = sAddr;
return result;
}
AZ::s32 Connect(AZSOCKET sock, const AzSocketAddress& addr)
{
AZ::s32 err = HandleSocketError(connect(sock, addr.GetTargetAddress(), sizeof(AZSOCKADDR_IN)));
if (err == static_cast<AZ::s32>(AzSockError::eASE_EINPROGRESS))
{
err = static_cast<AZ::s32>(AzSockError::eASE_EWOULDBLOCK_CONN);
}
return err;
}
AZ::s32 Listen(AZSOCKET sock, AZ::s32 backlog)
{
return HandleSocketError(listen(sock, backlog));
}
AZSOCKET Accept(AZSOCKET sock, AzSocketAddress& addr)
{
AZSOCKADDR sAddr;
AZSOCKLEN sAddrLen = sizeof(AZSOCKADDR);
memset(&sAddr, 0, sAddrLen);
AZSOCKET outSock = HandleInvalidSocket(accept(sock, &sAddr, &sAddrLen));
addr = sAddr;
return outSock;
}
AZ::s32 Send(AZSOCKET sock, const char* buf, AZ::s32 len, AZ::s32 flags)
{
AZ::s32 msgNoSignal = MSG_NOSIGNAL;
return HandleSocketError(send(sock, buf, len, flags | msgNoSignal));
}
AZ::s32 Recv(AZSOCKET sock, char* buf, AZ::s32 len, AZ::s32 flags)
{
return HandleSocketError(recv(sock, buf, len, flags));
}
AZ::s32 Bind(AZSOCKET sock, const AzSocketAddress& addr)
{
return HandleSocketError(bind(sock, addr.GetTargetAddress(), sizeof(AZSOCKADDR_IN)));
}
AZ::s32 Select(AZSOCKET sock, AZFD_SET* readfdsock, AZFD_SET* writefdsock, AZFD_SET* exceptfdsock, AZTIMEVAL* timeout)
{
return HandleSocketError(::select(sock + 1, readfdsock, writefdsock, exceptfdsock, timeout));
}
AZ::s32 IsRecvPending(AZSOCKET sock, AZTIMEVAL* timeout)
{
AZFD_SET readSet;
FD_ZERO(&readSet);
FD_SET(sock, &readSet);
AZ::s32 ret = Select(sock, &readSet, nullptr, nullptr, timeout);
if (ret >= 0)
{
ret = FD_ISSET(sock, &readSet);
if (ret != 0)
{
ret = 1;
}
}
return ret;
}
AZ::s32 WaitForWritableSocket(AZSOCKET sock, AZTIMEVAL* timeout)
{
AZFD_SET writeSet;
FD_ZERO(&writeSet);
FD_SET(sock, &writeSet);
AZ::s32 ret = Select(sock, nullptr, &writeSet, nullptr, timeout);
if (ret >= 0)
{
ret = FD_ISSET(sock, &writeSet);
if (ret != 0)
{
ret = 1;
}
}
return ret;
}
AZ::s32 Startup()
{
return static_cast<AZ::s32>(AzSockError::eASE_NO_ERROR);
}
AZ::s32 Cleanup()
{
return static_cast<AZ::s32>(AzSockError::eASE_NO_ERROR);
}
bool ResolveAddress(const AZStd::string& ip, AZ::u16 port, AZSOCKADDR_IN& socketAddress)
{
bool foundAddr = false;
addrinfo hints;
memset(&hints, 0, sizeof(addrinfo));
addrinfo* addrInfo;
hints.ai_family = AF_INET;
hints.ai_flags = AI_CANONNAME;
char strPort[8];
azsnprintf(strPort, AZ_ARRAY_SIZE(strPort), "%d", port);
const char* address = ip.c_str();
if (address && strlen(address) == 0) // getaddrinfo doesn't accept empty string
{
address = nullptr;
}
AZ::s32 err = HandleSocketError(getaddrinfo(address, strPort, &hints, &addrInfo));
if (err == 0) // eASE_NO_ERROR
{
if (addrInfo->ai_family == AF_INET)
{
socketAddress = *reinterpret_cast<const AZSOCKADDR_IN*>(addrInfo->ai_addr);
foundAddr = true;
}
freeaddrinfo(addrInfo);
}
else
{
AZ_Assert(false, "AzSocketAddress could not resolve address %s with port %d. (reason - %s)", ip.c_str(), port, GetStringForError(err));
}
return foundAddr;
}
}
}
@@ -0,0 +1,22 @@
/*
* 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 <cstddef>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <fcntl.h>
#define SD_RECEIVE SHUT_RD
#define SD_SEND SHUT_WR
#define SD_BOTH SHUT_RDWR
@@ -0,0 +1,15 @@
/*
* 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 sockaddr;
struct sockaddr_in;
@@ -0,0 +1,43 @@
/*
* 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 <AzCore/Utils/Utils.h>
#include <stdlib.h>
namespace AZ
{
namespace Utils
{
void RequestAbnormalTermination()
{
abort();
}
void NativeErrorMessageBox(const char*, const char*) {}
AZStd::optional<AZStd::fixed_string<MaxPathLength>> ConvertToAbsolutePath(AZStd::string_view path)
{
AZStd::fixed_string<MaxPathLength> absolutePath;
AZStd::fixed_string<MaxPathLength> srcPath{ path };
if (char* result = realpath(srcPath.c_str(), absolutePath.data()); result)
{
// Fix the size value of the fixed string by calculating the c-string length using char traits
absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
return absolutePath;
}
return AZStd::nullopt;
}
} // namespace Utils
} // namespace AZ
@@ -0,0 +1,219 @@
/*
* 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/std/chrono/clocks.h>
/**
* This file is to be included from the mutex.h only. It should NOT be included by the user.
*/
namespace AZStd
{
//////////////////////////////////////////////////////////////////////////
// Condition variable
inline condition_variable::condition_variable()
{
pthread_cond_init (&m_cond_var, NULL);
}
inline condition_variable::condition_variable(const char* name)
{
(void)name;
pthread_cond_init (&m_cond_var, NULL);
}
inline condition_variable::~condition_variable()
{
pthread_cond_destroy(&m_cond_var);
}
inline void condition_variable::notify_one()
{
pthread_cond_signal(&m_cond_var);
}
inline void condition_variable::notify_all()
{
pthread_cond_broadcast(&m_cond_var);
}
inline void condition_variable::wait(unique_lock<mutex>& lock)
{
pthread_cond_wait(&m_cond_var, lock.mutex()->native_handle());
}
template <class Predicate>
AZ_FORCE_INLINE void condition_variable::wait(unique_lock<mutex>& lock, Predicate pred)
{
while (!pred())
{
wait(lock);
}
}
template <class Clock, class Duration>
AZ_FORCE_INLINE cv_status condition_variable::wait_until(unique_lock<mutex>& lock, const chrono::time_point<Clock, Duration>& abs_time)
{
const auto now = chrono::system_clock::now();
if (now < abs_time)
{
return wait_for(lock, abs_time - now);
}
return cv_status::timeout;
}
template <class Clock, class Duration, class Predicate>
AZ_FORCE_INLINE bool condition_variable::wait_until(unique_lock<mutex>& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred)
{
while (!pred())
{
if (wait_until(lock, abs_time) == cv_status::timeout)
{
return pred();
}
}
return true;
}
// all the other functions eventually call this one, which invokes pthread. Pthread wil try its best to wait
// until the specified time arrives (but it may wake up spuriously if cancelled!). According to the standard,
// we return timeout if the reason we woke up was a time out, and no_timeout in all other situations.
template <class Rep, class Period>
AZ_FORCE_INLINE cv_status condition_variable::wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time)
{
timespec ts = Internal::CurrentTimeAndOffset(rel_time);
int ret = pthread_cond_timedwait(&m_cond_var, lock.mutex()->native_handle(), &ts);
// this assert catches the situation where you've given an invalid value
// to 'ts', such as nanoseconds > 999999999.
AZ_Assert(ret != EINVAL && ret != EPERM, "Invalid return from pthread_cond_timedwait - %i errorno: %s\n", ret, strerror(errno));
// note that the other possible error code is EINTR (interrupted by signal), but in this case, we have to allow it to proceed anyway
return ret == ETIMEDOUT ? cv_status::timeout : cv_status::no_timeout;
}
template <class Rep, class Period, class Predicate>
AZ_FORCE_INLINE bool condition_variable::wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred)
{
return wait_until(lock, chrono::system_clock::now() + rel_time, move(pred));
}
condition_variable::native_handle_type
inline condition_variable::native_handle()
{
return &m_cond_var;
}
//////////////////////////////////////////////////////////////////////////
// Condition variable any
inline condition_variable_any::condition_variable_any()
{
pthread_mutex_init(&m_mutex, NULL);
pthread_cond_init (&m_cond_var, NULL);
}
inline condition_variable_any::condition_variable_any(const char* name)
{
pthread_mutex_init(&m_mutex, NULL);
(void)name;
pthread_cond_init (&m_cond_var, NULL);
}
inline condition_variable_any::~condition_variable_any()
{
pthread_mutex_destroy(&m_mutex);
pthread_cond_destroy(&m_cond_var);
}
inline void condition_variable_any::notify_one()
{
pthread_mutex_lock(&m_mutex);
pthread_cond_signal(&m_cond_var);
pthread_mutex_unlock(&m_mutex);
}
inline void condition_variable_any::notify_all()
{
pthread_mutex_lock(&m_mutex);
pthread_cond_broadcast(&m_cond_var);
pthread_mutex_unlock(&m_mutex);
}
template<class Lock>
AZ_FORCE_INLINE void condition_variable_any::wait(Lock& lock)
{
pthread_mutex_lock(&m_mutex);
lock.unlock();
// We need to make sure we use CriticalSection based mutex.
pthread_cond_wait(&m_cond_var, &m_mutex);
pthread_mutex_unlock(&m_mutex);
lock.lock();
}
template <class Lock, class Predicate>
AZ_FORCE_INLINE void condition_variable_any::wait(Lock& lock, Predicate pred)
{
while (!pred())
{
wait(lock);
}
}
template <class Lock, class Clock, class Duration>
AZ_FORCE_INLINE cv_status condition_variable_any::wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time)
{
const auto now = chrono::system_clock::now();
if (now < abs_time)
{
// note that wait_for will either time out, in which case we should return time out, or it will return
// without timing out which means either an error occurred, or we got the signal we were waiting for.
// This means that either way, there is no point in having a while loop here.
return wait_for(lock, abs_time - now);
}
// if we started with the timeout already passed, we are immediately timed out.
return cv_status::timeout;
}
template <class Lock, class Clock, class Duration, class Predicate>
AZ_FORCE_INLINE bool condition_variable_any::wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred)
{
while (!pred())
{
if (wait_until(lock, abs_time) == cv_status::timeout)
{
return pred();
}
}
return true;
}
template <class Lock, class Rep, class Period>
AZ_FORCE_INLINE cv_status condition_variable_any::wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time)
{
pthread_mutex_lock(&m_mutex);
lock.unlock();
// We need to make sure we use CriticalSection based mutex.
timespec ts = Internal::CurrentTimeAndOffset(rel_time);
int ret = pthread_cond_timedwait(&m_cond_var, lock.mutex()->native_handle(), &ts);
pthread_mutex_unlock(&m_mutex);
lock.lock();
return ret == ETIMEDOUT ? cv_status::timeout : cv_status::no_timeout;
}
template <class Lock, class Rep, class Period, class Predicate>
AZ_FORCE_INLINE bool condition_variable_any::wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred)
{
return wait_until(lock, chrono::system_clock::now() + rel_time, move(pred));
}
condition_variable_any::native_handle_type
inline condition_variable_any::native_handle()
{
return &m_cond_var;
}
//////////////////////////////////////////////////////////////////////////
}
@@ -0,0 +1,106 @@
/*
* 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
/**
* This file is to be included from the mutex.h only. It should NOT be included by the user.
*/
namespace AZStd
{
//////////////////////////////////////////////////////////////////////////
// mutex
inline mutex::mutex()
{
pthread_mutex_init(&m_mutex, NULL);
}
inline mutex::mutex(const char* name)
{
(void)name;
pthread_mutex_init(&m_mutex, NULL);
}
inline mutex::~mutex()
{
pthread_mutex_destroy(&m_mutex);
}
AZ_FORCE_INLINE void
mutex::lock()
{
pthread_mutex_lock(&m_mutex);
}
AZ_FORCE_INLINE bool
mutex::try_lock()
{
return pthread_mutex_trylock(&m_mutex) == 0;
}
AZ_FORCE_INLINE void
mutex::unlock()
{
pthread_mutex_unlock(&m_mutex);
}
AZ_FORCE_INLINE mutex::native_handle_type
mutex::native_handle()
{
return &m_mutex;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// recursive_mutex
inline recursive_mutex::recursive_mutex()
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m_mutex, &attr);
pthread_mutexattr_destroy(&attr);
}
inline recursive_mutex::recursive_mutex(const char* name)
{
(void)name;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m_mutex, &attr);
pthread_mutexattr_destroy(&attr);
}
inline recursive_mutex::~recursive_mutex()
{
pthread_mutex_destroy(&m_mutex);
}
AZ_FORCE_INLINE void
recursive_mutex::lock()
{
pthread_mutex_lock(&m_mutex);
}
AZ_FORCE_INLINE bool
recursive_mutex::try_lock()
{
return pthread_mutex_trylock(&m_mutex) == 0;
}
AZ_FORCE_INLINE void
recursive_mutex::unlock()
{
pthread_mutex_unlock(&m_mutex);
}
AZ_FORCE_INLINE recursive_mutex::native_handle_type
recursive_mutex::native_handle()
{
return &m_mutex;
}
//////////////////////////////////////////////////////////////////////////
}
@@ -0,0 +1,119 @@
/*
* 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 "time_UnixLike.h"
/**
* This file is to be included from the semaphore.h only. It should NOT be included by the user.
*/
namespace AZStd
{
inline semaphore::semaphore(unsigned int initialCount, unsigned int maximumCount)
{
int result = sem_init(&m_semaphore, 0, initialCount);
(void)result;
AZ_Assert(result == 0, "sem_init error %s\n", strerror(errno));
result = sem_init(&m_maxCountSemaphore, 0, maximumCount);
AZ_Assert(result == 0, "sem_init error for max count semaphore %s\n", strerror(errno));
}
inline semaphore::semaphore(const char* name, unsigned int initialCount, unsigned int maximumCount)
{
(void)name; // name is used only for debug, if we pass it to the semaphore it will become named semaphore
// we can share the semaphore and use the name, but the intention of the name is for debugging
// for named shared semaphores use the OS directly as this is a slot operation
int result = sem_init(&m_semaphore, 0, initialCount);
(void)result;
AZ_Assert(result == 0, "sem_init error %s\n", strerror(errno));
result = sem_init(&m_maxCountSemaphore, 0, maximumCount);
AZ_Assert(result == 0, "sem_init error for max count semaphore %s\n", strerror(errno));
}
inline semaphore::~semaphore()
{
int result = sem_destroy(&m_semaphore);
(void)result;
AZ_Assert(result == 0, "sem_destroy error %s\n", strerror(errno));
result = sem_destroy(&m_maxCountSemaphore);
AZ_Assert(result == 0, "sem_destroy error for max count semaphore:%s\n", strerror(errno));
}
inline void semaphore::acquire()
{
int result = sem_post(&m_maxCountSemaphore);
AZ_Assert(result == 0, "post error for max count semaphore:%s\n", strerror(errno));
result = sem_wait(&m_semaphore);
(void)result;
// note that we could return 0, or we could return EINTR, and its okay to be 'interrupted'
// by a system call. Therefore, the only real error we care about is EINVAL.
AZ_Assert(result != EINVAL && result != EINTR, "sem_wait error %s\n", strerror(errno));
}
template <class Rep, class Period>
AZ_FORCE_INLINE bool semaphore::try_acquire_for(const chrono::duration<Rep, Period>& rel_time)
{
timespec ts = Internal::CurrentTimeAndOffset(rel_time);
int result = 0;
while ((result = sem_timedwait(&m_semaphore, &ts)) == -1 && errno == EINTR)
{
continue; /* Restart if interrupted by handler */
}
// as above, EINVAL is the only "unexpected" code
AZ_Assert(result != EINVAL && result != EINTR, "sem_timedwait error %s\n", strerror(errno));
return result == 0;
}
template <class Clock, class Duration>
AZ_FORCE_INLINE bool semaphore::try_acquire_until(const chrono::time_point<Clock, Duration>& abs_time)
{
auto timeNow = chrono::system_clock::now();
if (timeNow >= abs_time)
{
// we already timed out.
return false;
}
auto timeDiff = abs_time - timeNow;
return try_acquire_for(timeDiff);
}
AZ_FORCE_INLINE void semaphore::release(unsigned int releaseCount)
{
int result = sem_wait(&m_maxCountSemaphore);
AZ_Assert(result == 0, "sem_wait error for max count semaphore: %s\n", strerror(errno));
while (releaseCount)
{
result = sem_post(&m_semaphore);
AZ_Assert(result == 0, "sem_post error: %s\n", strerror(errno));
if (result != 0)
{
break; // exit on error
}
--releaseCount;
}
}
inline semaphore::native_handle_type semaphore::native_handle()
{
return &m_semaphore;
}
}
@@ -0,0 +1,136 @@
/*
* 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 <AzCore/std/parallel/thread.h>
#include <AzCore/std/parallel/threadbus.h>
#include <sched.h>
#include <errno.h>
namespace AZStd
{
namespace Platform
{
void NameCurrentThread(const char* name);
void PreCreateSetThreadAffinity(int cpuId, pthread_attr_t& attr);
void SetThreadPriority(int priority, pthread_attr_t& attr);
void PostCreateThread(pthread_t tId, const char * name, int cpuId);
}
namespace Internal
{
void* thread_run_function(void* param)
{
thread_info* ti = reinterpret_cast<thread_info*>(param);
Platform::NameCurrentThread(ti->m_name);
ti->execute();
destroy_thread_info(ti);
ThreadEventBus::Broadcast(&ThreadEventBus::Events::OnThreadExit, this_thread::get_id());
ThreadDrillerEventBus::Broadcast(&ThreadDrillerEventBus::Events::OnThreadExit, this_thread::get_id());
pthread_exit(nullptr);
return nullptr;
}
pthread_t create_thread(const thread_desc* desc, thread_info* ti)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
size_t stackSize = 2 * 1024 * 1024;
int priority = -1;
int cpuId = -1;
const char* name = "AZStd thread";
if (desc)
{
if (desc->m_stackSize != -1)
{
stackSize = desc->m_stackSize;
}
if (desc->m_priority >= sched_get_priority_min(SCHED_FIFO) && desc->m_priority <= sched_get_priority_max(SCHED_FIFO))
{
priority = desc->m_priority;
}
if (desc->m_name)
{
name = desc->m_name;
}
cpuId = desc->m_cpuId;
pthread_attr_setdetachstate(&attr, desc->m_isJoinable ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED);
Platform::PreCreateSetThreadAffinity(cpuId, attr);
}
pthread_attr_setstacksize(&attr, stackSize);
Platform::SetThreadPriority(priority, attr);
pthread_t tId;
int res = pthread_create(&tId, &attr, &thread_run_function, ti);
(void)res;
AZ_Assert(res == 0, "pthread failed %s", strerror(errno));
pthread_attr_destroy(&attr);
// Platform specific post thread creation action (setting thread name on some, affinity on others)
Platform::PostCreateThread(tId, name, cpuId);
ThreadEventBus::Broadcast(&ThreadEventBus::Events::OnThreadEnter, thread::id(tId), desc);
ThreadDrillerEventBus::Broadcast(&ThreadDrillerEventBus::Events::OnThreadEnter, thread::id(tId), desc);
return tId;
}
}
thread::thread()
{
m_thread = native_thread_invalid_id;
}
thread::thread(Internal::thread_move_t<thread> rhs)
{
m_thread = rhs->m_thread;
rhs->m_thread = native_thread_invalid_id;
}
thread::~thread()
{
AZ_Assert(!joinable(), "You must call detach or join before you delete a thread!");
}
void thread::join()
{
AZ_Assert(joinable(), "Thread must be joinable!");
if (!pthread_equal(m_thread, native_thread_invalid_id))
{
pthread_join(m_thread, nullptr);
m_thread = native_thread_invalid_id;
}
}
void thread::detach()
{
AZ_Assert(joinable(), "Thread must be joinable!");
if (!pthread_equal(m_thread, native_thread_invalid_id))
{
pthread_detach(m_thread);
m_thread = native_thread_invalid_id;
}
}
unsigned thread::hardware_concurrency()
{
return AZ_TRAIT_THREAD_HARDWARE_CONCURRENCY_RETURN_VALUE;
}
}
@@ -0,0 +1,86 @@
/*
* 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 <unistd.h>
#include <sched.h>
namespace AZStd
{
namespace Internal
{
/**
* Create and run thread
*/
pthread_t create_thread(const thread_desc* desc, thread_info* ti);
}
//////////////////////////////////////////////////////////////////////////
// thread
template <class F>
inline thread::thread(F&& f, const thread_desc* desc)
{
Internal::thread_info* ti = Internal::create_thread_info(AZStd::forward<F>(f));
ti->m_name = desc ? desc->m_name : nullptr;
m_thread = Internal::create_thread(desc, ti);
}
inline bool thread::joinable() const
{
if (pthread_equal(m_thread, native_thread_invalid_id))
{
return false;
}
return !pthread_equal(m_thread, this_thread::get_id().m_id);
}
inline thread::id thread::get_id() const
{
return thread::id(m_thread);
}
thread::native_handle_type
inline thread::native_handle()
{
return m_thread;
}
//////////////////////////////////////////////////////////////////////////
namespace this_thread
{
AZ_FORCE_INLINE thread::id get_id()
{
return thread::id(pthread_self());
}
AZ_FORCE_INLINE void yield()
{
sched_yield();
}
AZ_FORCE_INLINE void pause(int numLoops)
{
for (int i = 0; i < numLoops; ++i)
{
sched_yield();
}
}
template <class Rep, class Period>
AZ_FORCE_INLINE void sleep_for(const chrono::duration<Rep, Period>& rel_time)
{
chrono::microseconds toSleep = rel_time;
//Note: nanosleep is reccomended over usleep
usleep(static_cast<useconds_t>(toSleep.count()));
}
}
}
@@ -0,0 +1,55 @@
/*
* 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 <time.h>
#include <errno.h>
namespace AZStd
{
namespace Internal
{
inline timespec CurrentTime()
{
struct timespec ts;
int result = clock_gettime(CLOCK_REALTIME, &ts);
(void)result;
AZ_Assert(result != -1, "clock_gettime error %s\n", strerror(errno));
return ts;
}
}
namespace Internal
{
template <class Rep, class Period>
AZ_FORCE_INLINE timespec CurrentTimeAndOffset(const chrono::duration<Rep, Period>& rel_time)
{
timespec ts = CurrentTime();
chrono::seconds timeInSeconds = rel_time;
ts.tv_sec += timeInSeconds.count();
ts.tv_nsec += chrono::nanoseconds(rel_time - timeInSeconds).count();
// note that ts.tv_nsec could have overflowed 'one second' worth of nanoseconds but since CurrentTime()
// will always return under 1,000,000,000 nanoseconds and so will the subtraction above here, the
// largest the two could be is 1,999,999,999 nanoseconds when summed together, so we do not have to do
// a while loop, one subtraction is enough.
if (ts.tv_nsec >= 1000000000)
{
ts.tv_nsec -= 1000000000;
ts.tv_sec += 1;
}
return ts;
}
}
}
@@ -0,0 +1,72 @@
/*
* 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 <AzCore/std/time.h>
#include <time.h>
#include <errno.h>
namespace AZStd
{
AZStd::sys_time_t GetTimeTicksPerSecond()
{
// Value is in nano seconds, return number of nano seconds in one second
AZStd::sys_time_t freq = 1000000000L;
return freq;
}
AZStd::sys_time_t GetTimeNowTicks()
{
AZStd::sys_time_t timeNow;
struct timespec ts;
int result = clock_gettime(CLOCK_MONOTONIC_RAW, &ts); // Similar to CLOCK_MONOTONIC, but provides access to a raw hardware-based time that is not subject to NTP adjustments.
if (result < 0)
{
// NOTE(HS): WSL doesn't implement support for CLOCK_MONOTONIC_RAW and there
// is no way to check platform for conditional compile. Fallback to supported
// option if desired option fails.
result = clock_gettime(CLOCK_MONOTONIC, &ts);
}
AZ_Assert(result != -1, "clock_gettime error: %s\n", strerror(errno));
timeNow = ts.tv_sec * GetTimeTicksPerSecond() + ts.tv_nsec;
return timeNow;
}
AZStd::sys_time_t GetTimeNowMicroSecond()
{
AZStd::sys_time_t timeNowMicroSecond;
timeNowMicroSecond = GetTimeNowTicks() / 1000L;
return timeNowMicroSecond;
}
// time in seconds is the same as the POSIX time_t
AZStd::sys_time_t GetTimeNowSecond()
{
AZStd::sys_time_t timeNowSecond;
struct timespec ts;
int result = clock_gettime(CLOCK_MONOTONIC_RAW, &ts); // Similar to CLOCK_MONOTONIC, but provides access to a raw hardware-based time that is not subject to NTP adjustments.
(void)result;
AZ_Assert(result != -1, "clock_gettime error: %s\n", strerror(errno));
timeNowSecond = ts.tv_sec;
return timeNowSecond;
}
AZ::u64 GetTimeUTCMilliSecond()
{
AZ::u64 utc;
struct timespec ts;
int result = clock_gettime(CLOCK_REALTIME, &ts);
(void)result;
AZ_Assert(result != -1, "clock_gettime error %s\n", strerror(errno));
utc = ts.tv_sec * 1000L + ts.tv_nsec / 1000000L;
return utc;
}
}
@@ -0,0 +1,258 @@
/*
* 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 <AzCore/IO/SystemFile.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/IO/FileIOEventBus.h>
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/PlatformIncl.h>
#include <AzCore/Utils/Utils.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <dirent.h>
namespace AZ::IO
{
namespace UnixLikePlatformUtil
{
bool CanCreateDirRecursive(char*)
{
// No additional checks on these platforms, tell the caller to continue
return true;
}
}
namespace
{
static const SystemFile::FileHandleType PlatformSpecificInvalidHandle = AZ_TRAIT_SYSTEMFILE_INVALID_HANDLE;
}
bool SystemFile::PlatformOpen(int mode, int platformFlags)
{
int desiredAccess = 0;
int permissions = S_IRWXU | S_IRGRP | S_IROTH;
bool createPath = false;
if ((mode & SF_OPEN_READ_WRITE) == SF_OPEN_READ_WRITE)
{
desiredAccess = O_RDWR;
}
else if ((mode & SF_OPEN_READ_ONLY) == SF_OPEN_READ_ONLY)
{
desiredAccess = O_RDONLY;
}
else if ((mode & SF_OPEN_WRITE_ONLY) == SF_OPEN_WRITE_ONLY || (mode & SF_OPEN_APPEND))
{
desiredAccess = O_WRONLY;
}
else
{
EBUS_EVENT(FileIOEventBus, OnError, this, nullptr, 0);
return false;
}
if ((mode & SF_OPEN_CREATE_NEW) == SF_OPEN_CREATE_NEW)
{
desiredAccess |= O_CREAT | O_EXCL;
createPath = (mode & SF_OPEN_CREATE_PATH) == SF_OPEN_CREATE_PATH;
}
else if ((mode & SF_OPEN_CREATE) == SF_OPEN_CREATE)
{
desiredAccess |= O_CREAT | O_TRUNC;
createPath = (mode & SF_OPEN_CREATE_PATH) == SF_OPEN_CREATE_PATH;
}
else if ((mode & SF_OPEN_TRUNCATE))
{
desiredAccess |= O_TRUNC;
}
if (createPath)
{
CreatePath(m_fileName);
}
m_handle = open(m_fileName, desiredAccess, permissions);
if (m_handle == PlatformSpecificInvalidHandle)
{
EBUS_EVENT(FileIOEventBus, OnError, this, nullptr, errno);
return false;
}
else
{
if (mode & SF_OPEN_APPEND)
{
lseek(m_handle, 0, SEEK_END);
}
}
return true;
}
void SystemFile::PlatformClose()
{
if (m_handle != PlatformSpecificInvalidHandle)
{
close(m_handle);
m_handle = PlatformSpecificInvalidHandle;
}
}
namespace Platform
{
using FileHandleType = AZ::IO::SystemFile::FileHandleType;
void Seek(FileHandleType handle, const SystemFile* systemFile, SizeType offset, SystemFile::SeekMode mode)
{
if (handle != PlatformSpecificInvalidHandle)
{
int result = lseek(handle, offset, mode);
if (result == -1)
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, errno);
}
}
}
SystemFile::SizeType Tell(FileHandleType handle, const SystemFile* systemFile)
{
if (handle != PlatformSpecificInvalidHandle)
{
off_t result = lseek(handle, 0, SEEK_CUR);
if (result == (off_t)-1)
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, errno);
}
return aznumeric_cast<SizeType>(result);
}
return 0;
}
bool Eof(FileHandleType handle, const SystemFile* systemFile)
{
if (handle != PlatformSpecificInvalidHandle)
{
off_t current = lseek(handle, 0, SEEK_CUR);
if (current == (off_t)-1)
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, current);
return false;
}
off_t end = lseek(handle, 0, SEEK_END);
if (end == (off_t)-1)
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, end);
return false;
}
// Reset file pointer back to from whence it came
lseek(handle, current, SEEK_SET);
return current == end;
}
return false;
}
AZ::u64 ModificationTime(FileHandleType handle, const SystemFile* systemFile)
{
if (handle != PlatformSpecificInvalidHandle)
{
struct stat statResult;
if (fstat(handle, &statResult) != 0)
{
return 0;
}
return aznumeric_cast<AZ::u64>(statResult.st_mtime);
}
return 0;
}
SystemFile::SizeType Read(FileHandleType handle, const SystemFile* systemFile, SizeType byteSize, void* buffer)
{
if (handle != PlatformSpecificInvalidHandle)
{
ssize_t bytesRead = read(handle, buffer, byteSize);
if (bytesRead == -1)
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, errno);
return 0;
}
return bytesRead;
}
return 0;
}
SystemFile::SizeType Write(FileHandleType handle, const SystemFile* systemFile, const void* buffer, SizeType byteSize)
{
if (handle != PlatformSpecificInvalidHandle)
{
ssize_t result = write(handle, buffer, byteSize);
if (result == -1)
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, errno);
return 0;
}
return result;
}
return 0;
}
void Flush(FileHandleType handle, const SystemFile* systemFile)
{
if (handle != PlatformSpecificInvalidHandle)
{
#if AZ_TRAIT_SYSTEMFILE_FSYNC_IS_DEFINED
if (fsync(handle) != 0)
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, errno);
}
#endif
}
}
SystemFile::SizeType Length(FileHandleType handle, const SystemFile* systemFile)
{
if (handle != PlatformSpecificInvalidHandle)
{
struct stat stat;
if (fstat(handle, &stat) < 0)
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, 0);
return 0;
}
return stat.st_size;
}
return 0;
}
bool Exists(const char* fileName)
{
return access(fileName, F_OK) == 0;
}
}
} // namespace AZ::IO
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<NonUserCode xmlns="http://schemas.microsoft.com/vstudio/debugger/jmc/2015">
<!-- <Module Name="?:\Windows\System32\*.dll"/> -->
<File Name="*\AzCore\std\*" />
<File Name="*\AzCore\Debug\Trace*" />
<File Name="*\AzCore\Debug\Stack*" />
<File Name="*\AzCore\EBus\*" />
<!-- Generated files-->
<File Name="*.generated*" />
</NonUserCode>
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010">
<Function><Name>AZStd::atomic&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::pair&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::reverse_iterator&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::vector&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::fixed_vector&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::array&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::bitset&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::bitset&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::list&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::forward_list&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::fixed_list&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::fixed_forward_list&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::intrusive_list&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::intrusive_slist&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::intrusive_multiset_node&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::intrusive_multiset&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::list_const_iterator&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::deque&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::queue&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::stack&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::priority_queue&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::map&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::hash_table&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::basic_string&lt;char,.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::basic_string&lt;wchar_t,.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::reference_wrapper&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::plus&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::minus&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::multiplies&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::divides&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::modulus&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::negate&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::equal_to&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::not_equal_to&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::greater&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::less&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::greater_equal&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::less_equal&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::logical_and&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::logical_or&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::logical_not&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::bit_and&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::bit_or&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::bit_xor&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::identity&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::unary_negate&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::binary_negate&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::forward&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZStd::move&lt;.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZ::Uuid::.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZ::Vector2::.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZ::Vector3::.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZ::Vector4::.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZ::Quaternion::.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZ::Transform::.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZ::Matrix3x3::.*</Name><Action>NoStepInto</Action></Function>
<Function><Name>AZ::Matrix4x4::.*</Name><Action>NoStepInto</Action></Function>
</StepFilter>
@@ -0,0 +1,833 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="AZStd::pair&lt;*&gt;">
<DisplayString>({first}, {second})</DisplayString>
<Expand>
<Item Name="first">first</Item>
<Item Name="second">second</Item>
</Expand>
</Type>
<Type Name="AZStd::reverse_iterator&lt;*&gt;" Priority="Medium">
<DisplayString>reverse_iterator base() {m_current}</DisplayString>
<Expand>
<Item Name="base()">m_current</Item>
</Expand>
</Type>
<!-- Partial Specialization for raw pointers and smart pointers which are indexable(supports operator[]). See natvis.xsd for more details-->
<Type Name="AZStd::reverse_iterator&lt;*&gt;" Priority="MediumHigh">
<SmartPointer Usage="Indexable">m_current - 1</SmartPointer>
<DisplayString>reverse_iterator {m_current[-1]}</DisplayString>
<Expand>
<Item Name="[ptr]">m_current - 1</Item>
</Expand>
</Type>
<Type Name="AZStd::vector&lt;*&gt;">
<DisplayString>vector[{m_last - m_start}]</DisplayString>
<Expand>
<Item Name="[capacity]">m_end - m_start</Item>
<ArrayItems>
<Size>m_last - m_start</Size>
<ValuePointer>m_start</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="AZStd::Internal::fixed_zero_size_storage&lt;*&gt;">
<AlternativeType Name="AZStd::fixed_vector&lt;*,0&gt;" />
<DisplayString>fixed_vector[0] capacity 0</DisplayString>
<Expand>
<Item Name="[size]">0</Item>
<Item Name="[capacity]">0</Item>
<ArrayItems>
<Size>0</Size>
<ValuePointer>nullptr</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="AZStd::Internal::fixed_trivial_storage&lt;*,*&gt;">
<AlternativeType Name="AZStd::fixed_vector&lt;*,*&gt;" />
<DisplayString>fixed_vector[{(size_t)m_size}] capacity {$T2}</DisplayString>
<Expand>
<Item Name="[size]">(size_t)m_size</Item>
<Item Name="[capacity]">$T2</Item>
<ArrayItems>
<Size>m_size</Size>
<ValuePointer>($T1*)m_data</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="AZStd::Internal::fixed_non_trivial_storage&lt;*,*&gt;">
<AlternativeType Name="AZStd::fixed_vector&lt;*,*&gt;" />
<DisplayString>fixed_vector[{(size_t)m_size}] capacity {$T2}</DisplayString>
<Expand>
<Item Name="[size]">(size_t)m_size</Item>
<Item Name="[capacity]">$T2</Item>
<ArrayItems>
<Size>m_size</Size>
<ValuePointer>($T1*)m_data</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="AZStd::atomic&lt;*&gt;">
<AlternativeType Name="AZStd::internal::atomic_base&lt;*&gt;" />
<Expand>
<Item Name="Value">m_value</Item>
</Expand>
</Type>
<Type Name="AZStd::array&lt;*,*&gt;">
<DisplayString>array[{$T2}]</DisplayString>
<Expand>
<ArrayItems>
<Size>$T2</Size>
<ValuePointer>m_elements</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="AZStd::bitset&lt;*&gt;">
<DisplayString>bitset[{$T1}]</DisplayString>
<Expand>
<IndexListItems>
<Size>$T1</Size>
<ValueNode>(m_bits[$i / BitsPerWord] &gt;&gt; ($i % BitsPerWord)) &amp; 1,d</ValueNode>
</IndexListItems>
</Expand>
</Type>
<Type Name="AZStd::bitset&lt;*&gt;::reference">
<DisplayString>{(m_bitSet.m_bits[m_pos / m_bitSet.BitsPerWord] &gt;&gt; (m_pos % m_bitSet.BitsPerWord)) &amp; 1,d}</DisplayString>
<Expand>
<Item Name="[bitset]">m_bitSet</Item>
<Item Name="[pos]">m_pos</Item>
</Expand>
</Type>
<Type Name="AZStd::list&lt;*&gt;">
<DisplayString>list[{m_numElements}]</DisplayString>
<Expand>
<LinkedListItems>
<Size>m_numElements</Size>
<HeadPointer>m_head.m_next</HeadPointer>
<NextPointer>m_next</NextPointer>
<ValueNode>(*(Internal::list_node&lt;$T1&gt;*)(this)).m_value</ValueNode>
</LinkedListItems>
</Expand>
</Type>
<Type Name="AZStd::forward_list&lt;*&gt;">
<DisplayString>forward_list[{m_numElements}]</DisplayString>
<Expand>
<LinkedListItems>
<Size>m_numElements</Size>
<HeadPointer>m_head.m_next</HeadPointer>
<NextPointer>m_next</NextPointer>
<ValueNode>*($T1*)(this+1)</ValueNode>
</LinkedListItems>
</Expand>
</Type>
<Type Name="AZStd::fixed_list&lt;*,*&gt;">
<DisplayString>fixed_list[{m_numElements}] capacity {$T2}</DisplayString>
<Expand>
<Item Name="[capacity]">$T2</Item>
<LinkedListItems>
<Size>m_numElements</Size>
<HeadPointer>m_head.m_next</HeadPointer>
<NextPointer>m_next</NextPointer>
<ValueNode>*($T1*)(this+1)</ValueNode>
</LinkedListItems>
</Expand>
</Type>
<Type Name="AZStd::fixed_forward_list&lt;*,*&gt;">
<DisplayString>fixed_forward_list[{m_numElements}] capacity {$T2}</DisplayString>
<Expand>
<Item Name="[capacity]">$T2</Item>
<LinkedListItems>
<Size>m_numElements</Size>
<HeadPointer>m_head.m_next</HeadPointer>
<NextPointer>m_next</NextPointer>
<ValueNode>*($T1*)(this+1)</ValueNode>
</LinkedListItems>
</Expand>
</Type>
<Type Name="AZStd::intrusive_list&lt;*,AZStd::list_base_hook&lt;*&gt;&gt;">
<DisplayString>intrusive_list[{m_numElements}]</DisplayString>
<Expand>
<LinkedListItems>
<Size>m_numElements</Size>
<HeadPointer>((AZStd::intrusive_list_node&lt;$T1&gt;*)(m_root.m_buffer))-&gt;m_next</HeadPointer>
<NextPointer>m_next</NextPointer>
<ValueNode>*($T1*)this</ValueNode>
</LinkedListItems>
</Expand>
</Type>
<Type Name="AZStd::intrusive_list&lt;*,AZStd::list_member_hook&lt;*,*&gt;&gt;">
<DisplayString>intrusive_list[{m_numElements}]</DisplayString>
<Expand>
<LinkedListItems>
<Size>m_numElements</Size>
<HeadPointer>(((AZStd::intrusive_list_node&lt;$T1&gt;*)(m_root.m_buffer + $T3))-&gt;m_next)</HeadPointer>
<NextPointer>(((AZStd::intrusive_list_node&lt;$T1&gt;*)((char*)this + $T3))-&gt;m_next)</NextPointer>
<ValueNode>*this</ValueNode>
</LinkedListItems>
</Expand>
</Type>
<Type Name="AZStd::intrusive_slist&lt;*,AZStd::slist_base_hook&lt;*&gt;&gt;">
<DisplayString>intrusive_slist[{m_numElements}]</DisplayString>
<Expand>
<LinkedListItems>
<Size>m_numElements</Size>
<HeadPointer>((AZStd::intrusive_slist_node&lt;$T1,0&gt;*)(m_root.m_buffer))-&gt;m_next</HeadPointer>
<NextPointer>m_next</NextPointer>
<ValueNode>*($T1*)this</ValueNode>
</LinkedListItems>
</Expand>
</Type>
<Type Name="AZStd::intrusive_slist&lt;*,AZStd::slist_member_hook&lt;*,*&gt;&gt;">
<DisplayString>intrusive_slist[{m_numElements}]</DisplayString>
<Expand>
<LinkedListItems>
<Size>m_numElements</Size>
<HeadPointer>(((AZStd::intrusive_slist_node&lt;$T1,0&gt;*)(m_root.m_buffer + $T3))-&gt;m_next)</HeadPointer>
<NextPointer>(((AZStd::intrusive_slist_node&lt;$T1,0&gt;*)((char*)this + $T3))-&gt;m_next)</NextPointer>
<ValueNode>*this</ValueNode>
</LinkedListItems>
</Expand>
</Type>
<Type Name="AZStd::intrusive_multiset_node&lt;*&gt;">
<DisplayString>intrusive_multiset_node</DisplayString>
<Expand>
<Item Name="Children">m_children</Item>
<Item Name="Neighbours">m_children</Item>
<Item Name="Parent">($T1*)((size_t)m_parentColorSide &amp; &#126;3)</Item>
<Item Name="Color">((size_t)m_parentColorSide &amp; 1)</Item>
</Expand>
</Type>
<Type Name="AZStd::intrusive_multiset&lt;*,AZStd::intrusive_multiset_base_hook&lt;*&gt;,*&gt;">
<DisplayString>intrusive_multiset[{m_numElements}]</DisplayString>
<Expand>
<Item Name="NumberElements">m_numElements</Item>
<Item Name="Root">((AZStd::intrusive_multiset_node&lt;$T1&gt;*)(m_head.m_buffer))-&gt;m_children[0]</Item>
</Expand>
</Type>
<Type Name="AZStd::intrusive_multiset&lt;*,AZStd::intrusive_multiset_member_hook&lt;*,*&gt;,*&gt;">
<DisplayString>intrusive_multiset[{m_numElements}]</DisplayString>
<Expand>
<Item Name="NumberElements">m_numElements</Item>
<Item Name="Root">((AZStd::intrusive_multiset_node&lt;$T1&gt;*)(m_head.m_buffer + $T3))-&gt;m_children[0]</Item>
</Expand>
</Type>
<Type Name="AZStd::list_const_iterator&lt;*&gt;">
<AlternativeType Name="AZStd::list_iterator&lt;*&gt;" />
<AlternativeType Name="AZStd::forward_list_iterator&lt;*&gt;" />
<AlternativeType Name="AZStd::forward_list_const_iterator&lt;*&gt;" />
<DisplayString>{*((Internal::list_node&lt;$T1&gt;*)(m_node))}</DisplayString>
<Expand>
<Item Name="[ptr]">(void*)(m_node), x</Item>
<Item Name="[value]">*((Internal::list_node&lt;$T1&gt;*)(m_node))</Item>
</Expand>
</Type>
<Type Name="AZStd::intrusive_list&lt;*&gt;::const_iterator_impl">
<AlternativeType Name="AZStd::intrusive_list&lt;*&gt;::iterator_impl" />
<AlternativeType Name="AZStd::intrusive_slist&lt;*&gt;::const_iterator_impl" />
<AlternativeType Name="AZStd::intrusive_slist&lt;*&gt;::iterator_impl" />
<DisplayString>{*m_node}</DisplayString>
<Expand>
<Item Name="[ptr]">(void*)m_node, x</Item>
<Item Name="[value]">*m_node</Item>
</Expand>
</Type>
<Type Name="AZStd::deque&lt;*,*,*,*&gt;">
<DisplayString>deque[{m_size}]</DisplayString>
<Expand>
<IndexListItems>
<Size>m_size</Size>
<ValueNode>m_map[ (($i + m_firstOffset) / $T3 ) % m_mapSize][($i + m_firstOffset) % $T3]</ValueNode>
</IndexListItems>
</Expand>
</Type>
<Type Name="AZStd::deque&lt;*,*,*,*&gt;::const_iterator_impl">
<AlternativeType Name="AZStd::deque&lt;*,*,*,*&gt;::iterator_impl" />
<DisplayString Condition="m_offset &gt;= (m_container-&gt;m_firstOffset + m_container-&gt;m_size)">[end]</DisplayString>
<DisplayString Condition="m_offset &lt; (m_container-&gt;m_firstOffset + m_container-&gt;m_size)">deque[{m_offset-m_container-&gt;m_firstOffset}] = {m_container-&gt;m_map[(m_offset / $T3) % m_container-&gt;m_mapSize][m_offset % $T3]}</DisplayString>
<Expand>
<Item Condition="m_offset &lt; (m_container-&gt;m_firstOffset + m_container-&gt;m_size)" Name="[index]">m_offset-m_container-&gt;m_firstOffset</Item>
<Item Condition="m_offset &lt; (m_container-&gt;m_firstOffset + m_container-&gt;m_size)" Name="[value]">m_container-&gt;m_map[(m_offset / $T3) % m_container-&gt;m_mapSize][m_offset % $T3]</Item>
<Item Condition="m_offset &lt; (m_container-&gt;m_firstOffset + m_container-&gt;m_size)" Name="[ptr]">&amp;m_container-&gt;m_map[(m_offset / $T3) % m_container-&gt;m_mapSize][m_offset % $T3]</Item>
</Expand>
</Type>
<Type Name="AZStd::queue&lt;*&gt;">
<DisplayString>queue({m_container})</DisplayString>
<Expand>
<Item Name="container">m_container</Item>
</Expand>
</Type>
<Type Name="AZStd::stack&lt;*&gt;">
<DisplayString>stack({m_container})</DisplayString>
<Expand>
<Item Name="container">m_container</Item>
</Expand>
</Type>
<Type Name="AZStd::priority_queue&lt;*&gt;">
<DisplayString>priority_queue({m_container})</DisplayString>
<Expand>
<Item Name="container">m_container</Item>
<Item Name="compare">m_comp</Item>
</Expand>
</Type>
<!-- TODO: AZStd::ring_buffer -->
<Type Name="AZStd::rbtree_const_iterator&lt;*&gt;">
<AlternativeType Name="AZStd::rbtree_iterator&lt;*&gt;" />
<DisplayString>{m_node-&gt;m_value}</DisplayString>
<Expand>
<Item Name="[ptr]">(void*)&amp;m_node-&gt;m_value, x</Item>
<Item Name="[value]">m_node-&gt;m_value</Item>
</Expand>
</Type>
<Type Name="AZStd::Internal::rbtree_node_base">
<Expand>
<Synthetic Name="color">
<DisplayString Condition="((size_t)(m_parentColor) &amp; 1) == 1">Black</DisplayString>
<DisplayString Condition="((size_t)(m_parentColor) &amp; 1) == 0">Red</DisplayString>
</Synthetic>
<Item Name="parent">(AZStd::Internal::rbtree_node_base*)((uintptr_t)(m_parentColor) &amp; ~1ULL)</Item>
<Item Name="left">m_left</Item>
<Item Name="right">m_right</Item>
</Expand>
</Type>
<Type Name="AZStd::Internal::rbtree_node&lt;*&gt;">
<Expand>
<Item Name="value">m_value</Item>
<ExpandedItem>*(AZStd::Internal::rbtree_node_base*)this,nd</ExpandedItem>
</Expand>
</Type>
<Type Name="AZStd::rbtree&lt;*&gt;">
<DisplayString>rbtree[{m_numElements}]</DisplayString>
<Expand>
<TreeItems>
<Size>m_numElements</Size>
<HeadPointer>m_head.m_parentColor</HeadPointer>
<LeftPointer>m_left</LeftPointer>
<RightPointer>m_right</RightPointer>
<ValueNode Condition="this != m_left">*((typename AZStd::rbtree&lt;$T1&gt;::node_type*)(this))</ValueNode>
</TreeItems>
</Expand>
</Type>
<Type Name="AZStd::set&lt;*&gt;">
<AlternativeType Name="AZStd::multiset&lt;*&gt;" />
<DisplayString>ordered_set[{m_tree.m_numElements}]</DisplayString>
<Expand>
<TreeItems>
<Size>m_tree.m_numElements</Size>
<HeadPointer>m_tree.m_head.m_parentColor</HeadPointer>
<LeftPointer>m_left</LeftPointer>
<RightPointer>m_right</RightPointer>
<ValueNode Condition="this != m_left">(*(AZStd::Internal::rbtree_node&lt;$T1&gt;*)(this)).m_value</ValueNode>
</TreeItems>
</Expand>
</Type>
<Type Name="AZStd::map&lt;*,*&gt;">
<AlternativeType Name="AZStd::multimap&lt;*,*&gt;" />
<DisplayString>ordered_map[{m_tree.m_numElements}]</DisplayString>
<Expand>
<TreeItems>
<Size>m_tree.m_numElements</Size>
<HeadPointer>m_tree.m_head.m_parentColor</HeadPointer>
<LeftPointer>m_left</LeftPointer>
<RightPointer>m_right</RightPointer>
<ValueNode Condition="this != m_left" Name="[{*($T1*)(this + 1)}]">*($T2*)(&amp;((*((AZStd::Internal::rbtree_node&lt;AZStd::pair&lt;$T1,$T2&gt; &gt;*)(this))).m_value.second))</ValueNode>
</TreeItems>
</Expand>
</Type>
<Type Name="AZStd::hash_table&lt;*&gt;">
<AlternativeType Name="AZStd::unordered_map&lt;*&gt;" />
<AlternativeType Name="AZStd::unordered_multimap&lt;*&gt;" />
<AlternativeType Name="AZStd::unordered_set&lt;*&gt;" />
<AlternativeType Name="AZStd::unordered_multiset&lt;*&gt;" />
<DisplayString>hash_map[{m_data.m_list.m_numElements}]</DisplayString>
<Expand>
<Item Name="elements">m_data.m_list</Item>
<Item Name="load factor" Condition="m_data.m_numBuckets > 0">((float)m_data.m_list.m_numElements / (float)m_data.m_numBuckets)</Item>
<Item Name="max load factor">m_data.m_max_load_factor</Item>
<Item Name="buckets">m_data.m_vector</Item>
</Expand>
</Type>
<!-- -->
<Type Name="AZStd::basic_string&lt;char,*&gt;">
<DisplayString Condition="m_capacity &lt; SSO_BUF_SIZE">{m_buffer,s}</DisplayString>
<DisplayString Condition="m_capacity &gt;= SSO_BUF_SIZE">{m_data,s}</DisplayString>
<StringView Condition="m_capacity &lt; SSO_BUF_SIZE">m_buffer,s</StringView>
<StringView Condition="m_capacity &gt;= SSO_BUF_SIZE">m_data,s</StringView>
<Expand>
<Item Name="[size]">m_size</Item>
<Item Name="[capacity]">m_capacity</Item>
<ArrayItems>
<Size>m_size</Size>
<ValuePointer Condition="m_capacity &lt; SSO_BUF_SIZE">m_buffer</ValuePointer>
<ValuePointer Condition="m_capacity &gt;= SSO_BUF_SIZE">m_data</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="AZStd::basic_string&lt;wchar_t,*&gt;">
<AlternativeType Name="AZStd::basic_string&lt;unsigned short,*&gt;" />
<DisplayString Condition="m_capacity &lt; SSO_BUF_SIZE">{m_buffer,su}</DisplayString>
<DisplayString Condition="m_capacity &gt;= SSO_BUF_SIZE">{m_data,su}</DisplayString>
<StringView Condition="m_capacity &lt; SSO_BUF_SIZE">m_buffer,su</StringView>
<StringView Condition="m_capacity &gt;= SSO_BUF_SIZE">m_data,su</StringView>
<Expand>
<Item Name="[size]">m_size</Item>
<Item Name="[capacity]">m_capacity</Item>
<ArrayItems>
<Size>m_size</Size>
<ValuePointer Condition="m_capacity &lt; SSO_BUF_SIZE">m_buffer</ValuePointer>
<ValuePointer Condition="m_capacity &gt;= SSO_BUF_SIZE">m_data</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="AZStd::basic_fixed_string&lt;char,*,*&gt;">
<DisplayString>{m_buffer,s}</DisplayString>
<StringView>m_buffer,s</StringView>
<Expand>
<Item Name="[size]">m_size</Item>
<Item Name="[capacity]">$T1</Item>
<ArrayItems>
<Size>m_size</Size>
<ValuePointer>m_buffer</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="AZStd::basic_fixed_string&lt;wchar_t,*,*&gt;">
<DisplayString>{m_buffer,su}</DisplayString>
<StringView >m_buffer,su</StringView>
<Expand>
<Item Name="[size]">m_size</Item>
<Item Name="[capacity]">$T1</Item>
<ArrayItems>
<Size>m_size</Size>
<ValuePointer>m_buffer</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="AZStd::basic_string_view&lt;char,*&gt;">
<DisplayString Condition="m_size == 0">""</DisplayString>
<DisplayString Condition="m_size != 0">{m_begin,[m_size]}</DisplayString>
<StringView Condition="m_size == 0">""</StringView>
<StringView Condition="m_size != 0">m_begin,[m_size]</StringView>
<Expand>
<Item Name="[size]">m_size</Item>
<ArrayItems>
<Size>m_size</Size>
<ValuePointer>m_begin</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="AZStd::basic_string_view&lt;wchar_t,*&gt;">
<AlternativeType Name="AZStd::basic_string_view&lt;unsigned short,*&gt;" />
<DisplayString Condition="m_size == 0">L""</DisplayString>
<DisplayString Condition="m_size != 0">{m_begin,[m_size]su}</DisplayString>
<StringView Condition="m_size == 0">L""</StringView>
<StringView Condition="m_size != 0">m_begin,[m_size]su</StringView>
<Expand>
<Item Name="[size]">m_size</Item>
<ArrayItems>
<Size>m_size</Size>
<ValuePointer>m_begin</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="AZStd::reference_wrapper&lt;*&gt;">
<DisplayString>{m_t}</DisplayString>
<Expand>
<ExpandedItem>m_t</ExpandedItem>
</Expand>
</Type>
<Type Name="AZStd::plus&lt;*&gt;">
<DisplayString>plus</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::minus&lt;*&gt;">
<DisplayString>minus</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::multiplies&lt;*&gt;">
<DisplayString>multiplies</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::divides&lt;*&gt;">
<DisplayString>divides</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::modulus&lt;*&gt;">
<DisplayString>modulus</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::negate&lt;*&gt;">
<DisplayString>negate</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::equal_to&lt;*&gt;">
<DisplayString>equal_to</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::not_equal_to&lt;*&gt;">
<DisplayString>not_equal_to</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::greater&lt;*&gt;">
<DisplayString>greater</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::less&lt;*&gt;">
<DisplayString>less</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::greater_equal&lt;*&gt;">
<DisplayString>greater_equal</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::less_equal&lt;*&gt;">
<DisplayString>less_equal</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::logical_and&lt;*&gt;">
<DisplayString>logical_and</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::logical_or&lt;*&gt;">
<DisplayString>logical_or</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::logical_not&lt;*&gt;">
<DisplayString>logical_not</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::bit_and&lt;*&gt;">
<DisplayString>bit_and</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::bit_or&lt;*&gt;">
<DisplayString>bit_or</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::bit_xor&lt;*&gt;">
<DisplayString>bit_xor</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::identity&lt;*&gt;">
<DisplayString>identity</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::unary_negate&lt;*&gt;">
<DisplayString>not1({m_functor})</DisplayString>
<Expand>
<Item Name="[pred]">m_functor</Item>
</Expand>
</Type>
<Type Name="AZStd::binary_negate&lt;*&gt;">
<DisplayString>not2({m_functor})</DisplayString>
<Expand>
<Item Name="[pred]">m_functor</Item>
</Expand>
</Type>
<!-- Implementation without custom types added to the code or plug-ins, displays the UUID as 4 32 bit variables -->
<Type Name="AZ::Uuid">
<DisplayString>{((((int)data[3] &amp; 0xFF)) + (((int)data[2] &amp; 0xFF) &lt;&lt; 8) + (((int)data[1] &amp; 0xFF) &lt;&lt; 16) + (((int)data[0] &amp; 0xFF) &lt;&lt; 24)),X} - {((((int)data[7] &amp; 0xFF)) + (((int)data[6] &amp; 0xFF) &lt;&lt; 8) + (((int)data[5] &amp; 0xFF) &lt;&lt; 16) + (((int)data[4] &amp; 0xFF) &lt;&lt; 24)),X} - {((((int)data[11] &amp; 0xFF)) + (((int)data[10] &amp; 0xFF) &lt;&lt; 8) + (((int)data[9] &amp; 0xFF) &lt;&lt; 16) + (((int)data[8] &amp; 0xFF) &lt;&lt; 24)),X} - {((((int)data[15] &amp; 0xFF)) + (((int)data[14] &amp; 0xFF) &lt;&lt; 8) + (((int)data[13] &amp; 0xFF) &lt;&lt; 16) + (((int)data[12] &amp; 0xFF) &lt;&lt; 24)),X}</DisplayString>
</Type>
<Type Name="AZ::EntityId">
<DisplayString>{m_id}</DisplayString>
<Expand>
<Item Name="MonotonicCount">static_cast &lt; unsigned int &gt; (m_id &gt;&gt; 32)</Item>
<Item Name="ProcessSignature">static_cast &lt; unsigned int &gt; (m_id &amp; 0xFFFFFFFF)</Item>
</Expand>
</Type>
<Type Name="AZ::Outcome&lt;*&gt;">
<DisplayString Condition="m_isSuccess" >{{Value = {*(SuccessType*)&amp;m_success}}}</DisplayString>
<DisplayString Condition="!m_isSuccess">{{Error = {*(FailureType*)&amp;m_failure}}}</DisplayString>
<Expand>
<Item Name="IsSuccess">m_isSuccess</Item>
<Item Name="Value" Condition="m_isSuccess" >*(SuccessType*)&amp;m_success</Item>
<Item Name="Error" Condition="!m_isSuccess">*(FailureType*)&amp;m_failure</Item>
</Expand>
</Type>
<Type Name="AZ::Internal::OutcomeStorage&lt;void,*&gt;">
<DisplayString>{{void}}</DisplayString>
<Expand />
</Type>
<Type Name="AZ::Internal::OutcomeStorage&lt;*,*&gt;">
<DisplayString>{*($T1*)&amp;m_value}</DisplayString>
<Expand>
<Item Name="Value">*($T1*)&amp;m_value</Item>
</Expand>
</Type>
<Type Name="AZ::EnvironmentVariable&lt;*&gt;">
<DisplayString Condition="m_data != nullptr">{*($T1*)&amp;m_data->m_value}</DisplayString>
<Expand>
<Item Name="Value">*($T1*)&amp;m_data->m_value</Item>
</Expand>
</Type>
<Type Name="AZ::Internal::EnvironmentVariableHolder&lt;*&gt;">
<DisplayString>{*($T1*)&amp;m_value}</DisplayString>
<Expand>
<Item Name="Value">*($T1*)&amp;m_value</Item>
</Expand>
</Type>
<Type Name="AZStd::recursive_mutex">
<DisplayString>{(_RTL_CRITICAL_SECTION*)(&amp;m_mutex)}</DisplayString>
<Expand>
<Item Name="Value">(_RTL_CRITICAL_SECTION*)(&amp;m_mutex)</Item>
</Expand>
</Type>
<Type Name="AZStd::function&lt;*&gt;">
<DisplayString Condition="this-&gt;vtable == 0">empty</DisplayString>
<DisplayString Condition="this-&gt;vtable != 0">{this-&gt;functor.obj_ptr}</DisplayString>
<Expand>
<ExpandedItem Condition="this-&gt;vtable != 0">this-&gt;functor.obj_ptr</ExpandedItem>
</Expand>
</Type>
<Type Name="AZStd::hash&lt;*&gt;">
<DisplayString>hash</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::chrono::duration&lt;*,AZStd::ratio&lt;1,1000000000&gt; &gt;">
<DisplayString>{m_rep} nanoseconds</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::chrono::duration&lt;*,AZStd::ratio&lt;1,1000000&gt; &gt;">
<DisplayString>{m_rep} microseconds</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::chrono::duration&lt;*,AZStd::ratio&lt;1,1000&gt; &gt;">
<DisplayString>{m_rep} milliseconds</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::chrono::duration&lt;*,AZStd::ratio&lt;1,1&gt; &gt;">
<DisplayString>{m_rep} seconds</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::chrono::duration&lt;*,AZStd::ratio&lt;60,1&gt; &gt;">
<DisplayString>{m_rep} minutes</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::chrono::duration&lt;*,AZStd::ratio&lt;3600,1&gt; &gt;">
<DisplayString>{m_rep} hours</DisplayString>
<Expand/>
</Type>
<Type Name="AZStd::nullopt_t">
<DisplayString>nullopt</DisplayString>
</Type>
<Type Name="AZStd::optional&lt;*&gt;">
<Intrinsic Name="has_value" Expression="this-&gt;m_engaged"/>
<Intrinsic Name="value" Expression="this-&gt;m_object"/>
<DisplayString Condition="!has_value()">nullopt</DisplayString>
<DisplayString Condition="has_value()">{value()}</DisplayString>
<Expand>
<Item Condition="has_value()" Name="value">value()</Item>
</Expand>
</Type>
<Type Name="AZStd::variant_detail::alternative_impl&lt;*,*&gt;">
<DisplayString>{m_value}</DisplayString>
</Type>
<Type Name="AZStd::variant&lt;*&gt;">
<Intrinsic Name="index" Expression="(size_t)m_impl.m_index"/>
<DisplayString Condition="index() == AZStd::variant_npos">[valueless]</DisplayString>
<DisplayString Condition="index() == 0" Optional="true"> {{ index={index()}, value={m_impl.m_union_data.m_head} }}</DisplayString>
<DisplayString Condition="index() == 1" Optional="true"> {{ index={index()}, value={m_impl.m_union_data.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 2" Optional="true"> {{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 3" Optional="true"> {{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 4" Optional="true"> {{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 5" Optional="true"> {{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 6" Optional="true"> {{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 7" Optional="true"> {{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 8" Optional="true"> {{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 9" Optional="true"> {{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 10" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 11" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 12" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 13" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 14" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 15" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 16" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 17" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 18" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 19" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 20" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 21" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 22" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 23" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 24" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 25" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 26" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 27" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 28" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 29" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 30" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<DisplayString Condition="index() == 31" Optional="true">{{ index={index()}, value={m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head} }}</DisplayString>
<Expand>
<Item Name="index">index()</Item>
<Item Name="[value]" Condition="index() == 0" Optional="true">m_impl.m_union_data.m_head</Item>
<!-- Do not recurse into variant with more than 32 alternatives -->
<!-- if the variant index is greater than 32 to avoid performance stalls in the visualizer -->
<Item Name="[value]" Condition="index() == 1" Optional="true"> m_impl.m_union_data.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 2" Optional="true"> m_impl.m_union_data.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 3" Optional="true"> m_impl.m_union_data.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 4" Optional="true"> m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 5" Optional="true"> m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 6" Optional="true"> m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 7" Optional="true"> m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 8" Optional="true"> m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 9" Optional="true"> m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 10" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 11" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 12" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 13" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 14" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 15" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 16" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 17" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 18" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 19" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 20" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 21" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 22" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 23" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 24" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 25" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 26" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 27" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 28" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 29" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 30" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
<Item Name="[value]" Condition="index() == 31" Optional="true">m_impl.m_union_data.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_tail.m_head</Item>
</Expand>
</Type>
<Type Name="AZStd::monostate">
<DisplayString>monostate</DisplayString>
</Type>
<Type Name="AZStd::any">
<Intrinsic Name="has_value" Expression="(uint64_t*)(m_typeInfo.m_id.data)[0] != 0 || (uint64_t*)(m_typeInfo.m_id.data)[1] != 0"/>
<Intrinsic Name="rep" Expression="m_typeInfo.m_useHeap"/>
<Intrinsic Name="Is_big" Expression="has_value() &amp;&amp; rep()"/>
<Intrinsic Name="Is_small" Expression="has_value() &amp;&amp; !rep()"/>
<DisplayString Condition="!has_value()">[empty]</DisplayString>
<DisplayString Condition="Is_small()">[not empty (Small)]</DisplayString>
<DisplayString Condition="Is_big()">[not empty (Large)]</DisplayString>
<Expand>
<Synthetic Name="has_value">
<DisplayString>{has_value()}</DisplayString>
</Synthetic>
<Synthetic Name="[representation]" Condition="Is_small()">
<DisplayString>(Small Object)</DisplayString>
</Synthetic>
<Synthetic Name="[representation]" Condition="Is_big()">
<DisplayString>(Dynamic Allocation)</DisplayString>
</Synthetic>
</Expand>
</Type>
<Type Name="AZ::ConsoleFunctorBase">
<DisplayString Condition="m_name != nullptr">{m_name,na}</DisplayString>
<Expand>
<CustomListItems>
<Variable Name="functorNode" InitialValue="this"/>
<Loop>
<Break Condition="functorNode == nullptr"/>
<Item>functorNode-&gt;m_name,na</Item>
<Exec>functorNode = functorNode-&gt;m_next</Exec>
</Loop>
</CustomListItems>
</Expand>
</Type>
<Type Name="AZ::Console">
<DisplayString Condition="m_head != nullptr">{*m_head}</DisplayString>
</Type>
</AutoVisualizer>
@@ -0,0 +1,178 @@
/*
* 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 <AzCore/Debug/Trace.h>
#include <AzCore/base.h>
#include <AzCore/PlatformIncl.h>
#include <AzCore/Debug/TraceMessageBus.h>
#include <AzCore/Debug/TraceMessagesDrillerBus.h>
#include <stdio.h>
namespace AZ
{
#if defined(AZ_ENABLE_DEBUG_TOOLS)
LONG WINAPI ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo);
LPTOP_LEVEL_EXCEPTION_FILTER g_previousExceptionHandler = nullptr;
#endif
const int g_maxMessageLength = 4096;
namespace Debug
{
namespace Platform
{
#if defined(AZ_ENABLE_DEBUG_TOOLS)
bool IsDebuggerPresent()
{
return ::IsDebuggerPresent() ? true : false;
}
void HandleExceptions(bool isEnabled)
{
if (isEnabled)
{
g_previousExceptionHandler = ::SetUnhandledExceptionFilter(&ExceptionHandler);
}
else
{
::SetUnhandledExceptionFilter(g_previousExceptionHandler);
g_previousExceptionHandler = NULL;
}
}
void DebugBreak()
{
__debugbreak();
}
#endif // AZ_ENABLE_DEBUG_TOOLS
void Terminate(int exitCode)
{
TerminateProcess(GetCurrentProcess(), exitCode);
}
void OutputToDebugger(const char* window, const char* message)
{
AZ_UNUSED(window);
#ifdef _UNICODE
wchar_t messageW[g_maxMessageLength];
size_t numCharsConverted;
if (mbstowcs_s(&numCharsConverted, messageW, message, g_maxMessageLength - 1) == 0)
{
OutputDebugStringW(messageW);
}
#else // !_UNICODE
OutputDebugString(message);
#endif // !_UNICODE
}
}
}
#if defined(AZ_ENABLE_DEBUG_TOOLS)
const char* GetExeptionName(DWORD code)
{
#define RETNAME(exc) case exc: \
return (#exc);
switch (code)
{
RETNAME(EXCEPTION_ACCESS_VIOLATION);
RETNAME(EXCEPTION_ARRAY_BOUNDS_EXCEEDED);
RETNAME(EXCEPTION_BREAKPOINT);
RETNAME(EXCEPTION_DATATYPE_MISALIGNMENT);
RETNAME(EXCEPTION_FLT_DENORMAL_OPERAND);
RETNAME(EXCEPTION_FLT_DIVIDE_BY_ZERO);
RETNAME(EXCEPTION_FLT_INEXACT_RESULT);
RETNAME(EXCEPTION_FLT_INVALID_OPERATION);
RETNAME(EXCEPTION_FLT_OVERFLOW);
RETNAME(EXCEPTION_FLT_STACK_CHECK);
RETNAME(EXCEPTION_FLT_UNDERFLOW);
RETNAME(EXCEPTION_ILLEGAL_INSTRUCTION);
RETNAME(EXCEPTION_IN_PAGE_ERROR);
RETNAME(EXCEPTION_INT_DIVIDE_BY_ZERO);
RETNAME(EXCEPTION_INT_OVERFLOW);
RETNAME(EXCEPTION_INVALID_DISPOSITION);
RETNAME(EXCEPTION_NONCONTINUABLE_EXCEPTION);
RETNAME(EXCEPTION_PRIV_INSTRUCTION);
RETNAME(EXCEPTION_SINGLE_STEP);
RETNAME(EXCEPTION_STACK_OVERFLOW);
RETNAME(EXCEPTION_INVALID_HANDLE);
default:
return (char*)("Unknown exception");
}
#undef RETNAME
}
// Defined in Trace.cpp
namespace DebugInternal
{
extern AZ_THREAD_LOCAL bool g_suppressEBusCalls; // used when it would be dangerous to use ebus broadcasts.
}
extern void* g_exceptionInfo;
LONG WINAPI ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
{
static bool volatile isInExeption = false;
if (isInExeption)
{
// prevent g_tracer from calling the tracebus:
DebugInternal::g_suppressEBusCalls = true;
Debug::Trace::Instance().Output(nullptr, "Exception handler loop!");
Debug::Trace::Instance().PrintCallstack(nullptr, 0, ExceptionInfo->ContextRecord);
DebugInternal::g_suppressEBusCalls = false;
if (Debug::Trace::Instance().IsDebuggerPresent())
{
Debug::Trace::Instance().Break();
}
else
{
_exit(ExceptionInfo->ExceptionRecord->ExceptionCode); // do not proceed any further. note that this is expected to terminate immediately. exit without the underscore may still execute code.
}
}
isInExeption = true;
g_exceptionInfo = (void*)ExceptionInfo;
char message[g_maxMessageLength];
Debug::Trace::Instance().Output(nullptr, "==================================================================\n");
azsnprintf(message, g_maxMessageLength, "Exception : 0x%X - '%s' [%p]\n", ExceptionInfo->ExceptionRecord->ExceptionCode, GetExeptionName(ExceptionInfo->ExceptionRecord->ExceptionCode), ExceptionInfo->ExceptionRecord->ExceptionAddress);
Debug::Trace::Instance().Output(nullptr, message);
EBUS_EVENT(Debug::TraceMessageDrillerBus, OnException, message);
bool result = false;
EBUS_EVENT_RESULT(result, Debug::TraceMessageBus, OnException, message);
if (result)
{
Debug::Trace::Instance().Output(nullptr, "==================================================================\n");
g_exceptionInfo = NULL;
// if someone ever returns TRUE we assume that they somehow handled this exception and continue.
return EXCEPTION_CONTINUE_EXECUTION;
}
Debug::Trace::Instance().PrintCallstack(nullptr, 0, ExceptionInfo->ContextRecord);
Debug::Trace::Instance().Output(nullptr, "==================================================================\n");
// allowing continue of execution is not valid here. This handler gets called for serious exceptions.
// programs wanting things like a message box can implement them on a case-by-case basis, but we want no such
// default behavior - this code is used in automated build systems and UI applications alike.
LONG lReturn = EXCEPTION_CONTINUE_SEARCH;
isInExeption = false;
g_exceptionInfo = NULL;
return lReturn;
}
#endif
}
@@ -0,0 +1,107 @@
/*
* 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 <utility>
#include <AzCore/Casting/numeric_cast.h>
#include <../Common/WinAPI/AzCore/IO/Streamer/StreamerContext_WinAPI.h>
#include <AzCore/Debug/Profiler.h>
namespace AZ::Platform
{
StreamerContextThreadSync::StreamerContextThreadSync()
{
for (size_t i = 0; i < MAXIMUM_WAIT_OBJECTS; ++i)
{
HANDLE event = CreateEvent(nullptr, true, false, nullptr);
if (event)
{
m_events[i] = event;
}
else
{
DWORD error = ::GetLastError();
AZ_Assert(event, "Failed to create a required event for IO Scheduler (Error: %u).", error);
}
}
}
StreamerContextThreadSync::~StreamerContextThreadSync()
{
for (size_t i = 0; i < MAXIMUM_WAIT_OBJECTS; ++i)
{
HANDLE event = m_events[i];
if (event)
{
if (!::CloseHandle(event))
{
DWORD error = ::GetLastError();
AZ_Assert(false, "Failed to close an event handle for IO Scheduler (Error: %u)", error);
}
}
}
}
void StreamerContextThreadSync::Suspend()
{
AZ_Assert(m_events[0], "There is no synchronization event created for the main streamer thread to use to suspend.");
DWORD result = ::WaitForMultipleObjects(m_handleCount, m_events, false, INFINITE);
if (result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + m_handleCount)
{
DWORD index = result - WAIT_OBJECT_0;
::ResetEvent(m_events[index]);
}
else
{
AZ_Assert(false, "Unexpected wait result: %u.", result);
}
}
void StreamerContextThreadSync::Resume()
{
AZ_Assert(m_events[0], "There is no synchronization event created for the main streamer thread to use to resume.");
::SetEvent(m_events[0]);
}
HANDLE StreamerContextThreadSync::CreateEventHandle()
{
AZ_Assert(m_handleCount < MAXIMUM_WAIT_OBJECTS, "There are no more slots available to allocate a new IO event in.");
return m_events[m_handleCount++];
}
void StreamerContextThreadSync::DestroyEventHandle(HANDLE event)
{
AZ_Assert(m_handleCount > 1, "There are no more IO events that can be destroyed.");
for (size_t i = 1; i < m_handleCount; ++i)
{
if (m_events[i] == event)
{
m_handleCount--;
AZStd::swap(m_events[i], m_events[m_handleCount]);
return;
}
}
AZ_Assert(false, "IO event couldn't be destroyed as it wasn't found.");
}
DWORD StreamerContextThreadSync::GetEventHandleCount() const
{
return m_handleCount - 1;
}
bool StreamerContextThreadSync::AreEventHandlesAvailable() const
{
return m_handleCount < MAXIMUM_WAIT_OBJECTS;
}
} // namespace AZ::Platform
@@ -0,0 +1,44 @@
/*
* 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/PlatformIncl.h>
#include <AzCore/base.h>
namespace AZ::Platform
{
class StreamerContextThreadSync
{
public:
static constexpr size_t MaxIoEvents = MAXIMUM_WAIT_OBJECTS - 1;
StreamerContextThreadSync();
~StreamerContextThreadSync();
void Suspend();
void Resume();
HANDLE CreateEventHandle();
void DestroyEventHandle(HANDLE event);
DWORD GetEventHandleCount() const;
bool AreEventHandlesAvailable() const;
private:
// Note: The first event handle is reserved for the synchronization of the
// scheduler thread with the rest of the engine. The remaining event handles
// can be freely used by Streamer's internals.
HANDLE m_events[MAXIMUM_WAIT_OBJECTS]{};
DWORD m_handleCount{ 1 }; // The first event is for external wake up calls.
};
} // namespace AZ::Platform
@@ -0,0 +1,695 @@
/*
* 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 <AzCore/IO/SystemFile.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/IO/FileIOEventBus.h>
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/PlatformIncl.h>
#include <AzCore/Utils/Utils.h>
#include <stdio.h>
namespace AZ::IO
{
namespace
{
//=========================================================================
// GetAttributes
// Internal utility to avoid code duplication. Returns result of win32
// GetFileAttributes
//=========================================================================
DWORD GetAttributes(const char* fileName)
{
#ifdef _UNICODE
wchar_t fileNameW[AZ_MAX_PATH_LEN];
size_t numCharsConverted;
if (mbstowcs_s(&numCharsConverted, fileNameW, fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0)
{
return GetFileAttributesW(fileNameW);
}
else
{
return INVALID_FILE_ATTRIBUTES;
}
#else //!_UNICODE
return GetFileAttributes(fileName);
#endif // !_UNICODE
}
//=========================================================================
// SetAttributes
// Internal utility to avoid code duplication. Returns result of win32
// SetFileAttributes
//=========================================================================
BOOL SetAttributes(const char* fileName, DWORD fileAttributes)
{
#ifdef _UNICODE
wchar_t fileNameW[AZ_MAX_PATH_LEN];
size_t numCharsConverted;
if (mbstowcs_s(&numCharsConverted, fileNameW, fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0)
{
return SetFileAttributesW(fileNameW, fileAttributes);
}
else
{
return FALSE;
}
#else //!_UNICODE
return SetFileAttributes(fileName, fileAttributes);
#endif // !_UNICODE
}
//=========================================================================
// CreateDirRecursive
// [2/3/2013]
// Internal utility to create a folder hierarchy recursively without
// any additional string copies.
// If this function fails (returns false), the error will be available via:
// * GetLastError() on Windows-like platforms
// * errno on Unix platforms
//=========================================================================
#if defined(_UNICODE)
bool CreateDirRecursive(wchar_t* dirPath)
{
if (CreateDirectoryW(dirPath, nullptr))
{
return true; // Created without error
}
DWORD error = GetLastError();
if (error == ERROR_PATH_NOT_FOUND)
{
// try to create our parent hierarchy
for (size_t i = wcslen(dirPath); i > 0; --i)
{
if (dirPath[i] == L'/' || dirPath[i] == L'\\')
{
wchar_t delimiter = dirPath[i];
dirPath[i] = 0; // null-terminate at the previous slash
bool ret = CreateDirRecursive(dirPath);
dirPath[i] = delimiter; // restore slash
if (ret)
{
// now that our parent is created, try to create again
return CreateDirectoryW(dirPath, nullptr) != 0;
}
return false;
}
}
// if we reach here then there was no parent folder to create, so we failed for other reasons
}
else if (error == ERROR_ALREADY_EXISTS)
{
DWORD attributes = GetFileAttributesW(dirPath);
return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
return false;
}
#else
bool CreateDirRecursive(char* dirPath)
{
if (CreateDirectory(dirPath, nullptr))
{
return true; // Created without error
}
DWORD error = GetLastError();
if (error == ERROR_PATH_NOT_FOUND)
{
// try to create our parent hierarchy
for (size_t i = strlen(dirPath); i > 0; --i)
{
if (dirPath[i] == '/' || dirPath[i] == '\\')
{
char delimiter = dirPath[i];
dirPath[i] = 0; // null-terminate at the previous slash
bool ret = CreateDirRecursive(dirPath);
dirPath[i] = delimiter; // restore slash
if (ret)
{
// now that our parent is created, try to create again
if (CreateDirectory(dirPath, nullptr))
{
return true;
}
DWORD creationError = GetLastError();
if (creationError == ERROR_ALREADY_EXISTS)
{
DWORD attributes = GetFileAttributes(dirPath);
return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
return false;
}
return false;
}
}
// if we reach here then there was no parent folder to create, so we failed for other reasons
}
else if (error == ERROR_ALREADY_EXISTS)
{
DWORD attributes = GetFileAttributes(dirPath);
return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
return false;
}
#endif
static const SystemFile::FileHandleType PlatformSpecificInvalidHandle = INVALID_HANDLE_VALUE;
}
bool SystemFile::PlatformOpen(int mode, int platformFlags)
{
DWORD dwDesiredAccess = 0;
DWORD dwShareMode = FILE_SHARE_READ;
DWORD dwFlagsAndAttributes = platformFlags;
DWORD dwCreationDisposition = OPEN_EXISTING;
bool createPath = false;
if (mode & SF_OPEN_READ_ONLY)
{
dwDesiredAccess |= GENERIC_READ;
// Always open files for reading with file shared write flag otherwise it may result in a sharing violation if
// either some process has already opened the file for writing or if some process will later on try to open the file for writing.
dwShareMode |= FILE_SHARE_WRITE;
}
if (mode & SF_OPEN_READ_WRITE)
{
dwDesiredAccess |= GENERIC_READ;
}
if ((mode & SF_OPEN_WRITE_ONLY) || (mode & SF_OPEN_READ_WRITE) || (mode & SF_OPEN_APPEND))
{
dwDesiredAccess |= GENERIC_WRITE;
}
if ((mode & SF_OPEN_CREATE_NEW))
{
dwCreationDisposition = CREATE_NEW;
createPath = (mode & SF_OPEN_CREATE_PATH) == SF_OPEN_CREATE_PATH;
}
else if ((mode & SF_OPEN_CREATE))
{
dwCreationDisposition = CREATE_ALWAYS;
createPath = (mode & SF_OPEN_CREATE_PATH) == SF_OPEN_CREATE_PATH;
}
else if ((mode & SF_OPEN_TRUNCATE))
{
dwCreationDisposition = TRUNCATE_EXISTING;
}
if (createPath)
{
CreatePath(m_fileName);
}
# ifdef _UNICODE
wchar_t fileNameW[AZ_MAX_PATH_LEN];
size_t numCharsConverted;
m_handle = INVALID_HANDLE_VALUE;
if (mbstowcs_s(&numCharsConverted, fileNameW, m_fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0)
{
m_handle = CreateFileW(fileNameW, dwDesiredAccess, dwShareMode, 0, dwCreationDisposition, dwFlagsAndAttributes, 0);
}
# else //!_UNICODE
m_handle = CreateFile(m_fileName, dwDesiredAccess, dwShareMode, 0, dwCreationDisposition, dwFlagsAndAttributes, 0);
# endif // !_UNICODE
if (m_handle == INVALID_HANDLE_VALUE)
{
EBUS_EVENT(FileIOEventBus, OnError, this, nullptr, (int)GetLastError());
return false;
}
else
{
if (mode & SF_OPEN_APPEND)
{
SetFilePointer(m_handle, 0, NULL, FILE_END);
}
}
return true;
}
void SystemFile::PlatformClose()
{
if (m_handle != PlatformSpecificInvalidHandle)
{
if (!CloseHandle(m_handle))
{
EBUS_EVENT(FileIOEventBus, OnError, this, nullptr, (int)GetLastError());
}
m_handle = INVALID_HANDLE_VALUE;
}
}
const char* SystemFile::GetNullFilename()
{
return "NUL";
}
namespace Platform
{
using FileHandleType = AZ::IO::SystemFile::FileHandleType;
void Seek(FileHandleType handle, const SystemFile* systemFile, SizeType offset, SystemFile::SeekMode mode)
{
if (handle != PlatformSpecificInvalidHandle)
{
DWORD dwMoveMethod = mode;
LARGE_INTEGER distToMove;
distToMove.QuadPart = offset;
if (!SetFilePointerEx(handle, distToMove, 0, dwMoveMethod))
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, (int)GetLastError());
}
}
}
SystemFile::SizeType Tell(FileHandleType handle, const SystemFile* systemFile)
{
if (handle != PlatformSpecificInvalidHandle)
{
LARGE_INTEGER distToMove;
distToMove.QuadPart = 0;
LARGE_INTEGER newFilePtr;
if (!SetFilePointerEx(handle, distToMove, &newFilePtr, FILE_CURRENT))
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, (int)GetLastError());
return 0;
}
return aznumeric_cast<SizeType>(newFilePtr.QuadPart);
}
return 0;
}
bool Eof(FileHandleType handle, const SystemFile* systemFile)
{
if (handle != PlatformSpecificInvalidHandle)
{
LARGE_INTEGER zero;
zero.QuadPart = 0;
LARGE_INTEGER currentFilePtr;
if (!SetFilePointerEx(handle, zero, &currentFilePtr, FILE_CURRENT))
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, (int)GetLastError());
return false;
}
FILE_STANDARD_INFO fileInfo;
if (!GetFileInformationByHandleEx(handle, FileStandardInfo, &fileInfo, sizeof(fileInfo)))
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, (int)GetLastError());
return false;
}
return currentFilePtr.QuadPart == fileInfo.EndOfFile.QuadPart;
}
return false;
}
AZ::u64 ModificationTime(FileHandleType handle, const SystemFile* systemFile)
{
if (handle != PlatformSpecificInvalidHandle)
{
FILE_BASIC_INFO fileInfo;
if (!GetFileInformationByHandleEx(handle, FileBasicInfo, &fileInfo, sizeof(fileInfo)))
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, (int)GetLastError());
return 0;
}
AZ::u64 modTime = aznumeric_cast<AZ::u64>(fileInfo.ChangeTime.QuadPart);
// On exFat filesystems the ChangeTime field will be 0
// Use the LastWriteTime as a failsafe in that case
if (modTime == 0)
{
modTime = aznumeric_cast<AZ::u64>(fileInfo.LastWriteTime.QuadPart);
}
return modTime;
}
return 0;
}
SystemFile::SizeType Read(FileHandleType handle, const SystemFile* systemFile, SizeType byteSize, void* buffer)
{
if (handle != PlatformSpecificInvalidHandle)
{
DWORD dwNumBytesRead = 0;
DWORD nNumberOfBytesToRead = (DWORD)byteSize;
if (!ReadFile(handle, buffer, nNumberOfBytesToRead, &dwNumBytesRead, 0))
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, (int)GetLastError());
return 0;
}
return static_cast<SizeType>(dwNumBytesRead);
}
return 0;
}
SystemFile::SizeType Write(FileHandleType handle, const SystemFile* systemFile, const void* buffer, SizeType byteSize)
{
if (handle != PlatformSpecificInvalidHandle)
{
DWORD dwNumBytesWritten = 0;
DWORD nNumberOfBytesToWrite = (DWORD)byteSize;
if (!WriteFile(handle, buffer, nNumberOfBytesToWrite, &dwNumBytesWritten, 0))
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, (int)GetLastError());
return 0;
}
return static_cast<SizeType>(dwNumBytesWritten);
}
return 0;
}
void Flush(FileHandleType handle, const SystemFile* systemFile)
{
if (handle != PlatformSpecificInvalidHandle)
{
if (!FlushFileBuffers(handle))
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, (int)GetLastError());
}
}
}
SystemFile::SizeType Length(FileHandleType handle, const SystemFile* systemFile)
{
if (handle != PlatformSpecificInvalidHandle)
{
LARGE_INTEGER size;
if (!GetFileSizeEx(handle, &size))
{
EBUS_EVENT(FileIOEventBus, OnError, systemFile, nullptr, (int)GetLastError());
return 0;
}
return static_cast<SizeType>(size.QuadPart);
}
return 0;
}
bool Exists(const char* fileName)
{
return GetAttributes(fileName) != INVALID_FILE_ATTRIBUTES;
}
void FindFiles(const char* filter, SystemFile::FindFileCB cb)
{
WIN32_FIND_DATA fd;
HANDLE hFile;
int lastError;
#ifdef _UNICODE
wchar_t filterW[AZ_MAX_PATH_LEN];
size_t numCharsConverted;
hFile = INVALID_HANDLE_VALUE;
if (mbstowcs_s(&numCharsConverted, filterW, filter, AZ_ARRAY_SIZE(filterW) - 1) == 0)
{
hFile = FindFirstFile(filterW, &fd);
}
#else // !_UNICODE
hFile = FindFirstFile(filter, &fd);
#endif // !_UNICODE
if (hFile != INVALID_HANDLE_VALUE)
{
const char* fileName;
#ifdef _UNICODE
char fileNameA[AZ_MAX_PATH_LEN];
fileName = NULL;
if (wcstombs_s(&numCharsConverted, fileNameA, fd.cFileName, AZ_ARRAY_SIZE(fileNameA) - 1) == 0)
{
fileName = fileNameA;
}
#else // !_UNICODE
fileName = fd.cFileName;
#endif // !_UNICODE
cb(fileName, (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0);
// List all the other files in the directory.
while (FindNextFile(hFile, &fd) != 0)
{
#ifdef _UNICODE
fileName = NULL;
if (wcstombs_s(&numCharsConverted, fileNameA, fd.cFileName, AZ_ARRAY_SIZE(fileNameA) - 1) == 0)
{
fileName = fileNameA;
}
#else // !_UNICODE
fileName = fd.cFileName;
#endif // !_UNICODE
cb(fileName, (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0);
}
lastError = (int)GetLastError();
FindClose(hFile);
if (lastError != ERROR_NO_MORE_FILES)
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, fileName, lastError);
}
}
else
{
lastError = (int)GetLastError();
if (lastError != ERROR_FILE_NOT_FOUND)
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, filter, lastError);
}
}
}
AZ::u64 ModificationTime(const char* fileName)
{
HANDLE handle = nullptr;
#ifdef _UNICODE
wchar_t fileNameW[AZ_MAX_PATH_LEN];
size_t numCharsConverted;
if (mbstowcs_s(&numCharsConverted, fileNameW, fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0)
{
handle = CreateFileW(fileNameW, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
}
#else // !_UNICODE
handle = CreateFileA(fileName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
#endif // !_UNICODE
if (handle == INVALID_HANDLE_VALUE)
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, fileName, (int)GetLastError());
return 0;
}
FILE_BASIC_INFO fileInfo{};
if (!GetFileInformationByHandleEx(handle, FileBasicInfo, &fileInfo, sizeof(fileInfo)))
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, fileName, (int)GetLastError());
}
CloseHandle(handle);
// On exFat filesystems the ChangeTime field will be 0
// Use the LastWriteTime as a failsafe in that case
if (fileInfo.ChangeTime.QuadPart == 0)
{
return aznumeric_cast<AZ::u64>(fileInfo.LastWriteTime.QuadPart);
}
return aznumeric_cast<AZ::u64>(fileInfo.ChangeTime.QuadPart);
}
SystemFile::SizeType Length(const char* fileName)
{
SizeType len = 0;
WIN32_FILE_ATTRIBUTE_DATA data = { 0 };
BOOL result = FALSE;
#ifdef _UNICODE
wchar_t fileNameW[AZ_MAX_PATH_LEN];
size_t numCharsConverted;
if (mbstowcs_s(&numCharsConverted, fileNameW, fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0)
{
result = GetFileAttributesExW(fileNameW, GetFileExInfoStandard, &data);
}
#else // !_UNICODE
result = GetFileAttributesExA(fileName, GetFileExInfoStandard, &data);
#endif // !_UNICODE
if (result)
{
// Convert hi/lo parts to a SizeType
LARGE_INTEGER fileSize;
fileSize.LowPart = data.nFileSizeLow;
fileSize.HighPart = data.nFileSizeHigh;
len = aznumeric_cast<SizeType>(fileSize.QuadPart);
}
else
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, fileName, (int)GetLastError());
}
return len;
}
bool Delete(const char* fileName)
{
#ifdef _UNICODE
wchar_t fileNameW[AZ_MAX_PATH_LEN];
size_t numCharsConverted;
if (mbstowcs_s(&numCharsConverted, fileNameW, fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0)
{
if (DeleteFileW(fileNameW) == 0)
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, fileName, (int)GetLastError());
return false;
}
}
else
{
return false;
}
#else // !_UNICODE
if (DeleteFile(fileName) == 0)
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, fileName, (int)GetLastError());
return false;
}
#endif // !_UNICODE
return true;
}
bool Rename(const char* sourceFileName, const char* targetFileName, bool overwrite)
{
#ifdef _UNICODE
wchar_t sourceFileNameW[AZ_MAX_PATH_LEN];
wchar_t targetFileNameW[AZ_MAX_PATH_LEN];
size_t numCharsConverted;
if (mbstowcs_s(&numCharsConverted, sourceFileNameW, sourceFileName, AZ_ARRAY_SIZE(sourceFileNameW) - 1) == 0 &&
mbstowcs_s(&numCharsConverted, targetFileNameW, targetFileName, AZ_ARRAY_SIZE(targetFileNameW) - 1) == 0)
{
if (MoveFileExW(sourceFileNameW, targetFileNameW, overwrite ? MOVEFILE_REPLACE_EXISTING : 0) == 0)
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, sourceFileName, (int)GetLastError());
return false;
}
}
else
{
return false;
}
#else // !_UNICODE
if (MoveFileEx(sourceFileName, targetFileName, overwrite ? MOVEFILE_REPLACE_EXISTING : 0) == 0)
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, sourceFileName, (int)GetLastError());
return false;
}
#endif // !_UNICODE
return true;
}
bool IsWritable(const char* sourceFileName)
{
auto fileAttr = GetAttributes(sourceFileName);
return !((fileAttr == INVALID_FILE_ATTRIBUTES) || (fileAttr & FILE_ATTRIBUTE_DIRECTORY) || (fileAttr & FILE_ATTRIBUTE_READONLY));
}
bool SetWritable(const char* sourceFileName, bool writable)
{
auto fileAttr = GetAttributes(sourceFileName);
if ((fileAttr == INVALID_FILE_ATTRIBUTES) || (fileAttr & FILE_ATTRIBUTE_DIRECTORY))
{
return false;
}
if (writable)
{
fileAttr = fileAttr & (~FILE_ATTRIBUTE_READONLY);
}
else
{
fileAttr = fileAttr | (FILE_ATTRIBUTE_READONLY);
}
auto success = SetAttributes(sourceFileName, fileAttr);
return success != FALSE;
}
bool CreateDir(const char* dirName)
{
if (dirName)
{
#if defined(_UNICODE)
wchar_t dirPath[AZ_MAX_PATH_LEN];
size_t numCharsConverted;
if (mbstowcs_s(&numCharsConverted, dirPath, dirName, AZ_ARRAY_SIZE(dirPath) - 1) == 0)
{
bool success = CreateDirRecursive(dirPath);
if (!success)
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, dirName, (int)GetLastError());
}
return success;
}
#else
char dirPath[AZ_MAX_PATH_LEN];
if (azstrcpy(dirPath, AZ_ARRAY_SIZE(dirPath), dirName) == 0)
{
bool success = CreateDirRecursive(dirPath);
if (!success)
{
EBUS_EVENT(FileIOEventBus, OnError, nullptr, dirName, (int)GetLastError());
}
return success;
}
#endif
}
return false;
}
bool DeleteDir(const char* dirName)
{
if (dirName)
{
#if defined(_UNICODE)
wchar_t dirNameW[AZ_MAX_PATH_LEN];
size_t numCharsConverted;
if (mbstowcs_s(&numCharsConverted, dirNameW, dirName, AZ_ARRAY_SIZE(dirNameW) - 1) == 0)
{
return RemoveDirectory(dirNameW) != 0;
}
#else
return RemoveDirectory(dirName) != 0;
#endif
}
return false;
}
}
} // namespace AZ::IO
@@ -0,0 +1,111 @@
/*
* 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 <fcntl.h>
#include <corecrt_io.h>
namespace AZ
{
namespace IO
{
namespace Internal
{
using SizeType = AZ::u64;
using FileHandleType = void*;
}
namespace PosixInternal
{
enum class OpenFlags : int
{
Append = _O_APPEND, // Moves the file pointer to the end of the file before every write operation.
Create = _O_CREAT, // Creates a file and opens it for writing. Has no effect if the file specified by filename exists. PermissionMode is required.
Temporary = _O_TEMPORARY, // Applies only when used with CREAT. Creates a file as temporary; the file is deleted when the last file descriptor is closed. PermissionMode equired when CREAT is specified.
Exclusive = _O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
Truncate = _O_TRUNC, // Opens a file and truncates it to zero length; the file must have write permission. Cannot be specified with RDONLY.
// Note: The TRUNC flag destroys the contents of the specified file.
ReadOnly = _O_RDONLY, // Opens a file for reading only. Cannot be specified with RDWR or WRONLY.
WriteOnly = _O_WRONLY, // Opens a file for writing only. Cannot be specified with RDONLY or RDWR.
ReadWrite = _O_RDWR, // Opens a file for both reading and writing. Cannot be specified with RDONLY or WRONLY.
// Windows-specific
NoInherit = _O_NOINHERIT, // Prevents creation of a shared file descriptor.
Random = _O_RANDOM, // Specifies that caching is optimized for, but not restricted to, random access from disk.
Sequential = _O_SEQUENTIAL, // Specifies that caching is optimized for, but not restricted to, sequential access from disk.
Binary = _O_BINARY, // Opens the file in binary(untranslated) mode. (See fopen for a description of binary mode.)
Text = _O_TEXT, // Opens a file in text(translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.)
U16Text = _O_U16TEXT, // Opens a file in Unicode UTF-16 mode.
U8Text = _O_U8TEXT, // Opens a file in Unicode UTF-8 mode.
WText = _O_WTEXT, // Opens a file in Unicode mode.
// Unix-specific
Async = 0, // (Not applicable in windows) Enable signal-driven I/O: generate a signal (SIGIO by default, but this can be changed via fcntl(2)) when input or output becomes possible on this file descriptor. This feature is available only for terminals, pseudoterminals, sockets, and (since Linux 2.6) pipes and FIFOs.
Direct = 0, // (Not applicable in windows) Try to minimize cache effects of the I/O to and from this file. In general this will degrade performance, but it is useful in special situations, such as when applications do their own caching.
Directory = 0, // (Not applicable in windows) If pathname is not a directory, cause the open to fail.
NoFollow = 0, // (Not applicable in windows) If the trailing component (i.e., basename) of pathname is a symbolic link, then the open fails, with the error ELOOP. Symbolic links in earlier components of the pathname will still be followed.
NoAccessTime = 0, // (Not applicable in windows) Do not update the file last access time.
Path = 0, // (Not applicable in windows) Obtain a file descriptor that can be used for two purposes: to indicate a location in the filesystem tree and to perform operations that act purely at the file descriptor level.
};
AZ_DEFINE_ENUM_BITWISE_OPERATORS(OpenFlags);
enum class PermissionModeFlags : int
{
None = 0,
Read = _S_IREAD,
Write = _S_IWRITE
};
AZ_DEFINE_ENUM_BITWISE_OPERATORS(PermissionModeFlags);
inline int Open(const char* const fileName, OpenFlags openFlags, PermissionModeFlags newFilePermissions = PermissionModeFlags::None)
{
int fileDescriptor = -1;
int shareAccess = _SH_DENYNO; // < Deny nothing, allowing read/write sharing
errno_t result = _sopen_s(&fileDescriptor, fileName, static_cast<int>(openFlags), shareAccess, static_cast<int>(newFilePermissions));
if (result == 0)
{
return fileDescriptor;
}
else
{
return -1;
}
}
inline int Close(int fileDescriptor)
{
return _close(fileDescriptor);
}
inline int Read(int fileDescriptor, void* data, unsigned int size)
{
return _read(fileDescriptor, data, size);
}
inline int Write(int fileDescriptor, const void* data, unsigned int size)
{
return _write(fileDescriptor, data, size);
}
inline int Dup(int fileDescriptor)
{
return _dup(fileDescriptor);
}
inline int Dup2(int fileDescriptorSource, int fileDescriptorDestination)
{
return _dup2(fileDescriptorSource, fileDescriptorDestination);
}
} // namespace AZ::IO::PosixInternal
} // namespace AZ::IO
} // namespace AZ
@@ -0,0 +1,15 @@
/*
* 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_OS_MALLOC(byteSize, alignment) _aligned_malloc(byteSize, alignment)
#define AZ_OS_FREE(pointer) _aligned_free(pointer)
@@ -0,0 +1,78 @@
/*
* 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 <AzCore/Memory/OverrunDetectionAllocator.h>
namespace AZ
{
namespace Internal
{
static const int ODS_PAGE_SIZE = 4096;
static const int ODS_PAGE_SHIFT = 12;
static const int ODS_PAGES_PER_ALLOCATION = 16;
static const int ODS_PAGES_PER_ALLOCATION_SHIFT = 4;
static const int ODS_ALLOCATION_SIZE = ODS_PAGE_SIZE * ODS_PAGES_PER_ALLOCATION;
class WinAPIOverrunDetectionSchema : public OverrunDetectionSchema::PlatformAllocator
{
public:
virtual SystemInformation GetSystemInformation() override
{
SystemInformation result;
SYSTEM_INFO info;
GetSystemInfo(&info);
result.m_pageSize = info.dwPageSize;
result.m_minimumAllocationSize = info.dwAllocationGranularity;
return result;
}
virtual void* ReserveBytes(size_t amount) override
{
void* result = VirtualAlloc(0, amount, MEM_RESERVE, PAGE_NOACCESS);
if (!result)
{
// Out of memory
AZ_Crash();
}
return result;
}
virtual void ReleaseReservedBytes(void* base) override
{
VirtualFree(base, 0, MEM_RELEASE);
}
virtual void* CommitBytes(void* base, size_t amount) override
{
void* result = VirtualAlloc(base, amount, MEM_COMMIT, PAGE_READWRITE);
if (!result)
{
// Out of memory
AZ_Crash();
}
return result;
}
virtual void DecommitBytes(void* base, size_t amount) override
{
VirtualFree(base, amount, MEM_DECOMMIT);
}
};
using PlatformOverrunDetectionSchema = WinAPIOverrunDetectionSchema;
}
}
@@ -0,0 +1,140 @@
/*
* 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 <AzCore/IO/Path/Path.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/Module/DynamicModuleHandle.h>
#include <AzCore/Memory/OSAllocator.h>
#include <AzCore/PlatformIncl.h>
#include <AzCore/Utils/Utils.h>
namespace AZ
{
class DynamicModuleHandleWindows
: public DynamicModuleHandle
{
public:
AZ_CLASS_ALLOCATOR(DynamicModuleHandleWindows, OSAllocator, 0)
DynamicModuleHandleWindows(const char* fullFileName)
: DynamicModuleHandle(fullFileName)
, m_handle(nullptr)
{
// Ensure filename ends in ".dll"
// Otherwise filenames like "gem.1.0.0" fail to load (.0 is assumed to be the extension).
if (m_fileName.substr(m_fileName.length() - 4) != AZ_TRAIT_OS_DYNAMIC_LIBRARY_EXTENSION)
{
m_fileName = m_fileName + AZ_TRAIT_OS_DYNAMIC_LIBRARY_EXTENSION;
}
AZ::IO::PathView modulePathView{ m_fileName };
// If the module path doesn't have a directory within it, prepend it to the path
// and check if the new path exist
if (modulePathView.HasFilename() && !modulePathView.HasParentPath())
{
char exeDirectory[AZ::IO::MaxPathLength];
if (AZ::Utils::GetExecutableDirectory(exeDirectory, AZ_ARRAY_SIZE(exeDirectory)) ==
AZ::Utils::ExecutablePathResult::Success)
{
AZ::IO::FixedMaxPath candidatePath = exeDirectory;
candidatePath /= modulePathView;
// Check to see if the module exist before assigning it as the file name
if (AZ::IO::SystemFile::Exists(candidatePath.c_str()))
{
m_fileName.assign(candidatePath.Native().c_str(), candidatePath.Native().size());
}
}
}
}
~DynamicModuleHandleWindows() override
{
Unload();
}
LoadStatus LoadModule() override
{
if (IsLoaded())
{
return LoadStatus::AlreadyLoaded;
}
bool alreadyLoaded = false;
# ifdef _UNICODE
wchar_t fileNameW[MAX_PATH];
size_t numCharsConverted;
errno_t wcharResult = mbstowcs_s(&numCharsConverted, fileNameW, m_fileName.c_str(), AZ_ARRAY_SIZE(fileNameW) - 1);
if (wcharResult == 0)
{
// If module already open, return false, it was not loaded.
alreadyLoaded = NULL != GetModuleHandleW(fileNameW);
m_handle = LoadLibraryW(fileNameW);
}
else
{
AZ_Assert(false, "Failed to convert %s to wchar with error %d!", m_fileName.c_str(), wcharResult);
m_handle = NULL;
return LoadStatus::LoadFailure;
}
# else //!_UNICODE
alreadyLoaded = NULL != GetModuleHandleA(m_fileName.c_str());
m_handle = LoadLibraryA(m_fileName.c_str());
# endif // !_UNICODE
if (m_handle)
{
if (alreadyLoaded)
{
return LoadStatus::AlreadyLoaded;
}
else
{
return LoadStatus::LoadSuccess;
}
}
else
{
return LoadStatus::LoadFailure;
}
}
bool UnloadModule() override
{
bool result = false;
if (m_handle)
{
result = FreeLibrary(m_handle) ? true : false;
m_handle = 0;
}
return result;
}
bool IsLoaded() const override
{
return m_handle ? true : false;
}
void* GetFunctionAddress(const char* functionName) const override
{
return reinterpret_cast<void*>(::GetProcAddress(m_handle, functionName));
}
HMODULE m_handle;
};
// Implement the module creation function
AZStd::unique_ptr<DynamicModuleHandle> DynamicModuleHandle::Create(const char* fullFileName)
{
return AZStd::unique_ptr<DynamicModuleHandle>(aznew DynamicModuleHandleWindows(fullFileName));
}
} // namespace AZ
@@ -0,0 +1,384 @@
/*
* 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 <AzCore/Socket/AzSocket.h>
namespace AZ
{
namespace AzSock
{
AZ::s32 TranslateOSError(AZ::s32 oserror)
{
AZ::s32 error;
#define TRANSLATE(_from, _to) case (_from): error = static_cast<AZ::s32>(_to); break;
switch (oserror)
{
TRANSLATE(0, AzSockError::eASE_NO_ERROR);
TRANSLATE(WSAEACCES, AzSockError::eASE_EACCES);
TRANSLATE(WSAEADDRINUSE, AzSockError::eASE_EADDRINUSE);
TRANSLATE(WSAEADDRNOTAVAIL, AzSockError::eASE_EADDRNOTAVAIL);
TRANSLATE(WSAEAFNOSUPPORT, AzSockError::eASE_EAFNOSUPPORT);
TRANSLATE(WSAEALREADY, AzSockError::eASE_EALREADY);
TRANSLATE(WSAEBADF, AzSockError::eASE_EBADF);
TRANSLATE(WSAECONNABORTED, AzSockError::eASE_ECONNABORTED);
TRANSLATE(WSAECONNREFUSED, AzSockError::eASE_ECONNREFUSED);
TRANSLATE(WSAECONNRESET, AzSockError::eASE_ECONNRESET);
TRANSLATE(WSAEFAULT, AzSockError::eASE_EFAULT);
TRANSLATE(WSAEHOSTDOWN, AzSockError::eASE_EHOSTDOWN);
TRANSLATE(WSAEINPROGRESS, AzSockError::eASE_EINPROGRESS);
TRANSLATE(WSAEINTR, AzSockError::eASE_EINTR);
TRANSLATE(WSAEINVAL, AzSockError::eASE_EINVAL);
TRANSLATE(WSAEISCONN, AzSockError::eASE_EISCONN);
TRANSLATE(WSAEMFILE, AzSockError::eASE_EMFILE);
TRANSLATE(WSAEMSGSIZE, AzSockError::eASE_EMSGSIZE);
TRANSLATE(WSAENETUNREACH, AzSockError::eASE_ENETUNREACH);
TRANSLATE(WSAENOBUFS, AzSockError::eASE_ENOBUFS);
TRANSLATE(WSAENOPROTOOPT, AzSockError::eASE_ENOPROTOOPT);
TRANSLATE(WSAENOTCONN, AzSockError::eASE_ENOTCONN);
TRANSLATE(WSAEOPNOTSUPP, AzSockError::eASE_EOPNOTSUPP);
TRANSLATE(WSAEPROTONOSUPPORT, AzSockError::eASE_EAFNOSUPPORT);
TRANSLATE(WSAETIMEDOUT, AzSockError::eASE_ETIMEDOUT);
TRANSLATE(WSAETOOMANYREFS, AzSockError::eASE_ETOOMANYREFS);
TRANSLATE(WSAEWOULDBLOCK, AzSockError::eASE_EWOULDBLOCK);
// No equivalent in the posix api
TRANSLATE(WSANOTINITIALISED, AzSockError::eASE_ENOTINITIALISED);
default:
AZ_TracePrintf("AzSock", "AzSocket could not translate OS error code %x, treating as miscellaneous.\n", oserror);
error = static_cast<AZ::s32>(AzSockError::eASE_MISC_ERROR);
break;
}
#undef TRANSLATE
return error;
}
AZ::s32 TranslateSocketOption(AzSocketOption opt)
{
AZ::s32 value;
#define TRANSLATE(_from, _to) case (_from): value = (_to); break;
switch (opt)
{
TRANSLATE(AzSocketOption::REUSEADDR, SO_REUSEADDR);
TRANSLATE(AzSocketOption::KEEPALIVE, SO_KEEPALIVE);
TRANSLATE(AzSocketOption::LINGER, SO_LINGER);
default:
AZ_TracePrintf("AzSock", "AzSocket option %x not yet supported", opt);
value = 0;
break;
}
#undef TRANSLATE
return value;
}
AZSOCKET HandleInvalidSocket(SOCKET sock)
{
AZSOCKET azsock = static_cast<AZSOCKET>(sock);
if (sock == INVALID_SOCKET)
{
azsock = TranslateOSError(WSAGetLastError());
}
return azsock;
}
AZ::s32 HandleSocketError(AZ::s32 socketError)
{
if (socketError == SOCKET_ERROR)
{
socketError = TranslateOSError(WSAGetLastError());
}
return socketError;
}
const char* GetStringForError(AZ::s32 errorNumber)
{
AzSockError errorCode = AzSockError(errorNumber);
#define CASE_RETSTRING(errorEnum) case errorEnum: { return #errorEnum; }
switch (errorCode)
{
CASE_RETSTRING(AzSockError::eASE_NO_ERROR);
CASE_RETSTRING(AzSockError::eASE_SOCKET_INVALID);
CASE_RETSTRING(AzSockError::eASE_EACCES);
CASE_RETSTRING(AzSockError::eASE_EADDRINUSE);
CASE_RETSTRING(AzSockError::eASE_EADDRNOTAVAIL);
CASE_RETSTRING(AzSockError::eASE_EAFNOSUPPORT);
CASE_RETSTRING(AzSockError::eASE_EALREADY);
CASE_RETSTRING(AzSockError::eASE_EBADF);
CASE_RETSTRING(AzSockError::eASE_ECONNABORTED);
CASE_RETSTRING(AzSockError::eASE_ECONNREFUSED);
CASE_RETSTRING(AzSockError::eASE_ECONNRESET);
CASE_RETSTRING(AzSockError::eASE_EFAULT);
CASE_RETSTRING(AzSockError::eASE_EHOSTDOWN);
CASE_RETSTRING(AzSockError::eASE_EINPROGRESS);
CASE_RETSTRING(AzSockError::eASE_EINTR);
CASE_RETSTRING(AzSockError::eASE_EINVAL);
CASE_RETSTRING(AzSockError::eASE_EISCONN);
CASE_RETSTRING(AzSockError::eASE_EMFILE);
CASE_RETSTRING(AzSockError::eASE_EMSGSIZE);
CASE_RETSTRING(AzSockError::eASE_ENETUNREACH);
CASE_RETSTRING(AzSockError::eASE_ENOBUFS);
CASE_RETSTRING(AzSockError::eASE_ENOPROTOOPT);
CASE_RETSTRING(AzSockError::eASE_ENOTCONN);
CASE_RETSTRING(AzSockError::eASE_ENOTINITIALISED);
CASE_RETSTRING(AzSockError::eASE_EOPNOTSUPP);
CASE_RETSTRING(AzSockError::eASE_EPIPE);
CASE_RETSTRING(AzSockError::eASE_EPROTONOSUPPORT);
CASE_RETSTRING(AzSockError::eASE_ETIMEDOUT);
CASE_RETSTRING(AzSockError::eASE_ETOOMANYREFS);
CASE_RETSTRING(AzSockError::eASE_EWOULDBLOCK);
CASE_RETSTRING(AzSockError::eASE_EWOULDBLOCK_CONN);
CASE_RETSTRING(AzSockError::eASE_MISC_ERROR);
}
#undef CASE_RETSTRING
return "(invalid)";
}
AZ::u32 HostToNetLong(AZ::u32 hstLong)
{
return htonl(hstLong);
}
AZ::u32 NetToHostLong(AZ::u32 netLong)
{
return ntohl(netLong);
}
AZ::u16 HostToNetShort(AZ::u16 hstShort)
{
return htons(hstShort);
}
AZ::u16 NetToHostShort(AZ::u16 netShort)
{
return ntohs(netShort);
}
AZ::s32 GetHostName(AZStd::string& hostname)
{
AZ::s32 result = 0;
hostname.clear();
char name[256];
result = HandleSocketError(gethostname(name, AZ_ARRAY_SIZE(name)));
if (result == static_cast<AZ::s32>(AzSockError::eASE_NO_ERROR))
{
hostname = name;
}
return result;
}
AZSOCKET Socket()
{
return Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
}
AZSOCKET Socket(AZ::s32 af, AZ::s32 type, AZ::s32 protocol)
{
return HandleInvalidSocket(socket(af, type, protocol));
}
AZ::s32 SetSockOpt(AZSOCKET sock, AZ::s32 level, AZ::s32 optname, const char* optval, AZ::s32 optlen)
{
AZ::s32 length(optlen);
return HandleSocketError(setsockopt(sock, level, optname, optval, length));
}
AZ::s32 SetSocketOption(AZSOCKET sock, AzSocketOption opt, bool enable)
{
AZ::u32 val = enable ? 1 : 0;
return SetSockOpt(sock, SOL_SOCKET, TranslateSocketOption(opt), reinterpret_cast<const char*>(&val), sizeof(val));
}
AZ::s32 EnableTCPNoDelay(AZSOCKET sock, bool enable)
{
AZ::u32 val = enable ? 1 : 0;
return SetSockOpt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<const char*>(&val), sizeof(val));
}
AZ::s32 SetSocketBlockingMode(AZSOCKET sock, bool blocking)
{
u_long val = blocking ? 0 : 1;
return HandleSocketError(ioctlsocket(sock, FIONBIO, &val));
}
AZ::s32 CloseSocket(AZSOCKET sock)
{
return HandleSocketError(closesocket(sock));
}
AZ::s32 Shutdown(AZSOCKET sock, AZ::s32 how)
{
return HandleSocketError(shutdown(sock, how));
}
AZ::s32 GetSockName(AZSOCKET sock, AzSocketAddress& addr)
{
AZSOCKADDR sAddr;
AZ::s32 sAddrLen = sizeof(AZSOCKADDR);
memset(&sAddr, 0, sAddrLen);
AZ::s32 result = HandleSocketError(getsockname(sock, &sAddr, &sAddrLen));
addr = sAddr;
return result;
}
AZ::s32 Connect(AZSOCKET sock, const AzSocketAddress& addr)
{
AZ::s32 err = HandleSocketError(connect(sock, addr.GetTargetAddress(), sizeof(AZSOCKADDR_IN)));
if (err == static_cast<AZ::s32>(AzSockError::eASE_EWOULDBLOCK))
{
err = static_cast<AZ::s32>(AzSockError::eASE_EWOULDBLOCK_CONN);
}
return err;
}
AZ::s32 Listen(AZSOCKET sock, AZ::s32 backlog)
{
return HandleSocketError(listen(sock, backlog));
}
AZSOCKET Accept(AZSOCKET sock, AzSocketAddress& addr)
{
AZSOCKADDR sAddr;
AZ::s32 sAddrLen = sizeof(AZSOCKADDR);
memset(&sAddr, 0, sAddrLen);
AZSOCKET outSock = HandleInvalidSocket(accept(sock, &sAddr, &sAddrLen));
addr = sAddr;
return outSock;
}
AZ::s32 Send(AZSOCKET sock, const char* buf, AZ::s32 len, AZ::s32 flags)
{
return HandleSocketError(send(sock, buf, len, flags));
}
AZ::s32 Recv(AZSOCKET sock, char* buf, AZ::s32 len, AZ::s32 flags)
{
return HandleSocketError(recv(sock, buf, len, flags));
}
AZ::s32 Bind(AZSOCKET sock, const AzSocketAddress& addr)
{
return HandleSocketError(bind(sock, addr.GetTargetAddress(), sizeof(AZSOCKADDR_IN)));
}
AZ::s32 Select(AZSOCKET sock, AZFD_SET* readfdsock, AZFD_SET* writefdsock, AZFD_SET* exceptfdsock, AZTIMEVAL* timeout)
{
return HandleSocketError(::select(sock + 1, readfdsock, writefdsock, exceptfdsock, timeout));
}
AZ::s32 IsRecvPending(AZSOCKET sock, AZTIMEVAL* timeout)
{
AZFD_SET readSet;
FD_ZERO(&readSet);
FD_SET(sock, &readSet);
AZ::s32 ret = Select(sock, &readSet, nullptr, nullptr, timeout);
if (ret >= 0)
{
ret = FD_ISSET(sock, &readSet);
if (ret != 0)
{
ret = 1;
}
}
return ret;
}
AZ::s32 WaitForWritableSocket(AZSOCKET sock, AZTIMEVAL* timeout)
{
AZFD_SET writeSet;
FD_ZERO(&writeSet);
FD_SET(sock, &writeSet);
AZ::s32 ret = Select(sock, nullptr, &writeSet, nullptr, timeout);
if (ret >= 0)
{
ret = FD_ISSET(sock, &writeSet);
if (ret != 0)
{
ret = 1;
}
}
return ret;
}
AZ::s32 Startup()
{
WSAData wsaData;
return TranslateOSError(WSAStartup(MAKEWORD(2, 2), &wsaData));
}
AZ::s32 Cleanup()
{
return TranslateOSError(WSACleanup());
}
bool ResolveAddress(const AZStd::string& ip, AZ::u16 port, AZSOCKADDR_IN& socketAddress)
{
bool foundAddr = false;
addrinfo hints;
memset(&hints, 0, sizeof(addrinfo));
addrinfo* addrInfo;
hints.ai_family = AF_INET;
hints.ai_flags = AI_CANONNAME;
char strPort[8];
azsnprintf(strPort, AZ_ARRAY_SIZE(strPort), "%d", port);
const char* address = ip.c_str();
if (address && strlen(address) == 0) // getaddrinfo doesn't accept empty string
{
address = nullptr;
}
AZ::s32 err = HandleSocketError(getaddrinfo(address, strPort, &hints, &addrInfo));
if (err == 0) // eASE_NO_ERROR
{
if (addrInfo->ai_family == AF_INET)
{
socketAddress = *reinterpret_cast<const AZSOCKADDR_IN*>(addrInfo->ai_addr);
foundAddr = true;
}
freeaddrinfo(addrInfo);
}
else
{
AZ_Assert(false, "AzSocketAddress could not resolve address %s with port %d. (reason - %s)", ip.c_str(), port, GetStringForError(err));
}
return foundAddr;
}
};
}
/**
* Windows platform-specific net modules
*/
#pragma comment(lib, WIN_SOCK_LIB_TO_LINK)
@@ -0,0 +1,20 @@
/*
* 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 <WinSock2.h>
#include <ws2tcpip.h>
#define SD_RECEIVE 0x00
#define SD_SEND 0x01
#define SD_BOTH 0x02
@@ -0,0 +1,16 @@
/*
* 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 sockaddr;
struct sockaddr_in;
@@ -0,0 +1,69 @@
/*
* 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 <AzCore/Utils/Utils.h>
#include <AzCore/PlatformIncl.h>
#include <AzCore/std/optional.h>
#include <AzCore/std/string/fixed_string.h>
#include <stdlib.h>
namespace AZ
{
namespace Utils
{
void RequestAbnormalTermination()
{
abort();
}
GetExecutablePathReturnType GetExecutablePath(char* exeStorageBuffer, size_t exeStorageSize)
{
GetExecutablePathReturnType result;
result.m_pathIncludesFilename = true;
// Platform specific get exe path: http://stackoverflow.com/a/1024937
// https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulefilenamea
const DWORD pathLen = GetModuleFileNameA(nullptr, exeStorageBuffer, static_cast<DWORD>(exeStorageSize));
const DWORD errorCode = GetLastError();
if (pathLen == exeStorageSize && errorCode == ERROR_INSUFFICIENT_BUFFER)
{
result.m_pathStored = ExecutablePathResult::BufferSizeNotLargeEnough;
}
else if (pathLen == 0 && errorCode != ERROR_SUCCESS)
{
result.m_pathStored = ExecutablePathResult::GeneralError;
}
return result;
}
AZStd::optional<AZStd::fixed_string<MaxPathLength>> GetDefaultAppRootPath()
{
return AZStd::nullopt;
}
AZStd::optional<AZStd::fixed_string<MaxPathLength>> ConvertToAbsolutePath(AZStd::string_view path)
{
AZStd::fixed_string<MaxPathLength> absolutePath;
AZStd::fixed_string<MaxPathLength> srcPath{ path };
char* result = _fullpath(absolutePath.data(), srcPath.c_str(), absolutePath.capacity());
// Force update of the fixed_string size() value
absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
if (result)
{
return absolutePath;
}
return AZStd::nullopt;
}
}
}

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