Skip to content

Commit

Permalink
COMMON: Added SAIL_WINDOWS_UTF8_PATHS (#207)
Browse files Browse the repository at this point in the history
* COMMON: Added SAIL_WINDOWS_UTF8_PATHS

* COMMON: Fix allocation size

* SAIL: Print SAIL_WINDOWS_UTF8_PATHS
  • Loading branch information
HappySeaFox authored Mar 26, 2024
1 parent bf70ced commit 44eb715
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 30 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ dynamically loaded plugins." OFF "BUILD_SHARED_LIBS" ON)
option(SAIL_THIRD_PARTY_CODECS_PATH "Enable loading third-party codecs from the ';'-separated paths specified in \
the SAIL_THIRD_PARTY_CODECS_PATH environment variable." ON)
option(SAIL_THREAD_SAFE "Enable working in multi-threaded environments by locking the internal context with a mutex." ON)
if (WIN32)
option(SAIL_WINDOWS_UTF8_PATHS "Convert file paths to UTF-8 on Windows." ON)
endif()

if (SAIL_ENABLE_OPENMP)
sail_check_openmp()
Expand Down Expand Up @@ -341,6 +344,9 @@ message("* SAIL_OPENMP_SCHEDULE: ${SAIL_OPENMP_SCHEDULE}")
message("* SAIL_OPENMP_FLAGS: ${SAIL_OPENMP_FLAGS}")
message("* SAIL_OPENMP_INCLUDE_DIRS: ${SAIL_OPENMP_INCLUDE_DIRS}")
message("* SAIL_OPENMP_LIBS: ${SAIL_OPENMP_LIBS}")
if (WIN32)
message("* SAIL_WINDOWS_UTF8_PATHS: ${SAIL_WINDOWS_UTF8_PATHS}")
endif()
message("*")
message("* [*] - these options depend on other options, their values may be altered by CMake.")
message("* For example, if you configure with -DBUILD_SHARED_LIBS=OFF -DSAIL_COMBINE_CODECS=OFF,")
Expand Down
2 changes: 2 additions & 0 deletions src/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,6 @@
/* OpenMP scheduling algorithm. */
#cmakedefine SAIL_OPENMP_SCHEDULE @SAIL_OPENMP_SCHEDULE@

#cmakedefine SAIL_WINDOWS_UTF8_PATHS

#endif
165 changes: 135 additions & 30 deletions src/sail-common/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,10 +549,22 @@ bool sail_path_exists(const char *path) {
return false;
}

#ifdef _MSC_VER
return _access(path, 0) == 0;
#ifdef SAIL_WINDOWS_UTF8_PATHS
wchar_t *wpath;
SAIL_TRY_OR_EXECUTE(sail_multibyte_to_wchar(path, &wpath),
/* on error */ return false);

bool result = _waccess(wpath, 0) == 0;

sail_free(wpath);

return result;
#else
return access(path, 0) == 0;
#ifdef _MSC_VER
return _access(path, 0) == 0;
#else
return access(path, 0) == 0;
#endif
#endif
}

Expand All @@ -563,22 +575,39 @@ bool sail_is_dir(const char *path) {
return false;
}

#ifdef _MSC_VER
#ifdef SAIL_WINDOWS_UTF8_PATHS
wchar_t *wpath;
SAIL_TRY_OR_EXECUTE(sail_multibyte_to_wchar(path, &wpath),
/* on error */ return false);

struct _stat attrs;

if (_stat(path, &attrs) != 0) {
if (_wstat(wpath, &attrs) != 0) {
sail_free(wpath);
return false;
}

sail_free(wpath);

return (attrs.st_mode & _S_IFMT) == _S_IFDIR;
#else
struct stat attrs;
#ifdef _MSC_VER
struct _stat attrs;

if (stat(path, &attrs) != 0) {
return false;
}
if (_stat(path, &attrs) != 0) {
return false;
}

return (attrs.st_mode & _S_IFMT) == _S_IFDIR;
#else
struct stat attrs;

if (stat(path, &attrs) != 0) {
return false;
}

return S_ISDIR(attrs.st_mode);
return S_ISDIR(attrs.st_mode);
#endif
#endif
}

Expand All @@ -589,22 +618,39 @@ bool sail_is_file(const char *path) {
return false;
}

#ifdef _MSC_VER
#ifdef SAIL_WINDOWS_UTF8_PATHS
wchar_t *wpath;
SAIL_TRY_OR_EXECUTE(sail_multibyte_to_wchar(path, &wpath),
/* on error */ return false);

struct _stat attrs;

