Windows: use utf16 for file functions
This commit is contained in:
parent
40609b2f5f
commit
e12ca55ee0
@ -9,13 +9,26 @@
|
|||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
#include "../windows/realpath.c"
|
#include "../windows/realpath.c"
|
||||||
|
#include "../windows/utf16.c"
|
||||||
|
// use wide char functions for unicode support / longer paths (potentially)
|
||||||
|
// opendir() is provided by mingw and does unicode convertion already
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
FILE* file_open(B path, char* desc, char* mode) { // doesn't consume
|
FILE* file_open(B path, char* desc, char* mode) { // doesn't consume
|
||||||
|
#if !defined(_WIN32)
|
||||||
char* p = toCStr(path);
|
char* p = toCStr(path);
|
||||||
FILE* f = fopen(p, mode);
|
FILE* f = fopen(p, mode);
|
||||||
freeCStr(p);
|
freeCStr(p);
|
||||||
|
#else
|
||||||
|
WCHAR wmode[8] = {0};
|
||||||
|
u64 len = strlen(mode);
|
||||||
|
assert(len<(sizeof(wmode)/sizeof(WCHAR)));
|
||||||
|
for (u64 i = 0; i<len; ++i) wmode[i] = (WCHAR)mode[i];
|
||||||
|
WCHAR *p = toWStr(path);
|
||||||
|
FILE* f = _wfopen(p, wmode);
|
||||||
|
freeWStr(p);
|
||||||
|
#endif
|
||||||
if (f==NULL) thrF("Couldn't %S file \"%R\"", desc, path);
|
if (f==NULL) thrF("Couldn't %S file \"%R\"", desc, path);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
@ -301,9 +314,9 @@ static NOINLINE Arr* mmapH_slice(B x, usz s, usz ia) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
B mmap_file(B path) {
|
B mmap_file(B path) {
|
||||||
|
#if !defined(_WIN32)
|
||||||
char* p = toCStr(path);
|
char* p = toCStr(path);
|
||||||
dec(path);
|
dec(path);
|
||||||
#if !defined(_WIN32)
|
|
||||||
int fd = open(p, 0);
|
int fd = open(p, 0);
|
||||||
freeCStr(p);
|
freeCStr(p);
|
||||||
if (fd==-1) thrF("Failed to open file: %S", strerror(errno));
|
if (fd==-1) thrF("Failed to open file: %S", strerror(errno));
|
||||||
@ -316,11 +329,12 @@ B mmap_file(B path) {
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// see https://learn.microsoft.com/en-us/windows/win32/memory/creating-a-view-within-a-file
|
// see https://learn.microsoft.com/en-us/windows/win32/memory/creating-a-view-within-a-file
|
||||||
|
WCHAR* p = toWStr(path);
|
||||||
HANDLE hFile = CreateFileA(
|
dec(path);
|
||||||
|
HANDLE hFile = CreateFileW(
|
||||||
p, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL,
|
p, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL,
|
||||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
freeCStr(p);
|
freeWStr(p);
|
||||||
if (hFile==INVALID_HANDLE_VALUE) thrF("Failed to open file: %S", winError());
|
if (hFile==INVALID_HANDLE_VALUE) thrF("Failed to open file: %S", winError());
|
||||||
LARGE_INTEGER fileSize;
|
LARGE_INTEGER fileSize;
|
||||||
if (!GetFileSizeEx(hFile, &fileSize)) {
|
if (!GetFileSizeEx(hFile, &fileSize)) {
|
||||||
@ -329,7 +343,7 @@ B mmap_file(B path) {
|
|||||||
}
|
}
|
||||||
u64 len = fileSize.QuadPart;
|
u64 len = fileSize.QuadPart;
|
||||||
|
|
||||||
HANDLE hMapFile = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
HANDLE hMapFile = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||||
if (hMapFile==INVALID_HANDLE_VALUE) {
|
if (hMapFile==INVALID_HANDLE_VALUE) {
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
thrF("Failed to create file mapping: %S", winError());
|
thrF("Failed to create file mapping: %S", winError());
|
||||||
@ -379,39 +393,61 @@ void mmap_init() { }
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
bool dir_create(B path) {
|
bool dir_create(B path) {
|
||||||
|
#if !defined(_WIN32)
|
||||||
char* p = toCStr(path);
|
char* p = toCStr(path);
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
bool r = mkdir(p, S_IRWXU) == 0;
|
||||||
bool r = _mkdir(p) == 0;
|
|
||||||
#else
|
|
||||||
bool r = mkdir(p, S_IRWXU) == 0;
|
|
||||||
#endif
|
|
||||||
freeCStr(p);
|
freeCStr(p);
|
||||||
|
#else
|
||||||
|
WCHAR* p = toWStr(path);
|
||||||
|
bool r = _wmkdir(p) == 0;
|
||||||
|
freeWStr(p);
|
||||||
|
#endif
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool path_rename(B old_path, B new_path) {
|
bool path_rename(B old_path, B new_path) {
|
||||||
|
#if !defined(_WIN32)
|
||||||
char* old = toCStr(old_path);
|
char* old = toCStr(old_path);
|
||||||
char* new = toCStr(new_path);
|
char* new = toCStr(new_path);
|
||||||
// TODO Fix race condition, e.g., with renameat2 on Linux, etc.
|
// TODO Fix race condition, e.g., with renameat2 on Linux, etc.
|
||||||
bool ok = access(new, F_OK) != 0 && rename(old, new) == 0;
|
bool ok = access(new, F_OK) != 0 && rename(old, new) == 0;
|
||||||
freeCStr(new);
|
freeCStr(new);
|
||||||
freeCStr(old);
|
freeCStr(old);
|
||||||
|
#else
|
||||||
|
WCHAR* old = toWStr(old_path);
|
||||||
|
WCHAR* new = toWStr(new_path);
|
||||||
|
bool ok = _waccess(new, F_OK) != 0 && _wrename(old, new) == 0;
|
||||||
|
freeWStr(new);
|
||||||
|
freeWStr(old);
|
||||||
|
#endif
|
||||||
dec(old_path);
|
dec(old_path);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool path_remove(B path) {
|
bool path_remove(B path) {
|
||||||
|
#if !defined(_WIN32)
|
||||||
char* p = toCStr(path);
|
char* p = toCStr(path);
|
||||||
bool ok = unlink(p) == 0;
|
bool ok = unlink(p) == 0;
|
||||||
freeCStr(p);
|
freeCStr(p);
|
||||||
|
#else
|
||||||
|
WCHAR* p = toWStr(path);
|
||||||
|
bool ok = _wunlink(p) == 0;
|
||||||
|
freeWStr(p);
|
||||||
|
#endif
|
||||||
dec(path);
|
dec(path);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
int path_stat(struct stat* s, B path) { // doesn't consume; get stat of s; errors if path isn't string; returns non-zero on failure
|
int path_stat(struct stat* s, B path) { // doesn't consume; get stat of s; errors if path isn't string; returns non-zero on failure
|
||||||
|
#if !defined(_WIN32)
|
||||||
char* p = toCStr(path);
|
char* p = toCStr(path);
|
||||||
int r = stat(p, s);
|
int r = stat(p, s);
|
||||||
freeCStr(p);
|
freeCStr(p);
|
||||||
|
#else
|
||||||
|
WCHAR* p = toWStr(path);
|
||||||
|
int r = wstat(p, s);
|
||||||
|
freeWStr(p);
|
||||||
|
#endif
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,13 +26,13 @@ FORCE_INLINE void utf16_w(WCHAR** buf_i, u32 c)
|
|||||||
*buf_i = buf;
|
*buf_i = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void toUTF16(B x, WCHAR* p) {
|
static void toUTF16(B x, WCHAR* p) {
|
||||||
SGetU(x)
|
SGetU(x)
|
||||||
usz ia = IA(x);
|
usz ia = IA(x);
|
||||||
for (u64 i = 0; i < ia; ++i) utf16_w(&p, o2cG(GetU(x,i)));
|
for (u64 i = 0; i < ia; ++i) utf16_w(&p, o2cG(GetU(x,i)));
|
||||||
}
|
}
|
||||||
|
|
||||||
B utf16Decode(const WCHAR* s, i64 len) {
|
static B utf16Decode(const WCHAR* s, i64 len) {
|
||||||
#define UTF16_MASK 0xFC00
|
#define UTF16_MASK 0xFC00
|
||||||
#define UTF16_IS_HI(WC) ((UTF16_MASK&(WC))==0xD800) /* 0xD800..0xDBFF */
|
#define UTF16_IS_HI(WC) ((UTF16_MASK&(WC))==0xD800) /* 0xD800..0xDBFF */
|
||||||
#define UTF16_IS_LO(WC) ((UTF16_MASK&(WC))==0xDC00) /* 0xDC00..0xDFFF */
|
#define UTF16_IS_LO(WC) ((UTF16_MASK&(WC))==0xDC00) /* 0xDC00..0xDFFF */
|
||||||
@ -64,13 +64,13 @@ B utf16Decode(const WCHAR* s, i64 len) {
|
|||||||
#undef UTF16_SURROGATE
|
#undef UTF16_SURROGATE
|
||||||
}
|
}
|
||||||
|
|
||||||
static WCHAR* toWideStr(B x) { // doesn't consume
|
static WCHAR* toWStr(B x) { // doesn't consume
|
||||||
u64 len = utf16lenB(x);
|
u64 len = utf16lenB(x);
|
||||||
TALLOC(WCHAR, p, len+1);
|
TALLOC(WCHAR, p, len+1);
|
||||||
toUTF16(x, p);
|
toUTF16(x, p);
|
||||||
p[len] = 0;
|
p[len] = 0;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
static void freeWideStr(WCHAR* p) {
|
static void freeWStr(WCHAR* p) {
|
||||||
TFREE(p);
|
TFREE(p);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user