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.
717 lines
22 KiB
C++
717 lines
22 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
|
|
#ifndef CRYINCLUDE_CRYCOMMON_LINUX_WIN32WRAPPER_H
|
|
#define CRYINCLUDE_CRYCOMMON_LINUX_WIN32WRAPPER_H
|
|
#pragma once
|
|
|
|
#include <CryAssert.h>
|
|
#include <dirent.h>
|
|
#include <vector>
|
|
/* Memory block identification */
|
|
#define _FREE_BLOCK 0
|
|
#define _NORMAL_BLOCK 1
|
|
#define _CRT_BLOCK 2
|
|
#define _IGNORE_BLOCK 3
|
|
#define _CLIENT_BLOCK 4
|
|
#define _MAX_BLOCKS 5
|
|
|
|
typedef void* HMODULE;
|
|
|
|
typedef struct _MEMORYSTATUS
|
|
{
|
|
DWORD dwLength;
|
|
DWORD dwMemoryLoad;
|
|
SIZE_T dwTotalPhys;
|
|
SIZE_T dwAvailPhys;
|
|
SIZE_T dwTotalPageFile;
|
|
SIZE_T dwAvailPageFile;
|
|
SIZE_T dwTotalVirtual;
|
|
SIZE_T dwAvailVirtual;
|
|
} MEMORYSTATUS, * LPMEMORYSTATUS;
|
|
|
|
extern void GlobalMemoryStatus(LPMEMORYSTATUS lpmem);
|
|
|
|
#if defined(PLATFORM_64BIT)
|
|
# define MEMORY_ALLOCATION_ALIGNMENT 16
|
|
#else
|
|
# define MEMORY_ALLOCATION_ALIGNMENT 8
|
|
#endif
|
|
|
|
#define S_OK 0
|
|
#define THREAD_PRIORITY_NORMAL 0
|
|
#define THREAD_PRIORITY_IDLE 0
|
|
#define THREAD_PRIORITY_LOWEST 0
|
|
#define THREAD_PRIORITY_BELOW_NORMAL 0
|
|
#define THREAD_PRIORITY_ABOVE_NORMAL 0
|
|
#define THREAD_PRIORITY_HIGHEST 0
|
|
#define THREAD_PRIORITY_TIME_CRITICAL 0
|
|
#define MAX_COMPUTERNAME_LENGTH 15 // required by CryOnline module
|
|
|
|
#if 0
|
|
//for compatibility reason we got to create a class which actually contains an int rather than a void* and make sure it does not get mistreated
|
|
template <class T, T U>
|
|
//U is default type for invalid handle value, T the encapsulated handle type to be used instead of void* (as under windows and never linux)
|
|
class CHandle
|
|
{
|
|
public:
|
|
typedef T HandleType;
|
|
typedef void* PointerType; //for compatibility reason to encapsulate a void* as an int
|
|
|
|
static const HandleType sciInvalidHandleValue = U;
|
|
|
|
CHandle(const CHandle<T, U>& cHandle)
|
|
: m_Value(cHandle.m_Value){}
|
|
CHandle(const HandleType cHandle = U)
|
|
: m_Value(cHandle){}
|
|
//CHandle(const PointerType cpHandle) : m_Value(reinterpret_cast<HandleType>(cpHandle)){}
|
|
//CHandle(INVALID_HANDLE_VALUE_ENUM) : m_Value(U){}//to be able to use a common value for all InvalidHandle - types
|
|
|
|
operator HandleType(){
|
|
return m_Value;
|
|
}
|
|
bool operator!() const{return m_Value == sciInvalidHandleValue; }
|
|
const CHandle& operator =(const CHandle& crHandle){m_Value = crHandle.m_Value; return *this; }
|
|
const CHandle& operator =(const PointerType cpHandle){m_Value = reinterpret_cast<HandleType>(cpHandle); return *this; }
|
|
const bool operator ==(const CHandle& crHandle) const{return m_Value == crHandle.m_Value; }
|
|
const bool operator ==(const HandleType cHandle) const{return m_Value == cHandle; }
|
|
//const bool operator ==(const PointerType cpHandle)const{return m_Value == reinterpret_cast<HandleType>(cpHandle);}
|
|
const bool operator !=(const HandleType cHandle) const{return m_Value != cHandle; }
|
|
const bool operator !=(const CHandle& crHandle) const{return m_Value != crHandle.m_Value; }
|
|
//const bool operator !=(const PointerType cpHandle)const{return m_Value != reinterpret_cast<HandleType>(cpHandle);}
|
|
const bool operator < (const CHandle& crHandle) const{return m_Value < crHandle.m_Value; }
|
|
HandleType Handle() const{return m_Value; }
|
|
|
|
private:
|
|
HandleType m_Value; //the actual value, remember that file descriptors are ints under linux
|
|
|
|
typedef void ReferenceType;//for compatibility reason to encapsulate a void* as an int
|
|
//forbid these function which would actually not work on an int
|
|
PointerType operator->();
|
|
PointerType operator->() const;
|
|
ReferenceType operator*();
|
|
ReferenceType operator*() const;
|
|
operator PointerType();
|
|
};
|
|
|
|
typedef CHandle<INT_PTR, (INT_PTR) 0> HANDLE;
|
|
|
|
typedef HANDLE EVENT_HANDLE;
|
|
typedef HANDLE THREAD_HANDLE;
|
|
|
|
#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
|
|
#endif
|
|
|
|
//#define __TIMESTAMP__ __DATE__" "__TIME__
|
|
|
|
// stdlib.h stuff
|
|
#define _MAX_DRIVE 3 // max. length of drive component
|
|
#define _MAX_DIR 256 // max. length of path component
|
|
#define _MAX_FNAME 256 // max. length of file name component
|
|
#define _MAX_EXT 256 // max. length of extension component
|
|
|
|
// fcntl.h
|
|
#define _O_RDONLY 0x0000 /* open for reading only */
|
|
#define _O_WRONLY 0x0001 /* open for writing only */
|
|
#define _O_RDWR 0x0002 /* open for reading and writing */
|
|
#define _O_APPEND 0x0008 /* writes done at eof */
|
|
#define _O_CREAT 0x0100 /* create and open file */
|
|
#define _O_TRUNC 0x0200 /* open and truncate */
|
|
#define _O_EXCL 0x0400 /* open only if file doesn't already exist */
|
|
#define _O_TEXT 0x4000 /* file mode is text (translated) */
|
|
#define _O_BINARY 0x8000 /* file mode is binary (untranslated) */
|
|
#define _O_RAW _O_BINARY
|
|
#define _O_NOINHERIT 0x0080 /* child process doesn't inherit file */
|
|
#define _O_TEMPORARY 0x0040 /* temporary file bit */
|
|
#define _O_SHORT_LIVED 0x1000 /* temporary storage file, try not to flush */
|
|
#define _O_SEQUENTIAL 0x0020 /* file access is primarily sequential */
|
|
#define _O_RANDOM 0x0010 /* file access is primarily random */
|
|
|
|
inline void MemoryBarrier() {
|
|
__sync_synchronize();
|
|
}
|
|
// Memory barrier implementation taken from https://code.google.com/p/gperftools/
|
|
//inline void MemoryBarrier() {
|
|
// __asm__ __volatile__("mfence" : : : "memory");
|
|
//}
|
|
|
|
#if !defined(_CPU_SSE)
|
|
typedef int64 __m128;
|
|
#endif
|
|
|
|
#if defined(LINUX64) || defined(APPLE)
|
|
unsigned char _InterlockedCompareExchange128(int64 volatile* dst, int64 exchangehigh, int64 exchangelow, int64* comperand);
|
|
#endif
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// io.h stuff
|
|
#if !defined(ANDROID)
|
|
extern int errno;
|
|
#endif
|
|
typedef unsigned int _fsize_t;
|
|
|
|
struct _OVERLAPPED;
|
|
typedef _OVERLAPPED* LPOVERLAPPED;
|
|
|
|
typedef void (* LPOVERLAPPED_COMPLETION_ROUTINE)(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, struct _OVERLAPPED* lpOverlapped);
|
|
|
|
typedef struct tagRECT
|
|
{
|
|
LONG left;
|
|
LONG top;
|
|
LONG right;
|
|
LONG bottom;
|
|
} RECT, * PRECT;
|
|
|
|
typedef struct tagPOINT
|
|
{
|
|
LONG x;
|
|
LONG y;
|
|
} POINT, * PPOINT;
|
|
|
|
#ifndef _FILETIME_
|
|
#define _FILETIME_
|
|
typedef struct _FILETIME
|
|
{
|
|
DWORD dwLowDateTime;
|
|
DWORD dwHighDateTime;
|
|
} FILETIME, * PFILETIME, * LPFILETIME;
|
|
#endif
|
|
|
|
typedef union _ULARGE_INTEGER
|
|
{
|
|
struct
|
|
{
|
|
DWORD LowPart;
|
|
DWORD HighPart;
|
|
};
|
|
unsigned long long QuadPart;
|
|
} ULARGE_INTEGER;
|
|
|
|
typedef ULARGE_INTEGER* PULARGE_INTEGER;
|
|
|
|
#ifdef __cplusplus
|
|
inline LONG CompareFileTime(const FILETIME* lpFileTime1, const FILETIME* lpFileTime2)
|
|
#else
|
|
static LONG CompareFileTime(const FILETIME* lpFileTime1, const FILETIME* lpFileTime2)
|
|
#endif
|
|
{
|
|
ULARGE_INTEGER u1, u2;
|
|
memcpy(&u1, lpFileTime1, sizeof u1);
|
|
memcpy(&u2, lpFileTime2, sizeof u2);
|
|
if (u1.QuadPart < u2.QuadPart)
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
if (u1.QuadPart > u2.QuadPart)
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
typedef struct _SYSTEMTIME
|
|
{
|
|
WORD wYear;
|
|
WORD wMonth;
|
|
WORD wDayOfWeek;
|
|
WORD wDay;
|
|
WORD wHour;
|
|
WORD wMinute;
|
|
WORD wSecond;
|
|
WORD wMilliseconds;
|
|
} SYSTEMTIME, * PSYSTEMTIME, * LPSYSTEMTIME;
|
|
|
|
typedef struct _TIME_FIELDS
|
|
{
|
|
short Year;
|
|
short Month;
|
|
short Day;
|
|
short Hour;
|
|
short Minute;
|
|
short Second;
|
|
short Milliseconds;
|
|
short Weekday;
|
|
} TIME_FIELDS, * PTIME_FIELDS;
|
|
|
|
#define DAYSPERNORMALYEAR 365
|
|
#define DAYSPERLEAPYEAR 366
|
|
#define MONSPERYEAR 12
|
|
|
|
inline void ZeroMemory(void* pPtr, int nSize)
|
|
{
|
|
memset(pPtr, 0, nSize);
|
|
}
|
|
|
|
inline BOOL InflateRect(RECT* pRect, int dx, int dy)
|
|
{
|
|
pRect->left -= dx;
|
|
pRect->right += dx;
|
|
pRect->top -= dy;
|
|
pRect->bottom += dy;
|
|
return TRUE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
extern BOOL SystemTimeToFileTime(const SYSTEMTIME* syst, LPFILETIME ft);
|
|
//Win32API function declarations actually used
|
|
extern bool IsBadReadPtr(void* ptr, unsigned int size);
|
|
|
|
// Defined in the launcher.
|
|
DLL_IMPORT void OutputDebugString(const char*);
|
|
DLL_IMPORT void DebugBreak();
|
|
|
|
/*
|
|
//critical section stuff
|
|
#define pthread_attr_default NULL
|
|
|
|
typedef pthread_mutex_t CRITICAL_SECTION;
|
|
#ifdef __cplusplus
|
|
inline void InitializeCriticalSection(CRITICAL_SECTION *lpCriticalSection)
|
|
{
|
|
pthread_mutexattr_t pthread_mutexattr_def;
|
|
pthread_mutexattr_settype(&pthread_mutexattr_def, PTHREAD_MUTEX_RECURSIVE_NP);
|
|
pthread_mutex_init(lpCriticalSection, &pthread_mutexattr_def);
|
|
}
|
|
inline void EnterCriticalSection(CRITICAL_SECTION *lpCriticalSection){pthread_mutex_lock(lpCriticalSection);}
|
|
inline void LeaveCriticalSection(CRITICAL_SECTION *lpCriticalSection){pthread_mutex_unlock(lpCriticalSection);}
|
|
inline void DeleteCriticalSection(CRITICAL_SECTION *lpCriticalSection){}
|
|
#else
|
|
static void InitializeCriticalSection(CRITICAL_SECTION *lpCriticalSection)
|
|
{
|
|
pthread_mutexattr_t pthread_mutexattr_def;
|
|
pthread_mutexattr_settype(&pthread_mutexattr_def, PTHREAD_MUTEX_RECURSIVE_NP);
|
|
pthread_mutex_init(lpCriticalSection, &pthread_mutexattr_def);
|
|
}
|
|
static void EnterCriticalSection(CRITICAL_SECTION *lpCriticalSection){pthread_mutex_lock(lpCriticalSection);}
|
|
static void LeaveCriticalSection(CRITICAL_SECTION *lpCriticalSection){pthread_mutex_unlock(lpCriticalSection);}
|
|
static void DeleteCriticalSection(CRITICAL_SECTION *lpCriticalSection){}
|
|
#endif
|
|
*/
|
|
|
|
extern bool QueryPerformanceCounter(LARGE_INTEGER* counter);
|
|
extern bool QueryPerformanceFrequency(LARGE_INTEGER* frequency);
|
|
#ifdef __cplusplus
|
|
|
|
inline uint32 GetTickCount()
|
|
{
|
|
LARGE_INTEGER count, freq;
|
|
QueryPerformanceCounter(&count);
|
|
QueryPerformanceFrequency(&freq);
|
|
return uint32(count.QuadPart * 1000 / freq.QuadPart);
|
|
}
|
|
|
|
#define IGNORE 0 // Ignore signal
|
|
#define INFINITE 0xFFFFFFFF // Infinite timeout
|
|
#endif
|
|
//begin--------------------------------findfirst/-next declaration/implementation----------------------------------------------------
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// function renaming
|
|
#define _TRUNCATE (size_t(-1))
|
|
#define _chmod chmod
|
|
#define _snprintf snprintf
|
|
#define stricmp strcasecmp
|
|
#define _stricmp strcasecmp
|
|
#define strnicmp strncasecmp
|
|
#define _strnicmp strncasecmp
|
|
|
|
#define _strlwr strlwr
|
|
#define _strlwr_s(BUF, SIZE) strlwr(BUF)
|
|
#define _strups strupr
|
|
|
|
#define _wtof(str) wcstod(str, 0)
|
|
|
|
// Need to include this before using it's used in finddata, but after the strnicmp definition
|
|
#include "CryString.h"
|
|
|
|
typedef struct __finddata64_t
|
|
{
|
|
//!< atributes set by find request
|
|
unsigned int attrib; //!< attributes, only directory and readonly flag actually set
|
|
int64 time_create; //!< creation time, cannot parse under linux, last modification time is used instead (game does nowhere makes decision based on this values)
|
|
int64 time_access; //!< last access time
|
|
int64 time_write; //!< last modification time
|
|
int64 size; //!< file size (for a directory it will be the block size)
|
|
char name[256]; //!< file/directory name
|
|
|
|
private:
|
|
int m_LastIndex; //!< last index for findnext
|
|
char m_DirectoryName[260]; //!< directory name, needed when getting file attributes on the fly
|
|
char m_ToMatch[260]; //!< pattern to match with
|
|
DIR* m_Dir; //!< directory handle
|
|
std::vector<string> m_Entries; //!< all file entries in the current directories
|
|
public:
|
|
|
|
inline __finddata64_t()
|
|
: attrib(0)
|
|
, time_create(0)
|
|
, time_access(0)
|
|
, time_write(0)
|
|
, size(0)
|
|
, m_LastIndex(-1)
|
|
, m_Dir(NULL)
|
|
{
|
|
memset(name, '0', 256);
|
|
}
|
|
~__finddata64_t();
|
|
|
|
//!< copies and retrieves the data for an actual match (to not waste any effort retrioeving data for unused files)
|
|
void CopyFoundData(const char* rMatchedFileName);
|
|
|
|
public:
|
|
//!< global _findfirst64 function using struct above, can't be a member function due to required semantic match
|
|
friend intptr_t _findfirst64(const char* pFileName, __finddata64_t* pFindData);
|
|
//!< global _findnext64 function using struct above, can't be a member function due to required semantic match
|
|
friend int _findnext64(intptr_t last, __finddata64_t* pFindData);
|
|
}__finddata64_t;
|
|
|
|
typedef struct _finddata_t
|
|
: public __finddata64_t
|
|
{}_finddata_t;//!< need inheritance since in many places it get used as struct _finddata_t
|
|
extern int _findnext64(intptr_t last, __finddata64_t* pFindData);
|
|
extern intptr_t _findfirst64(const char* pFileName, __finddata64_t* pFindData);
|
|
|
|
extern DWORD GetFileAttributes(LPCSTR lpFileName);
|
|
|
|
extern const bool GetFilenameNoCase(const char* file, char*, const bool cCreateNew = false);
|
|
|
|
extern BOOL GetUserName(LPSTR lpBuffer, LPDWORD nSize);
|
|
|
|
//error code stuff
|
|
//not thread specific, just a coarse implementation for the main thread
|
|
inline DWORD GetLastError() { return errno; }
|
|
inline void SetLastError(DWORD dwErrCode) { errno = dwErrCode; }
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
#define GENERIC_READ (0x80000000L)
|
|
#define GENERIC_WRITE (0x40000000L)
|
|
#define GENERIC_EXECUTE (0x20000000L)
|
|
#define GENERIC_ALL (0x10000000L)
|
|
|
|
#define CREATE_NEW 1
|
|
#define CREATE_ALWAYS 2
|
|
#define OPEN_EXISTING 3
|
|
#define OPEN_ALWAYS 4
|
|
#define TRUNCATE_EXISTING 5
|
|
|
|
#define FILE_SHARE_READ 0x00000001
|
|
#define FILE_SHARE_WRITE 0x00000002
|
|
#define OPEN_EXISTING 3
|
|
#define FILE_FLAG_OVERLAPPED 0x40000000
|
|
#define INVALID_FILE_SIZE ((DWORD)0xFFFFFFFFl)
|
|
#define FILE_BEGIN 0
|
|
#define FILE_CURRENT 1
|
|
#define FILE_END 2
|
|
#define ERROR_NO_SYSTEM_RESOURCES 1450L
|
|
#define ERROR_INVALID_USER_BUFFER 1784L
|
|
#define ERROR_NOT_ENOUGH_MEMORY 8L
|
|
#define ERROR_PATH_NOT_FOUND 3L
|
|
#define FILE_FLAG_SEQUENTIAL_SCAN 0x08000000
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
extern threadID GetCurrentThreadId();
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
extern HANDLE CreateEvent(
|
|
LPSECURITY_ATTRIBUTES lpEventAttributes,
|
|
BOOL bManualReset,
|
|
BOOL bInitialState,
|
|
LPCSTR lpName
|
|
);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
extern DWORD Sleep(DWORD dwMilliseconds);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
extern DWORD SleepEx(DWORD dwMilliseconds, BOOL bAlertable);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
extern DWORD WaitForSingleObjectEx(
|
|
HANDLE hHandle,
|
|
DWORD dwMilliseconds,
|
|
BOOL bAlertable);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
extern DWORD WaitForMultipleObjectsEx(
|
|
DWORD nCount,
|
|
const HANDLE* lpHandles,
|
|
BOOL bWaitAll,
|
|
DWORD dwMilliseconds,
|
|
BOOL bAlertable);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
extern DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
extern BOOL SetEvent(HANDLE hEvent);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
extern BOOL ResetEvent(HANDLE hEvent);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
extern HANDLE CreateMutex(
|
|
LPSECURITY_ATTRIBUTES lpMutexAttributes,
|
|
BOOL bInitialOwner,
|
|
LPCSTR lpName
|
|
);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
extern BOOL ReleaseMutex(HANDLE hMutex);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
typedef DWORD (* PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter);
|
|
typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
extern HANDLE CreateThread(
|
|
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
|
SIZE_T dwStackSize,
|
|
LPTHREAD_START_ROUTINE lpStartAddress,
|
|
LPVOID lpParameter,
|
|
DWORD dwCreationFlags,
|
|
LPDWORD lpThreadId
|
|
);
|
|
|
|
extern BOOL GetComputerName(LPSTR lpBuffer, LPDWORD lpnSize); //required for CryOnline
|
|
extern DWORD GetCurrentProcessId(void);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
#ifdef __cplusplus
|
|
|
|
//helper function
|
|
extern void adaptFilenameToLinux(char* rAdjustedFilename);
|
|
extern const int comparePathNames(const char* cpFirst, const char* cpSecond, unsigned int len);//returns 0 if identical
|
|
extern void replaceDoublePathFilename(char* szFileName);//removes "\.\" to "\" and "/./" to "/"
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
extern char* _fullpath(char* absPath, const char* relPath, size_t maxLength);
|
|
//////////////////////////////////////////////////////////////////////////
|
|
extern void _makepath(char* path, const char* drive, const char* dir, const char* filename, const char* ext);
|
|
|
|
template <size_t size>
|
|
void _makepath_s(char(&path)[size], const char *drive, const char *dir, const char *fname, const char *ext)
|
|
{
|
|
_makepath(path, drive, dir, fname, ext);
|
|
}
|
|
|
|
extern void _splitpath(const char* inpath, char* drv, char* dir, char* fname, char* ext);
|
|
|
|
template <size_t drivesize, size_t dirsize, size_t fnamesize, size_t extsize>
|
|
void _splitpath_s(const char *path, char(&drive)[drivesize], char(&dir)[dirsize], char(&fname)[fnamesize], char(&ext)[extsize])
|
|
{
|
|
_splitpath(path, drive, dir, fname, ext);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
extern int memicmp(LPCSTR s1, LPCSTR s2, DWORD len);
|
|
|
|
extern "C" char* strlwr (char* str);
|
|
extern "C" char* strupr(char* str);
|
|
|
|
extern char* _ui64toa(unsigned long long value, char* str, int radix);
|
|
extern long long _atoi64(const char* str);
|
|
|
|
extern int* _errno();
|
|
|
|
template <size_t SIZE>
|
|
int vsprintf_s(char (&dst)[SIZE], const char* format, va_list argptr)
|
|
{
|
|
vsnprintf(dst, SIZE, format, argptr);
|
|
dst[SIZE - 1] = 0;
|
|
return 0;
|
|
}
|
|
|
|
inline int vsprintf_s(char* dst, size_t size, const char* format, va_list argptr)
|
|
{
|
|
vsnprintf(dst, size, format, argptr);
|
|
dst[size - 1] = 0;
|
|
return 0;
|
|
}
|
|
|
|
//note that behaviour is different from strncpy.
|
|
//this will not pad string with zeroes if length of src is less than 'size'
|
|
|
|
inline int strncpy_s(char* dst, size_t buf_size, const char* src, size_t size)
|
|
{
|
|
size_t to_copy = std::min(size, strlen(src));
|
|
size_t term = std::min(buf_size - 1, to_copy);//length of result
|
|
strncpy(dst, src, term);
|
|
dst[term] = 0;
|
|
return 0;
|
|
}
|
|
|
|
template <size_t SIZE>
|
|
inline int strncpy_s(char(&dst)[SIZE], const char* src, size_t size)
|
|
{
|
|
size_t to_copy = std::min(size, strlen(src));
|
|
size_t term = std::min(SIZE - 1, to_copy);//length of result
|
|
strncpy(dst, src, term);
|
|
dst[term] = 0;
|
|
return 0;
|
|
}
|
|
|
|
inline int strcat_s(char* dst, size_t size, const char* src)
|
|
{
|
|
if (!dst || !src)
|
|
{
|
|
return EINVAL;
|
|
}
|
|
size_t len_dst = strlen(dst);
|
|
size_t len_src = strlen(src);
|
|
if (size == 0 || len_dst + len_src + 1 >= size)
|
|
{
|
|
return ERANGE;
|
|
}
|
|
memcpy(dst + len_dst, src, len_src);
|
|
dst[len_dst + len_src] = 0;
|
|
return 0;
|
|
}
|
|
|
|
template <size_t SIZE>
|
|
int strcat_s(char(&dst)[SIZE], const char* src)
|
|
{
|
|
return strcat_s(dst, SIZE, src);
|
|
}
|
|
|
|
|
|
template <size_t SIZE>
|
|
int strcpy_s(char(&dst)[SIZE], const char* src)
|
|
{
|
|
strncpy(dst, src, SIZE);
|
|
dst[SIZE - 1] = 0;
|
|
return 0;
|
|
}
|
|
|
|
inline int strcpy_s(char* dst, size_t size, const char* src)
|
|
{
|
|
strncpy(dst, src, size);
|
|
dst[size - 1] = 0;
|
|
return 0;
|
|
}
|
|
|
|
inline int sprintf_s(char* buffer, size_t sizeOfBuffer, const char* format, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, format);
|
|
int err = vsnprintf(buffer, sizeOfBuffer, format, args);
|
|
va_end(args);
|
|
return err;
|
|
}
|
|
|
|
template <size_t size>
|
|
int sprintf_s(char (&buffer)[size], const char* format, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, format);
|
|
int err = vsnprintf(buffer, size, format, args);
|
|
va_end(args);
|
|
return err;
|
|
}
|
|
|
|
#ifdef _isnan
|
|
#undef _isnan
|
|
template <typename T>
|
|
bool _isnan(T value)
|
|
{
|
|
return value != value;
|
|
}
|
|
#endif
|
|
|
|
|
|
#define vsnprintf_s(BUF, SIZE, COUNT, FORMAT, ARGVLIST) vsnprintf(BUF, SIZE, FORMAT, ARGVLIST)
|
|
#define _vsnwprintf_s(BUF, SIZE, COUNT, FORMAT, ARGVLIST) vswprintf(BUF, SIZE, FORMAT, ARGVLIST)
|
|
#define fprintf_s fprintf
|
|
#define sscanf_s sscanf
|
|
#define fread_s(BUF, SIZE, NMEMB, MAX, HANDLE) fread(BUF, SIZE, NMEMB, HANDLE)
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef __TRLTOA__
|
|
#define __TRLTOA__
|
|
extern char* ltoa (long i, char* a, int radix);
|
|
#endif
|
|
#define itoa ltoa
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
#if 0
|
|
inline long int abs(long int x)
|
|
{
|
|
return labs(x);
|
|
}
|
|
|
|
inline float abs(float x)
|
|
{
|
|
return fabsf(x);
|
|
}
|
|
|
|
inline double abs(double x)
|
|
{
|
|
return fabs(x);
|
|
}
|
|
|
|
inline float sqrt(float x)
|
|
{
|
|
return sqrtf(x);
|
|
}
|
|
#else
|
|
#include <cmath>
|
|
using std::abs;
|
|
using std::sqrt;
|
|
using std::fabs;
|
|
#endif
|
|
|
|
extern char* _strtime(char* date);
|
|
extern char* _strdate(char* date);
|
|
|
|
#if !defined(_CPU_SSE)
|
|
#define _MM_HINT_T0 (1)
|
|
#define _MM_HINT_T1 (2)
|
|
#define _MM_HINT_T2 (3)
|
|
#define _MM_HINT_NTA (0)
|
|
inline void _mm_prefetch(const char*, int) { }
|
|
#endif // !_CPU_SSE
|
|
|
|
#endif //__cplusplus
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Byte Swapping functions
|
|
|
|
inline unsigned short _byteswap_ushort(unsigned short input)
|
|
{
|
|
return ((input & 0xff) << 8) | ((input & 0xff00) >> 8);
|
|
}
|
|
|
|
inline LONG _byteswap_ulong(LONG input)
|
|
{
|
|
return (input & 0x000000ff) << 24 |
|
|
(input & 0x0000ff00) << 8 |
|
|
(input & 0x00ff0000) >> 8 |
|
|
(input & 0xff000000) >> 24;
|
|
}
|
|
|
|
inline unsigned long long _byteswap_uint64(unsigned long long input)
|
|
{
|
|
return (((input & 0xff00000000000000ull) >> 56) |
|
|
((input & 0x00ff000000000000ull) >> 40) |
|
|
((input & 0x0000ff0000000000ull) >> 24) |
|
|
((input & 0x000000ff00000000ull) >> 8) |
|
|
((input & 0x00000000ff000000ull) << 8) |
|
|
((input & 0x0000000000ff0000ull) << 24) |
|
|
((input & 0x000000000000ff00ull) << 40) |
|
|
((input & 0x00000000000000ffull) << 56));
|
|
}
|
|
|
|
#endif // CRYINCLUDE_CRYCOMMON_LINUX_WIN32WRAPPER_H
|
|
|
|
// vim:ts=2
|
|
|