diff --git a/src/utils/file.c b/src/utils/file.c index 26db5a48..28fcabf7 100644 --- a/src/utils/file.c +++ b/src/utils/file.c @@ -29,6 +29,21 @@ static DIR* dir_open(B path) { // doesn't consume return f; } +#if defined(_WIN32) || defined(_WIN64) +#define PREFERRED_SEP '\\' +static bool isPathSep(uint32_t c) { return c=='/' || c=='\\'; } +static bool isAbsolutePath(B x) { + char* p = toCStr(x); + bool r = winIsAbsolute(p); + freeCStr(p); + return r; +} +#else +#define PREFERRED_SEP '/' +static bool isPathSep(uint32_t c) { return c=='/'; } +static bool isAbsolutePath(B x) { return o2cG(IGetU(x, 0))=='/'; } +#endif + I8Arr* stream_bytes(FILE* f) { B r = emptyIVec(); @@ -114,17 +129,17 @@ B path_rel(B base, B rel) { // consumes rel; assumes base is a char vector or bi usz ria = IA(rel); if (RNK(rel)!=1) thrM("Paths must be character vectors"); guaranteeStr(rel); - if (ria>0 && o2cG(GetU(rel, 0))=='/') return rel; + if (ria>0 && isAbsolutePath(rel)) return rel; if (q_N(base)) thrM("Using relative path with no absolute base path known"); if (ria==0) { dec(rel); return incG(base); } usz bia = IA(base); if (bia==0) return rel; SGetU(base) - bool has = o2cG(GetU(base, bia-1))=='/'; + bool has = isPathSep(o2cG(GetU(base, bia-1))); u32* rp; B r = m_c32arrv(&rp, bia+ria+(has?0:1)); usz ri = 0; for (usz i = 0; i < bia-(has?1:0); i++) rp[ri++] = o2cG(GetU(base, i)); - rp[ri++] = '/'; + rp[ri++] = PREFERRED_SEP; for (usz i = 0; i < ria; i++) rp[ri++] = o2cG(GetU(rel, i)); dec(rel); return r; @@ -137,11 +152,11 @@ B path_parent(B path) { if (pia==0) thrM("Empty file path"); guaranteeStr(path); for (i64 i = (i64)pia-2; i >= 0; i--) { - if (o2cG(GetU(path, i))=='/') return taga(arr_shVec(TI(path,slice)(path, 0, i+1))); + if (isPathSep(o2cG(GetU(path, i)))) return taga(arr_shVec(TI(path,slice)(path, 0, i+1))); } - if (o2cG(GetU(path, 0))=='/') return path; + if (isAbsolutePath(path)) return path; dec(path); - u32* rp; B r = m_c32arrv(&rp, 2); rp[0] = '.'; rp[1] = '/'; + u32* rp; B r = m_c32arrv(&rp, 2); rp[0] = '.'; rp[1] = PREFERRED_SEP; return r; } B path_name(B path) { @@ -151,7 +166,7 @@ B path_name(B path) { if (pia==0) thrM("Empty file path"); guaranteeStr(path); for (i64 i = (i64)pia-1; i >= 0; i--) { - if (o2cG(GetU(path, i))=='/') { + if (isPathSep(o2cG(GetU(path, i)))) { if (i == pia-1) thrF("File path ended with a slash: \"%R\"", path); return taga(arr_shVec(TI(path,slice)(path, i+1, pia - (i+1)))); } diff --git a/src/windows/realpath.c b/src/windows/realpath.c index 327a2652..50a9528f 100644 --- a/src/windows/realpath.c +++ b/src/windows/realpath.c @@ -2,8 +2,8 @@ #include "realpath.h" char* realpath (const char *__restrict path, char *__restrict resolved_path) { - unsigned long len=strlen(path)+1; - void* r = malloc(len); - memcpy(r, path, len); - return r; + return _fullpath(NULL, path, 0); +} +bool winIsAbsolute(const char* path) { // TODO something more proper + return *path && path[1]==':' && (!path[2] || path[2]=='/' || path[2]=='\\'); } \ No newline at end of file diff --git a/src/windows/realpath.h b/src/windows/realpath.h index aed7bd6b..bfe555c7 100644 --- a/src/windows/realpath.h +++ b/src/windows/realpath.h @@ -1,6 +1,7 @@ #ifndef REALPATH_H #define REALPATH_H -char* realpath (const char *__restrict path, char *__restrict resolved_path); +char* realpath(const char *__restrict path, char *__restrict resolved_path); +bool winIsAbsolute(const char* path); #endif /* REALPATH_H */ \ No newline at end of file