DirectXShaderCompiler/lib/DxcSupport/WinFunctions.cpp

333 строки
8.6 KiB
C++

//===-- WinFunctions.cpp - Windows Functions for other platforms --*- C++
//-*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines Windows-specific functions used in the codebase for
// non-Windows platforms.
//
//===----------------------------------------------------------------------===//
#ifndef _WIN32
#include <fcntl.h>
#include <map>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "dxc/Support/WinFunctions.h"
#include "dxc/Support/microcom.h"
HRESULT StringCchPrintfA(char *dst, size_t dstSize, const char *format, ...) {
va_list args;
va_start(args, format);
va_list argscopy;
va_copy(argscopy, args);
// C++11 snprintf can return the size of the resulting string if it was to be
// constructed.
size_t size =
vsnprintf(nullptr, 0, format, argscopy) + 1; // Extra space for '\0'
if (size > dstSize) {
*dst = '\0';
} else {
vsnprintf(dst, size, format, args);
}
va_end(argscopy);
va_end(args);
return S_OK;
}
HRESULT UIntAdd(UINT uAugend, UINT uAddend, UINT *puResult) {
HRESULT hr;
if ((uAugend + uAddend) >= uAugend) {
*puResult = (uAugend + uAddend);
hr = S_OK;
} else {
*puResult = 0xffffffff;
hr = ERROR_ARITHMETIC_OVERFLOW;
}
return hr;
}
HRESULT IntToUInt(int in, UINT *out) {
HRESULT hr;
if (in >= 0) {
*out = (UINT)in;
hr = S_OK;
} else {
*out = 0xffffffff;
hr = ERROR_ARITHMETIC_OVERFLOW;
}
return hr;
}
HRESULT SizeTToInt(size_t in, int *out) {
HRESULT hr;
if (in <= INT_MAX) {
*out = (int)in;
hr = S_OK;
} else {
*out = 0xffffffff;
hr = ERROR_ARITHMETIC_OVERFLOW;
}
return hr;
}
HRESULT UInt32Mult(UINT a, UINT b, UINT *out) {
uint64_t result = (uint64_t)a * (uint64_t)b;
if (result > uint64_t(UINT_MAX))
return ERROR_ARITHMETIC_OVERFLOW;
*out = (uint32_t)result;
return S_OK;
}
int strnicmp(const char *str1, const char *str2, size_t count) {
size_t i = 0;
for (; i < count && str1[i] && str2[i]; ++i) {
int d = std::tolower(str1[i]) - std::tolower(str2[i]);
if (d != 0)
return d;
}
if (i == count) {
// All 'count' characters matched.
return 0;
}
// str1 or str2 reached NULL before 'count' characters were compared.
return str1[i] - str2[i];
}
int _stricmp(const char *str1, const char *str2) {
size_t i = 0;
for (; str1[i] && str2[i]; ++i) {
int d = std::tolower(str1[i]) - std::tolower(str2[i]);
if (d != 0)
return d;
}
return str1[i] - str2[i];
}
int _wcsicmp(const wchar_t *str1, const wchar_t *str2) {
size_t i = 0;
for (; str1[i] && str2[i]; ++i) {
int d = std::towlower(str1[i]) - std::towlower(str2[i]);
if (d != 0)
return d;
}
return str1[i] - str2[i];
}
int _wcsnicmp(const wchar_t *str1, const wchar_t *str2, size_t n) {
size_t i = 0;
for (; i < n && str1[i] && str2[i]; ++i) {
int d = std::towlower(str1[i]) - std::towlower(str2[i]);
if (d != 0)
return d;
}
if (i >= n)
return 0;
return str1[i] - str2[i];
}
unsigned char _BitScanForward(unsigned long *Index, unsigned long Mask) {
unsigned long l;
if (!Mask)
return 0;
for (l = 0; !(Mask & 1); l++)
Mask >>= 1;
*Index = l;
return 1;
}
HANDLE CreateFile2(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
DWORD dwCreationDisposition, void *pCreateExParams) {
return CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, pCreateExParams,
dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr);
}
HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
void *lpSecurityAttributes, DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
CW2A pUtf8FileName(lpFileName);
size_t fd = -1;
int flags = 0;
if (dwDesiredAccess & GENERIC_WRITE)
if (dwDesiredAccess & GENERIC_READ)
flags |= O_RDWR;
else
flags |= O_WRONLY;
else // dwDesiredAccess may be 0, but open() demands something here. This is
// mostly harmless
flags |= O_RDONLY;
if (dwCreationDisposition == CREATE_ALWAYS)
flags |= (O_CREAT | O_TRUNC);
if (dwCreationDisposition == OPEN_ALWAYS)
flags |= O_CREAT;
else if (dwCreationDisposition == CREATE_NEW)
flags |= (O_CREAT | O_EXCL);
else if (dwCreationDisposition == TRUNCATE_EXISTING)
flags |= O_TRUNC;
// OPEN_EXISTING represents default open() behavior
// Catch Implementation limitations.
assert(!lpSecurityAttributes &&
"security attributes not supported in CreateFileW yet");
assert(!hTemplateFile && "template file not supported in CreateFileW yet");
assert(dwFlagsAndAttributes == FILE_ATTRIBUTE_NORMAL &&
"Attributes other than NORMAL not supported in CreateFileW yet");
while ((int)(fd = open(pUtf8FileName, flags,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
if (errno != EINTR)
return INVALID_HANDLE_VALUE;
}
return (HANDLE)fd;
}
BOOL GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize) {
int fd = (size_t)hFile;
struct stat fdstat;
int rv = fstat(fd, &fdstat);
if (!rv) {
lpFileSize->QuadPart = (LONGLONG)fdstat.st_size;
return true;
}
return false;
}
BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead, void *lpOverlapped) {
size_t fd = (size_t)hFile;
ssize_t rv = -1;
// Implementation limitation
assert(!lpOverlapped && "Overlapping not supported in ReadFile yet.");
rv = read(fd, lpBuffer, nNumberOfBytesToRead);
if (rv < 0)
return false;
*lpNumberOfBytesRead = rv;
return true;
}
BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten, void *lpOverlapped) {
size_t fd = (size_t)hFile;
ssize_t rv = -1;
// Implementation limitation
assert(!lpOverlapped && "Overlapping not supported in WriteFile yet.");
rv = write(fd, lpBuffer, nNumberOfBytesToWrite);
if (rv < 0)
return false;
*lpNumberOfBytesWritten = rv;
return true;
}
BOOL CloseHandle(HANDLE hObject) {
int fd = (size_t)hObject;
return !close(fd);
}
// Half-hearted implementation of a heap structure
// Enables size queries, maximum allocation limit, and collective free at heap
// destruction Does not perform any preallocation or allocation organization.
// Does not respect any flags except for HEAP_ZERO_MEMORY
struct SimpleAllocation {
LPVOID ptr;
SIZE_T size;
};
struct SimpleHeap {
std::map<LPCVOID, SimpleAllocation> allocs;
SIZE_T maxSize, curSize;
};
HANDLE HeapCreate(DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize) {
SimpleHeap *simpHeap = new SimpleHeap;
simpHeap->maxSize = dwMaximumSize;
simpHeap->curSize = 0;
return (HANDLE)simpHeap;
}
BOOL HeapDestroy(HANDLE hHeap) {
SimpleHeap *simpHeap = (SimpleHeap *)hHeap;
for (auto it = simpHeap->allocs.begin(), e = simpHeap->allocs.end(); it != e;
it++)
free(it->second.ptr);
delete simpHeap;
return true;
}
LPVOID HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes) {
LPVOID ptr = nullptr;
SimpleHeap *simpHeap = (SimpleHeap *)hHeap;
if (simpHeap->maxSize && simpHeap->curSize + dwBytes > simpHeap->maxSize)
return nullptr;
if (dwFlags == HEAP_ZERO_MEMORY)
ptr = calloc(1, dwBytes);
else
ptr = malloc(dwBytes);
simpHeap->allocs[ptr] = {ptr, dwBytes};
simpHeap->curSize += dwBytes;
return ptr;
}
LPVOID HeapReAlloc(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, SIZE_T dwBytes) {
LPVOID ptr = nullptr;
SimpleHeap *simpHeap = (SimpleHeap *)hHeap;
SIZE_T oSize = simpHeap->allocs[lpMem].size;
if (simpHeap->maxSize &&
simpHeap->curSize - oSize + dwBytes > simpHeap->maxSize)
return nullptr;
ptr = realloc(lpMem, dwBytes);
if (dwFlags == HEAP_ZERO_MEMORY && oSize < dwBytes)
memset((char *)ptr + oSize, 0, dwBytes - oSize);
simpHeap->allocs.erase(lpMem);
simpHeap->curSize -= oSize;
simpHeap->allocs[ptr] = {ptr, dwBytes};
simpHeap->curSize += dwBytes;
return ptr;
}
BOOL HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem) {
SimpleHeap *simpHeap = (SimpleHeap *)hHeap;
SIZE_T oSize = simpHeap->allocs[lpMem].size;
free(lpMem);
simpHeap->allocs.erase(lpMem);
simpHeap->curSize -= oSize;
return true;
}
SIZE_T HeapSize(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem) {
SimpleHeap *simpHeap = (SimpleHeap *)hHeap;
return simpHeap->allocs[lpMem].size;
}
static SimpleHeap g_processHeap;
HANDLE GetProcessHeap() { return (HANDLE)&g_processHeap; }
#endif // _WIN32