Windows: use utf16 for file functions
This commit is contained in:
parent
40609b2f5f
commit
e12ca55ee0
@ -9,13 +9,26 @@
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <direct.h>
|
||||
#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
|
||||
|
||||
|
||||
FILE* file_open(B path, char* desc, char* mode) { // doesn't consume
|
||||
#if !defined(_WIN32)
|
||||
char* p = toCStr(path);
|
||||
FILE* f = fopen(p, mode);
|
||||
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);
|
||||
return f;
|
||||
}
|
||||
@ -301,9 +314,9 @@ static NOINLINE Arr* mmapH_slice(B x, usz s, usz ia) {
|
||||
}
|
||||
|
||||
B mmap_file(B path) {
|
||||
#if !defined(_WIN32)
|
||||
char* p = toCStr(path);
|
||||
dec(path);
|
||||
#if !defined(_WIN32)
|
||||
int fd = open(p, 0);
|
||||
freeCStr(p);
|
||||
if (fd==-1) thrF("Failed to open file: %S", strerror(errno));
|
||||
@ -316,11 +329,12 @@ B mmap_file(B path) {
|
||||
}
|
||||
#else
|
||||
// see https://learn.microsoft.com/en-us/windows/win32/memory/creating-a-view-within-a-file
|
||||
|
||||
HANDLE hFile = CreateFileA(
|
||||
WCHAR* p = toWStr(path);
|
||||
dec(path);
|
||||
HANDLE hFile = CreateFileW(
|
||||
p, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
freeCStr(p);
|
||||
freeWStr(p);
|
||||
if (hFile==INVALID_HANDLE_VALUE) thrF("Failed to open file: %S", winError());
|
||||
LARGE_INTEGER fileSize;
|
||||
if (!GetFileSizeEx(hFile, &fileSize)) {
|
||||
@ -329,7 +343,7 @@ B mmap_file(B path) {
|
||||
}
|
||||
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) {
|
||||
CloseHandle(hFile);
|
||||
thrF("Failed to create file mapping: %S", winError());
|
||||
@ -341,7 +355,7 @@ B mmap_file(B path) {
|
||||
thrF("Failed to map view of file: %S", winError());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
MmapHolder* holder = m_arrUnchecked(sizeof(MmapHolder), t_mmapH, len);
|
||||
holder->a = data;
|
||||
#if !defined(_WIN32)
|
||||
@ -379,39 +393,61 @@ void mmap_init() { }
|
||||
#include <sys/stat.h>
|
||||
|
||||
bool dir_create(B path) {
|
||||
#if !defined(_WIN32)
|
||||
char* p = toCStr(path);
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
bool r = _mkdir(p) == 0;
|
||||
#else
|
||||
bool r = mkdir(p, S_IRWXU) == 0;
|
||||
#endif
|
||||
bool r = mkdir(p, S_IRWXU) == 0;
|
||||
freeCStr(p);
|
||||
#else
|
||||
WCHAR* p = toWStr(path);
|
||||
bool r = _wmkdir(p) == 0;
|
||||
freeWStr(p);
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
bool path_rename(B old_path, B new_path) {
|
||||
#if !defined(_WIN32)
|
||||
char* old = toCStr(old_path);
|
||||
char* new = toCStr(new_path);
|
||||
// TODO Fix race condition, e.g., with renameat2 on Linux, etc.
|
||||
bool ok = access(new, F_OK) != 0 && rename(old, new) == 0;
|
||||
freeCStr(new);
|
||||
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);
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool path_remove(B path) {
|
||||
#if !defined(_WIN32)
|
||||
char* p = toCStr(path);
|
||||
bool ok = unlink(p) == 0;
|
||||
freeCStr(p);
|
||||
#else
|
||||
WCHAR* p = toWStr(path);
|
||||
bool ok = _wunlink(p) == 0;
|
||||
freeWStr(p);
|
||||
#endif
|
||||
dec(path);
|
||||
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
|
||||
#if !defined(_WIN32)
|
||||
char* p = toCStr(path);
|
||||
int r = stat(p, s);
|
||||
freeCStr(p);
|
||||
#else
|
||||
WCHAR* p = toWStr(path);
|
||||
int r = wstat(p, s);
|
||||
freeWStr(p);
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@ -26,13 +26,13 @@ FORCE_INLINE void utf16_w(WCHAR** buf_i, u32 c)
|
||||
*buf_i = buf;
|
||||
}
|
||||
|
||||
void toUTF16(B x, WCHAR* p) {
|
||||
static void toUTF16(B x, WCHAR* p) {
|
||||
SGetU(x)
|
||||
usz ia = IA(x);
|
||||
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_IS_HI(WC) ((UTF16_MASK&(WC))==0xD800) /* 0xD800..0xDBFF */
|
||||
#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
|
||||
}
|
||||
|
||||
static WCHAR* toWideStr(B x) { // doesn't consume
|
||||
static WCHAR* toWStr(B x) { // doesn't consume
|
||||
u64 len = utf16lenB(x);
|
||||
TALLOC(WCHAR, p, len+1);
|
||||
toUTF16(x, p);
|
||||
p[len] = 0;
|
||||
return p;
|
||||
}
|
||||
static void freeWideStr(WCHAR* p) {
|
||||
static void freeWStr(WCHAR* p) {
|
||||
TFREE(p);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user