if (_stat(path, &attrs) != 0) {
if (_wstat(wpath, &attrs) != 0) {
sail_free(wpath);
return false;
}

sail_free(wpath);

return (attrs.st_mode & _S_IFMT) == _S_IFREG;
#else
struct stat attrs;
#ifdef _MSC_VER
struct _stat attrs;

if (stat(path, &attrs) != 0) {
return false;
}
if (_stat(path, &attrs) != 0) {
return false;
}

return S_ISREG(attrs.st_mode);
return (attrs.st_mode & _S_IFMT) == _S_IFREG;
#else
struct stat attrs;

if (stat(path, &attrs) != 0) {
return false;
}

return S_ISREG(attrs.st_mode);
#endif
#endif
}

Expand All @@ -614,31 +660,48 @@ sail_status_t sail_file_size(const char *path, size_t *size) {

bool is_file;

#ifdef _MSC_VER
#ifdef SAIL_WINDOWS_UTF8_PATHS
wchar_t *wpath;
SAIL_TRY_OR_EXECUTE(sail_multibyte_to_wchar(path, &wpath),
/* on error */ return false);

struct _stat attrs;

if (_stat(path, &attrs) != 0) {
if (_wstat(wpath, &attrs) != 0) {
sail_free(wpath);
return false;
}

sail_free(wpath);

is_file = (attrs.st_mode & _S_IFMT) == _S_IFREG;
#else
struct stat attrs;
#ifdef _MSC_VER
struct _stat attrs;

if (stat(path, &attrs) != 0) {
return false;
}
if (_stat(path, &attrs) != 0) {
return false;
}

is_file = (attrs.st_mode & _S_IFMT) == _S_IFREG;
#else
struct stat attrs;

if (stat(path, &attrs) != 0) {
return false;
}

is_file = S_ISREG(attrs.st_mode);
is_file = S_ISREG(attrs.st_mode);
#endif
#endif

if (!is_file) {
if (is_file) {
*size = attrs.st_size;
} else {
SAIL_LOG_ERROR("'%s' is not a file", path);
SAIL_LOG_AND_RETURN(SAIL_ERROR_OPEN_FILE);
}

*size = attrs.st_size;

return SAIL_OK;
}

Expand All @@ -650,10 +713,20 @@ sail_status_t sail_file_contents_into_data(const char *path, void *data) {
size_t size;
SAIL_TRY(sail_file_size(path, &size));

#ifdef _MSC_VER
FILE *f = _fsopen(path, "rb", _SH_DENYWR);
#ifdef SAIL_WINDOWS_UTF8_PATHS
/* FIXME: We convert to UTF-8 twice, in sail_file_size() and here. */
wchar_t *wpath;
SAIL_TRY(sail_multibyte_to_wchar(path, &wpath));

FILE *f = _wfsopen(wpath, L"rb", _SH_DENYWR);

sail_free(wpath);
#else
FILE *f = fopen(path, "rb");
#ifdef _MSC_VER
FILE *f = _fsopen(path, "rb", _SH_DENYWR);
#else
FILE *f = fopen(path, "rb");
#endif
#endif

if (f == NULL) {
Expand Down Expand Up @@ -810,3 +883,35 @@ uint64_t sail_reverse_uint64(uint64_t v)
(view[7] << 0);
#endif
}

#ifdef SAIL_WINDOWS_UTF8_PATHS
sail_status_t sail_multibyte_to_wchar(const char *str, wchar_t **wstr) {

SAIL_CHECK_PTR(str);
SAIL_CHECK_PTR(wstr);

/* Detect buffer size. */
int chars_needed = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);

if (chars_needed <= 0) {
SAIL_LOG_ERROR("MultiByteToWideChar() failed. Error: 0x%X", GetLastError());
SAIL_LOG_AND_RETURN(SAIL_ERROR_INVALID_ARGUMENT);
}

wchar_t *wstr_local;
SAIL_TRY(sail_malloc(chars_needed * sizeof(wchar_t), &wstr_local));

/* Actually convert. */
int result = MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr_local, chars_needed);

if (result <= 0) {
sail_free(wstr_local);
SAIL_LOG_ERROR("MultiByteToWideChar() failed. Error: 0x%X", GetLastError());
SAIL_LOG_AND_RETURN(SAIL_ERROR_INVALID_ARGUMENT);
}

*wstr = wstr_local;

return SAIL_OK;
}
#endif
9 changes: 9 additions & 0 deletions src/sail-common/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,15 @@ SAIL_EXPORT uint32_t sail_reverse_uint32(uint32_t v);
*/
SAIL_EXPORT uint64_t sail_reverse_uint64(uint64_t v);

/*
* Converts a character string to a UTF-16 string. Available on Windows only.
*
* Returns SAIL_OK on success.
*/
#ifdef SAIL_WINDOWS_UTF8_PATHS
SAIL_EXPORT sail_status_t sail_multibyte_to_wchar(const char *str, wchar_t **wstr);
#endif

/* extern "C" */
#ifdef __cplusplus
}
Expand Down

0 comments on commit 44eb715

Please sign in to comment.