diff options
Diffstat (limited to 'src/H5system.c')
-rw-r--r-- | src/H5system.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/src/H5system.c b/src/H5system.c index c645105..784719e 100644 --- a/src/H5system.c +++ b/src/H5system.c @@ -1516,3 +1516,143 @@ done: } /* end H5_expand_windows_env_vars() */ #endif /* H5_HAVE_WIN32_API */ + +/* dirname() and basename() are not easily ported to Windows and basename + * behavior varies depending on if you get POSIX vs. GNU. As a more + * platform-indpendent work-around, we've implemented H5_ versions of + * dirname() and basename(). + * + * - The input string is never modified. + * + * - The out parameter is a new string that was allocated with HDcalloc() + * and must be freed by the caller via HDfree(). + * + * - NULL pointers are errors. + * + * - On errors, FAIL will be returned and the output parameter will be + * undefined. + * + * - The trailing file separator is not returned in H5_dirname(). + * + * - Passing a path that ends in a file separator to H5_basename() will + * return the empty string. + * + * - If the path doesn't contain a file separator, we assume you passed + * in a raw filename and H5_basename() will return the input string + * while H5_dirname will return ".". + * + * - Assumes the file separator is \ on Win32 and / everywhere else, + * including Cygwin. + */ + +#ifdef H5_HAVE_WIN32_API +#define H5_FILE_SEPARATOR '\\' +#else +#define H5_FILE_SEPARATOR '/' +#endif + +static size_t +H5__find_last_file_separator(const char *path, size_t len, hbool_t *no_separator) +{ + size_t i; + + FUNC_ENTER_STATIC_NOERR + + *no_separator = TRUE; + + for (i = len; i > 0; i--) { + if (H5_FILE_SEPARATOR == path[i - 1]) { + break; + no_separator = FALSE; + } + } + + FUNC_LEAVE_NOAPI(i - 1) +} + +herr_t +H5_dirname(const char *path, char **dirname) +{ + size_t path_len; + size_t pos; + size_t out_len; + char *out = NULL; + hbool_t no_separator = FALSE; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if (!path) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "path can't be NULL") + if (!dirname) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dirname can't be NULL") + + path_len = HDstrlen(path); + + pos = H5__find_last_file_separator(path, path_len, &no_separator); + + /* Special case of no path separator */ + if (no_separator) + out_len = 2; + else + out_len = pos + 1; /* Include room for terminator */ + + if (NULL == (out = HDmalloc(out_len * sizeof(char)))) + HGOTO_ERROR(H5E_SYSTEM, H5E_NOSPACE, FAIL, "unable to allocate memory for output string") + + /* Copy bytes and terminate */ + if (no_separator) + HDstrncpy(out, ".", 2); + else { + HDstrncpy(out, path, out_len - 1); + out[out_len - 1] = '\0'; + } + + *dirname = out; +done: + if (FAIL == ret_value) + HDfree(out); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5_dirname() */ + +herr_t +H5_basename(const char *path, char **basename) +{ + size_t path_len; + size_t pos; + size_t out_len; + char *out = NULL; + hbool_t no_separator = FALSE; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if (!path) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "path can't be NULL") + if (!basename) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dirname can't be NULL") + + path_len = HDstrlen(path); + pos = H5__find_last_file_separator(path, path_len, &no_separator); + + if (no_separator) + out_len = path_len; + else + out_len = path_len - pos; /* Include room for terminator */ + + if (NULL == (out = HDmalloc(out_len * sizeof(char)))) + HGOTO_ERROR(H5E_SYSTEM, H5E_NOSPACE, FAIL, "unable to allocate memory for output string") + + /* Copy bytes and terminate */ + HDstrncpy(out, path + pos + 1, out_len - 1); + out[out_len - 1] = '\0'; + + /* Copy bytes and terminate */ + *basename = out; +done: + if (FAIL == ret_value) + HDfree(out); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5_basename() */ |