You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
860 lines
22 KiB
C++
860 lines
22 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include <AzCore/AzCore_Traits_Platform.h>
|
|
|
|
// Description : Linux/Mac port support for Win32API calls
|
|
#if AZ_TRAIT_LEGACY_CRYCOMMON_USE_WINDOWS_STUBS
|
|
|
|
#include "platform.h" // Note: This should be first to get consistent debugging definitions
|
|
|
|
#include <CryCommon/ISystem.h>
|
|
#include <CryAssert.h>
|
|
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#undef AZ_RESTRICTED_SECTION
|
|
#define WINBASE_CPP_SECTION_1 1
|
|
#define WINBASE_CPP_SECTION_2 2
|
|
#define WINBASE_CPP_SECTION_3 3
|
|
#define WINBASE_CPP_SECTION_4 4
|
|
#define WINBASE_CPP_SECTION_5 5
|
|
#define WINBASE_CPP_SECTION_6 6
|
|
#endif
|
|
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION WINBASE_CPP_SECTION_1
|
|
#include AZ_RESTRICTED_FILE(WinBase_cpp)
|
|
#endif
|
|
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
|
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
|
#else
|
|
#include <signal.h>
|
|
#endif
|
|
|
|
#include <pthread.h>
|
|
#include <sys/types.h>
|
|
#include <fcntl.h>
|
|
#include <AzCore/IO/SystemFile.h>
|
|
#include <AzCore/std/string/conversions.h>
|
|
|
|
#ifdef APPLE
|
|
#include <mach/mach.h>
|
|
#include <mach/mach_time.h>
|
|
#include <sys/sysctl.h> // for total physical memory on Mac
|
|
#include <CoreFoundation/CoreFoundation.h> // for CryMessageBox
|
|
#include <mach/vm_statistics.h> // host_statistics
|
|
#include <mach/mach_types.h>
|
|
#include <mach/mach_init.h>
|
|
#include <mach/mach_host.h>
|
|
#endif
|
|
|
|
#include <sys/time.h>
|
|
|
|
#if defined(LINUX) || defined(APPLE)
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
#include <utime.h>
|
|
#include <dirent.h>
|
|
#endif
|
|
|
|
#if defined(APPLE)
|
|
#include <AzFramework/Utils/SystemUtilsApple.h>
|
|
#endif
|
|
|
|
#if AZ_TRAIT_COMPILER_DEFINE_FS_ERRNO_TYPE
|
|
typedef int FS_ERRNO_TYPE;
|
|
|
|
#include <mutex>
|
|
|
|
#endif
|
|
|
|
bool IsBadReadPtr(void* ptr, unsigned int size)
|
|
{
|
|
//too complicated to really support it
|
|
return ptr ? false : true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
char* _strtime(char* date)
|
|
{
|
|
azstrcpy(date, AZ_ARRAY_SIZE(date), "0:0:0");
|
|
return date;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
char* _strdate(char* date)
|
|
{
|
|
azstrcpy(date, AZ_ARRAY_SIZE(date), "0");
|
|
return date;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
char* strlwr (char* str)
|
|
{
|
|
char* cp; /* traverses string for C locale conversion */
|
|
|
|
for (cp = str; *cp; ++cp)
|
|
{
|
|
if ('A' <= *cp && *cp <= 'Z')
|
|
{
|
|
*cp += 'a' - 'A';
|
|
}
|
|
}
|
|
return str;
|
|
}
|
|
|
|
char* strupr (char* str)
|
|
{
|
|
char* cp; /* traverses string for C locale conversion */
|
|
|
|
for (cp = str; *cp; ++cp)
|
|
{
|
|
if ('a' <= *cp && *cp <= 'z')
|
|
{
|
|
*cp += 'A' - 'a';
|
|
}
|
|
}
|
|
return str;
|
|
}
|
|
|
|
char* ltoa (long i, char* a, int radix)
|
|
{
|
|
if (a == nullptr)
|
|
{
|
|
return nullptr;
|
|
}
|
|
strcpy (a, "0");
|
|
if (i && radix > 1 && radix < 37)
|
|
{
|
|
char buf[35];
|
|
unsigned long u = i, p = 34;
|
|
buf[p] = 0;
|
|
if (i < 0 && radix == 10)
|
|
{
|
|
u = -i;
|
|
}
|
|
while (u)
|
|
{
|
|
unsigned int d = u % radix;
|
|
buf[--p] = d < 10 ? '0' + d : 'a' + d - 10;
|
|
u /= radix;
|
|
}
|
|
if (i < 0 && radix == 10)
|
|
{
|
|
buf[--p] = '-';
|
|
}
|
|
strcpy (a, buf + p);
|
|
}
|
|
return a;
|
|
}
|
|
|
|
|
|
#if AZ_TRAIT_COMPILER_DEFINE_WCSICMP
|
|
// For Linux it's redefined to wcscasecmp and wcsncasecmp'
|
|
int wcsicmp (const wchar_t* s1, const wchar_t* s2)
|
|
{
|
|
wint_t c1, c2;
|
|
|
|
if (s1 == s2)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
do
|
|
{
|
|
c1 = towlower(*s1++);
|
|
c2 = towlower(*s2++);
|
|
}
|
|
while (c1 && c1 == c2);
|
|
|
|
return (int) (c1 - c2);
|
|
}
|
|
|
|
int wcsnicmp (const wchar_t* s1, const wchar_t* s2, size_t count)
|
|
{
|
|
wint_t c1, c2;
|
|
if (s1 == s2 || count == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
do
|
|
{
|
|
c1 = towlower(*s1++);
|
|
c2 = towlower(*s2++);
|
|
}
|
|
while ((--count) && c1 && (c1 == c2));
|
|
return (int) (c1 - c2);
|
|
}
|
|
#endif
|
|
|
|
#if defined(ANDROID)
|
|
// not defined in android-19 or prior
|
|
size_t wcsnlen(const wchar_t* str, size_t maxLen)
|
|
{
|
|
size_t length;
|
|
for (length = 0; length < maxLen; ++length, ++str)
|
|
{
|
|
if (!*str)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
return length;
|
|
}
|
|
|
|
char* stpcpy(char* dest, const char* str)
|
|
{
|
|
while (*str != '\0')
|
|
{
|
|
*dest++ = *str++;
|
|
}
|
|
*dest = '\0';
|
|
|
|
return dest;
|
|
}
|
|
#endif
|
|
|
|
void _makepath(char* path, const char* drive, const char* dir, const char* filename, const char* ext)
|
|
{
|
|
char ch;
|
|
char tmp[MAX_PATH];
|
|
if (!path)
|
|
{
|
|
return;
|
|
}
|
|
tmp[0] = '\0';
|
|
if (drive && drive[0])
|
|
{
|
|
tmp[0] = drive[0];
|
|
tmp[1] = ':';
|
|
tmp[2] = 0;
|
|
}
|
|
if (dir && dir[0])
|
|
{
|
|
azstrcat(tmp, MAX_PATH, dir);
|
|
ch = tmp[strlen(tmp) - 1];
|
|
if (ch != '/' && ch != '\\')
|
|
{
|
|
azstrcat(tmp, MAX_PATH, "\\");
|
|
}
|
|
}
|
|
if (filename && filename[0])
|
|
{
|
|
azstrcat(tmp, MAX_PATH, filename);
|
|
if (ext && ext[0])
|
|
{
|
|
if (ext[0] != '.')
|
|
{
|
|
azstrcat(tmp, MAX_PATH, ".");
|
|
}
|
|
azstrcat(tmp, MAX_PATH, ext);
|
|
}
|
|
}
|
|
azstrcpy(path, strlen(tmp) + 1, tmp);
|
|
}
|
|
|
|
char* _ui64toa(unsigned long long value, char* str, int radix)
|
|
{
|
|
if (str == nullptr)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
char buffer[65];
|
|
char* pos;
|
|
int digit;
|
|
|
|
pos = &buffer[64];
|
|
*pos = '\0';
|
|
|
|
do
|
|
{
|
|
digit = value % radix;
|
|
value = value / radix;
|
|
if (digit < 10)
|
|
{
|
|
*--pos = '0' + digit;
|
|
}
|
|
else
|
|
{
|
|
*--pos = 'a' + digit - 10;
|
|
} /* if */
|
|
} while (value != 0L);
|
|
|
|
memcpy(str, pos, &buffer[64] - pos + 1);
|
|
return str;
|
|
}
|
|
|
|
long long _atoi64(const char* str)
|
|
{
|
|
if (str == nullptr)
|
|
{
|
|
return -1;
|
|
}
|
|
unsigned long long RunningTotal = 0;
|
|
char bMinus = 0;
|
|
while (*str == ' ' || (*str >= '\011' && *str <= '\015'))
|
|
{
|
|
str++;
|
|
} /* while */
|
|
if (*str == '+')
|
|
{
|
|
str++;
|
|
}
|
|
else if (*str == '-')
|
|
{
|
|
bMinus = 1;
|
|
str++;
|
|
} /* if */
|
|
while (*str >= '0' && *str <= '9')
|
|
{
|
|
RunningTotal = RunningTotal * 10 + *str - '0';
|
|
str++;
|
|
} /* while */
|
|
return bMinus ? ((long long)-RunningTotal) : (long long)RunningTotal;
|
|
}
|
|
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION WINBASE_CPP_SECTION_2
|
|
#include AZ_RESTRICTED_FILE(WinBase_cpp)
|
|
#endif
|
|
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
|
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
|
#else
|
|
bool QueryPerformanceCounter(LARGE_INTEGER* counter)
|
|
{
|
|
#if defined(LINUX)
|
|
// replaced gettimeofday
|
|
// http://fixunix.com/kernel/378888-gettimeofday-resolution-linux.html
|
|
timespec tv;
|
|
clock_gettime(CLOCK_MONOTONIC, &tv);
|
|
counter->QuadPart = (uint64)tv.tv_sec * 1000000 + tv.tv_nsec / 1000;
|
|
return true;
|
|
#elif defined(APPLE)
|
|
counter->QuadPart = mach_absolute_time();
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
bool QueryPerformanceFrequency(LARGE_INTEGER* frequency)
|
|
{
|
|
#if defined(LINUX)
|
|
// On Linux we'll use gettimeofday(). The API resolution is microseconds,
|
|
// so we'll report that to the caller.
|
|
frequency->u.LowPart = 1000000;
|
|
frequency->u.HighPart = 0;
|
|
return true;
|
|
#elif defined(APPLE)
|
|
static mach_timebase_info_data_t s_kTimeBaseInfoData;
|
|
if (s_kTimeBaseInfoData.denom == 0)
|
|
{
|
|
mach_timebase_info(&s_kTimeBaseInfoData);
|
|
}
|
|
// mach_timebase_info_data_t expresses the tick period in nanoseconds
|
|
frequency->QuadPart = 1e+9 * (uint64_t)s_kTimeBaseInfoData.denom / (uint64_t)s_kTimeBaseInfoData.numer;
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
void _splitpath(const char* inpath, char* drv, char* dir, char* fname, char* ext)
|
|
{
|
|
if (drv)
|
|
{
|
|
drv[0] = 0;
|
|
}
|
|
|
|
typedef AZStd::fixed_string<AZ_MAX_PATH_LEN> path_stack_string;
|
|
|
|
const path_stack_string inPath(inpath);
|
|
AZStd::string::size_type s = inPath.rfind('/', inPath.size());//position of last /
|
|
path_stack_string fName;
|
|
if (s == AZStd::string::npos)
|
|
{
|
|
if (dir)
|
|
{
|
|
dir[0] = 0;
|
|
}
|
|
fName = inpath; //assign complete string as rest
|
|
}
|
|
else
|
|
{
|
|
if (dir)
|
|
{
|
|
azstrcpy(dir, AZ_MAX_PATH_LEN, (inPath.substr((AZStd::string::size_type)0, (AZStd::string::size_type)(s + 1))).c_str()); //assign directory
|
|
}
|
|
fName = inPath.substr((AZStd::string::size_type)(s + 1)); //assign remaining string as rest
|
|
}
|
|
if (fName.size() == 0)
|
|
{
|
|
if (ext)
|
|
{
|
|
ext[0] = 0;
|
|
}
|
|
if (fname)
|
|
{
|
|
fname[0] = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//dir and drive are now set
|
|
s = fName.find(".", (AZStd::string::size_type)0);//position of first .
|
|
if (s == AZStd::string::npos)
|
|
{
|
|
if (ext)
|
|
{
|
|
ext[0] = 0;
|
|
}
|
|
if (fname)
|
|
{
|
|
azstrcpy(fname, fName.size() + 1, fName.c_str()); //assign filename
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ext)
|
|
{
|
|
azstrcpy(ext, AZ_MAX_PATH_LEN, (fName.substr(s)).c_str()); //assign extension including .
|
|
}
|
|
if (fname)
|
|
{
|
|
if (s == 0)
|
|
{
|
|
fname[0] = 0;
|
|
}
|
|
else
|
|
{
|
|
azstrcpy(fname, AZ_MAX_PATH_LEN, (fName.substr((AZStd::string::size_type)0, s)).c_str()); //assign filename
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------other stuff-------------------------------------------------------------------
|
|
|
|
void GlobalMemoryStatus(LPMEMORYSTATUS lpmem)
|
|
{
|
|
//not complete implementation
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION WINBASE_CPP_SECTION_3
|
|
#include AZ_RESTRICTED_FILE(WinBase_cpp)
|
|
#endif
|
|
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
|
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
|
#elif defined(APPLE)
|
|
|
|
// Retrieve dwTotalPhys
|
|
int kMIB[] = {CTL_HW, HW_MEMSIZE};
|
|
uint64_t dwTotalPhys;
|
|
size_t ulength = sizeof(dwTotalPhys);
|
|
if (sysctl(kMIB, 2, &dwTotalPhys, &ulength, NULL, 0) != 0)
|
|
{
|
|
gEnv->pLog->LogError("sysctl failed\n");
|
|
}
|
|
else
|
|
{
|
|
lpmem->dwTotalPhys = static_cast<SIZE_T>(dwTotalPhys);
|
|
}
|
|
|
|
// Get the page size
|
|
mach_port_t kHost(mach_host_self());
|
|
vm_size_t uPageSize;
|
|
if (host_page_size(kHost, &uPageSize) != 0)
|
|
{
|
|
gEnv->pLog->LogError("host_page_size failed\n");
|
|
}
|
|
else
|
|
{
|
|
// Get memory statistics
|
|
vm_statistics_data_t kVMStats;
|
|
mach_msg_type_number_t uCount(sizeof(kVMStats) / sizeof(natural_t));
|
|
if (host_statistics(kHost, HOST_VM_INFO, (host_info_t)&kVMStats, &uCount) != 0)
|
|
{
|
|
gEnv->pLog->LogError("host_statistics failed\n");
|
|
}
|
|
else
|
|
{
|
|
// Calculate dwAvailPhys
|
|
lpmem->dwAvailPhys = uPageSize * kVMStats.free_count;
|
|
}
|
|
}
|
|
#else
|
|
FILE* f;
|
|
lpmem->dwMemoryLoad = 0;
|
|
lpmem->dwTotalPhys = 16 * 1024 * 1024;
|
|
lpmem->dwAvailPhys = 16 * 1024 * 1024;
|
|
lpmem->dwTotalPageFile = 16 * 1024 * 1024;
|
|
lpmem->dwAvailPageFile = 16 * 1024 * 1024;
|
|
azfopen(&f, "/proc/meminfo", "r");
|
|
if (f)
|
|
{
|
|
char buffer[256];
|
|
memset(buffer, '0', 256);
|
|
int total, used, free, shared, buffers, cached;
|
|
|
|
lpmem->dwLength = sizeof(MEMORYSTATUS);
|
|
lpmem->dwTotalPhys = lpmem->dwAvailPhys = 0;
|
|
lpmem->dwTotalPageFile = lpmem->dwAvailPageFile = 0;
|
|
while (fgets(buffer, sizeof(buffer), f))
|
|
{
|
|
if (azsscanf(buffer, "Mem: %d %d %d %d %d %d", &total, &used, &free, &shared, &buffers, &cached))
|
|
{
|
|
lpmem->dwTotalPhys += total;
|
|
lpmem->dwAvailPhys += free + buffers + cached;
|
|
}
|
|
if (azsscanf(buffer, "Swap: %d %d %d", &total, &used, &free))
|
|
{
|
|
lpmem->dwTotalPageFile += total;
|
|
lpmem->dwAvailPageFile += free;
|
|
}
|
|
if (azsscanf(buffer, "MemTotal: %d", &total))
|
|
{
|
|
lpmem->dwTotalPhys = total * 1024;
|
|
}
|
|
if (azsscanf(buffer, "MemFree: %d", &free))
|
|
{
|
|
lpmem->dwAvailPhys = free * 1024;
|
|
}
|
|
if (azsscanf(buffer, "SwapTotal: %d", &total))
|
|
{
|
|
lpmem->dwTotalPageFile = total * 1024;
|
|
}
|
|
if (azsscanf(buffer, "SwapFree: %d", &free))
|
|
{
|
|
lpmem->dwAvailPageFile = free * 1024;
|
|
}
|
|
if (azsscanf(buffer, "Buffers: %d", &buffers))
|
|
{
|
|
lpmem->dwAvailPhys += buffers * 1024;
|
|
}
|
|
if (azsscanf(buffer, "Cached: %d", &cached))
|
|
{
|
|
lpmem->dwAvailPhys += cached * 1024;
|
|
}
|
|
}
|
|
fclose(f);
|
|
if (lpmem->dwTotalPhys)
|
|
{
|
|
DWORD TotalPhysical = lpmem->dwTotalPhys + lpmem->dwTotalPageFile;
|
|
DWORD AvailPhysical = lpmem->dwAvailPhys + lpmem->dwAvailPageFile;
|
|
lpmem->dwMemoryLoad = (TotalPhysical - AvailPhysical) / (TotalPhysical / 100);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static const int YearLengths[2] = {DAYSPERNORMALYEAR, DAYSPERLEAPYEAR};
|
|
static const int MonthLengths[2][MONSPERYEAR] =
|
|
{
|
|
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
|
|
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
|
};
|
|
|
|
static int IsLeapYear(int Year)
|
|
{
|
|
return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0;
|
|
}
|
|
|
|
static void NormalizeTimeFields(short* FieldToNormalize, short* CarryField, int Modulus)
|
|
{
|
|
*FieldToNormalize = (short) (*FieldToNormalize - Modulus);
|
|
*CarryField = (short) (*CarryField + 1);
|
|
}
|
|
|
|
static bool TimeFieldsToTime(PTIME_FIELDS tfTimeFields, PLARGE_INTEGER Time)
|
|
{
|
|
#define SECSPERMIN 60
|
|
#define MINSPERHOUR 60
|
|
#define HOURSPERDAY 24
|
|
#define MONSPERYEAR 12
|
|
|
|
#define EPOCHYEAR 1601
|
|
|
|
#define SECSPERDAY 86400
|
|
#define TICKSPERMSEC 10000
|
|
#define TICKSPERSEC 10000000
|
|
#define SECSPERHOUR 3600
|
|
|
|
int CurYear, CurMonth;
|
|
LONGLONG rcTime;
|
|
TIME_FIELDS TimeFields = *tfTimeFields;
|
|
|
|
rcTime = 0;
|
|
while (TimeFields.Second >= SECSPERMIN)
|
|
{
|
|
NormalizeTimeFields(&TimeFields.Second, &TimeFields.Minute, SECSPERMIN);
|
|
}
|
|
while (TimeFields.Minute >= MINSPERHOUR)
|
|
{
|
|
NormalizeTimeFields(&TimeFields.Minute, &TimeFields.Hour, MINSPERHOUR);
|
|
}
|
|
while (TimeFields.Hour >= HOURSPERDAY)
|
|
{
|
|
NormalizeTimeFields(&TimeFields.Hour, &TimeFields.Day, HOURSPERDAY);
|
|
}
|
|
while (TimeFields.Day > MonthLengths[IsLeapYear(TimeFields.Year)][TimeFields.Month - 1])
|
|
{
|
|
NormalizeTimeFields(&TimeFields.Day, &TimeFields.Month, SECSPERMIN);
|
|
}
|
|
while (TimeFields.Month > MONSPERYEAR)
|
|
{
|
|
NormalizeTimeFields(&TimeFields.Month, &TimeFields.Year, MONSPERYEAR);
|
|
}
|
|
for (CurYear = EPOCHYEAR; CurYear < TimeFields.Year; CurYear++)
|
|
{
|
|
rcTime += YearLengths[IsLeapYear(CurYear)];
|
|
}
|
|
for (CurMonth = 1; CurMonth < TimeFields.Month; CurMonth++)
|
|
{
|
|
rcTime += MonthLengths[IsLeapYear(CurYear)][CurMonth - 1];
|
|
}
|
|
rcTime += TimeFields.Day - 1;
|
|
rcTime *= SECSPERDAY;
|
|
rcTime += TimeFields.Hour * SECSPERHOUR + TimeFields.Minute * SECSPERMIN + TimeFields.Second;
|
|
|
|
rcTime *= TICKSPERSEC;
|
|
rcTime += TimeFields.Milliseconds * TICKSPERMSEC;
|
|
|
|
Time->QuadPart = rcTime;
|
|
|
|
return true;
|
|
}
|
|
|
|
BOOL SystemTimeToFileTime(const SYSTEMTIME* syst, LPFILETIME ft)
|
|
{
|
|
TIME_FIELDS tf;
|
|
LARGE_INTEGER t;
|
|
|
|
tf.Year = syst->wYear;
|
|
tf.Month = syst->wMonth;
|
|
tf.Day = syst->wDay;
|
|
tf.Hour = syst->wHour;
|
|
tf.Minute = syst->wMinute;
|
|
tf.Second = syst->wSecond;
|
|
tf.Milliseconds = syst->wMilliseconds;
|
|
|
|
TimeFieldsToTime(&tf, &t);
|
|
ft->dwLowDateTime = t.u.LowPart;
|
|
ft->dwHighDateTime = t.u.HighPart;
|
|
return TRUE;
|
|
}
|
|
|
|
#define Int32x32To64(a, b) ((uint64)((uint64)(a)) * (uint64)((uint64)(b)))
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION WINBASE_CPP_SECTION_4
|
|
#include AZ_RESTRICTED_FILE(WinBase_cpp)
|
|
#endif
|
|
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
|
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
|
#else
|
|
threadID GetCurrentThreadId()
|
|
{
|
|
return threadID(pthread_self());
|
|
}
|
|
#endif
|
|
|
|
#include <chrono>
|
|
#include <thread>
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
DWORD Sleep(DWORD dwMilliseconds)
|
|
{
|
|
#if defined(LINUX) || defined(APPLE)
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(dwMilliseconds));
|
|
return 0;
|
|
#define AZ_RESTRICTED_SECTION_IMPLEMENTED
|
|
#elif defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION WINBASE_CPP_SECTION_5
|
|
#include AZ_RESTRICTED_FILE(WinBase_cpp)
|
|
#endif
|
|
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
|
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
|
#else
|
|
timeval tv, start, now;
|
|
uint64 tStart;
|
|
|
|
memset(&tv, 0, sizeof tv);
|
|
memset(&start, 0, sizeof start);
|
|
memset(&now, 0, sizeof now);
|
|
gettimeofday(&now, NULL);
|
|
start = now;
|
|
tStart = (uint64)start.tv_sec * 1000000 + start.tv_usec;
|
|
while (true)
|
|
{
|
|
uint64 tNow, timePassed, timeRemaining;
|
|
tNow = (uint64)now.tv_sec * 1000000 + now.tv_usec;
|
|
timePassed = tNow - tStart;
|
|
if (timePassed >= dwMilliseconds)
|
|
{
|
|
break;
|
|
}
|
|
timeRemaining = dwMilliseconds * 1000 - timePassed;
|
|
tv.tv_sec = timeRemaining / 1000000;
|
|
tv.tv_usec = timeRemaining % 1000000;
|
|
select(1, NULL, NULL, NULL, &tv);
|
|
gettimeofday(&now, NULL);
|
|
}
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
#if defined(LINUX) || defined(APPLE)
|
|
BOOL GetComputerName(LPSTR lpBuffer, LPDWORD lpnSize)
|
|
{
|
|
if (!lpBuffer || !lpnSize)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
int err = gethostname(lpBuffer, *lpnSize);
|
|
|
|
if (-1 == err)
|
|
{
|
|
CryLog("GetComputerName falied [%d]\n", errno);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
#if AZ_TRAIT_COMPILER_DEFINE_GETCURRENTPROCESSID
|
|
DWORD GetCurrentProcessId(void)
|
|
{
|
|
return (DWORD)getpid();
|
|
}
|
|
#endif
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CrySleep(unsigned int dwMilliseconds)
|
|
{
|
|
Sleep(dwMilliseconds);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CryMessageBox(const char* lpText, const char* lpCaption, [[maybe_unused]] unsigned int uType)
|
|
{
|
|
#ifdef WIN32
|
|
# error WIN32 is defined in WinBase.cpp (it is a non-Windows file)
|
|
#elif defined(MAC)
|
|
CFStringRef strText = CFStringCreateWithCString(NULL, lpText, kCFStringEncodingMacRoman);
|
|
CFStringRef strCaption = CFStringCreateWithCString(NULL, lpCaption, kCFStringEncodingMacRoman);
|
|
|
|
CFStringRef strOk = CFSTR("OK");
|
|
CFStringRef strCancel = CFSTR("Cancel");
|
|
CFStringRef strRetry = CFSTR("Retry");
|
|
CFStringRef strYes = CFSTR("Yes");
|
|
CFStringRef strNo = CFSTR("No");
|
|
CFStringRef strAbort = CFSTR("Abort");
|
|
CFStringRef strIgnore = CFSTR("Ignore");
|
|
CFStringRef strTryAgain = CFSTR("Try Again");
|
|
CFStringRef strContinue = CFSTR("Continue");
|
|
|
|
CFStringRef defaultButton = nullptr;
|
|
CFStringRef alternativeButton = nullptr;
|
|
CFStringRef otherButton = nullptr;
|
|
|
|
switch (uType & 0xf)
|
|
{
|
|
case MB_OKCANCEL:
|
|
defaultButton = strOk;
|
|
alternativeButton = strCancel;
|
|
break;
|
|
case MB_ABORTRETRYIGNORE:
|
|
defaultButton = strAbort;
|
|
alternativeButton = strRetry;
|
|
otherButton = strIgnore;
|
|
break;
|
|
case MB_YESNOCANCEL:
|
|
defaultButton = strYes;
|
|
alternativeButton = strNo;
|
|
otherButton = strCancel;
|
|
break;
|
|
case MB_YESNO:
|
|
defaultButton = strYes;
|
|
alternativeButton = strNo;
|
|
break;
|
|
case MB_RETRYCANCEL:
|
|
defaultButton = strRetry;
|
|
alternativeButton = strCancel;
|
|
break;
|
|
case MB_CANCELTRYCONTINUE:
|
|
defaultButton = strCancel;
|
|
alternativeButton = strTryAgain;
|
|
otherButton = strContinue;
|
|
break;
|
|
case MB_OK:
|
|
default:
|
|
defaultButton = strOk;
|
|
break;
|
|
}
|
|
|
|
CFOptionFlags kResult;
|
|
CFUserNotificationDisplayAlert(
|
|
0, // no timeout
|
|
kCFUserNotificationNoteAlertLevel, //change it depending message_type flags ( MB_ICONASTERISK.... etc.)
|
|
NULL, //icon url, use default, you can change it depending message_type flags
|
|
NULL, //not used
|
|
NULL, //localization of strings
|
|
strText, //header text
|
|
strCaption, //message text
|
|
defaultButton, //default "ok" text in button
|
|
alternativeButton, //alternate button title
|
|
otherButton, //other button title, null--> no other button
|
|
&kResult //response flags
|
|
);
|
|
|
|
if (strCaption)
|
|
{
|
|
CFRelease(strCaption);
|
|
}
|
|
if (strText)
|
|
{
|
|
CFRelease(strText);
|
|
}
|
|
|
|
#else
|
|
printf("Messagebox: cap: %s text:%s\n", lpCaption ? lpCaption : " ", lpText ? lpText : " ");
|
|
#endif
|
|
}
|
|
|
|
#if defined(LINUX) || defined(APPLE)
|
|
|
|
threadID CryGetCurrentThreadId()
|
|
{
|
|
return GetCurrentThreadId();
|
|
}
|
|
|
|
#endif//LINUX APPLE
|
|
|
|
#if defined(APPLE) || defined(LINUX)
|
|
// WinAPI debug functions.
|
|
DLL_EXPORT void OutputDebugString(const char* outputString)
|
|
{
|
|
#if !defined(_RELEASE)
|
|
// Emulates dev tools output in Xcode and cmd line launch with idevicedebug.
|
|
fprintf(stdout, "%s", outputString);
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif // AZ_TRAIT_LEGACY_CRYCOMMON_USE_WINDOWS_STUBS
|