%% options copyright owner = Dirk Krause copyright year = 2015-xxxx SPDX-License-Identifier: BSD-3-Clause %% header /** @file String operations for path names (dkChar characters). */ #ifndef DK4CONF_H_INCLUDED #if DK4_BUILDING_DKTOOLS4 #include "dk4conf.h" #else #include #endif #endif #ifndef DK4TYPES_H_INCLUDED #if DK4_BUILDING_DKTOOLS4 #include "dk4types.h" #else #include #endif #endif #ifndef DK4ERROR_H_INCLUDED #if DK4_BUILDING_DKTOOLS4 #include "dk4error.h" #else #include #endif #endif #if DK4_HAVE_WCHAR_H #ifndef WCHAR_H_INCLUDED #include #define WCHAR_H_INCLUDED 1 #endif #endif #ifdef __cplusplus extern "C" { #endif /** Check whether a file name is an absolute path. CRT on Windows: Not used. @param path Path name to check. @return 1 for absolute path, 0 for other path. */ int dk4path_is_absolute(const dkChar *path); /** Check whether a file name is a relative path. CRT on Windows: Not used. @param path Path name to check. @return 1 for absolute path, 0 for other path. */ int dk4path_is_relative(const dkChar *path); /** Append path filename to path name already stored in buffer. Resolve . and .. for current directory and parent directory. CRT on Windows: Optional, disabling CRT degrades performance. @param buffer Buffer already containing a path. @param sz Buffer size. @param filename Relative file name to append to buffer. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if buffer or filename is NULL or sz is 0, - DK4_E_MATH_OVERFLOW
if filename is too long, - DK4_E_MEMORY
if allocation of a filename copy fails, - DK4_E_SYNTAX
if too many .. in filename, - DK4_E_BUFFER_TOO_SMALL
if buffer size is too small. */ int dk4path_append( dkChar *buffer, size_t sz, const dkChar *filename, dk4_er_t *erp ); /** Find pointer to suffix. CRT on Windows: Not used. @param filename File name to find suffix for. @param erp Error report, may be NULL. @return Pointer to suffix dot if found, NULL otherwise. Error codes: - DK4_E_INVALID_ARGUMENTS
if filename is NULL, - DK4_E_NOT_FOUND
if the file name does not contain a suffix. */ dkChar * dk4path_get_suffix(const dkChar *filename, dk4_er_t *erp); /** Correct file name separators from slash to backslash on Windows, vice versa on other systems. CRT on Windows: Not used. @param filename File name to correct. */ void dk4path_correct_sep(dkChar *filename); /** Check whether file name needs expansion on Windows. CRT on Windows: Not used. @param filename File name to check. @return 1 if expansion is necessary, 0 otherwise. */ int dk4path_must_expand(const dkChar *filename); /** Check whether filename is in the specified parent directory. It may be equal to parent or below the parent directory. @param filename File or directory name to check. @param parent Parent directory. @param erp Error report, may be NULL. @return 1 for true, 0 for false. Error codes: - DK4_E_INVALID_ARGUMENTS
if filename or parent is NULL, - DK4_E_BUFFER_TOO_SMALL
if filename is too long for an internal buffer. */ int dk4path_is_in_subdir(const dkChar *filename,const dkChar *parent,dk4_er_t *erp); /** Create file name with specified suffix. @param pdst Destination buffer. @param szdst Size of pdst (number of dkChar). @param srcname Source file name. @param newsu New file suffix. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if pdst or srcname or newsu is NULL or szdst is 0, - DK4_E_BUFFER_TOO_SMALL
if the dst buffer is too small. - DK4_E_MATH_OVERFLOW
if a mathematical overflow occured in size calculation, */ int dk4path_set_suffix( dkChar *pdst, size_t szdst, dkChar const *srcname, dkChar const *newsu, dk4_er_t *erp ); /** Create a dynamic copy of a file name with changed suffix. @param srcname Old file name. @param newsu New suffix. @param erp Error report, may be NULL. @return Valid pointer to changed file name on success, NULL on error. On success call dk4mem_free() on the pointer when no longer needed to release the memory. Error codes: - DK4_E_INVALID_ARGUMENTS
if srcname or newsu is NULL, - DK4_E_BUG
if a bug occured, - DK4_E_MATH_OVERFLOW
if a mathematical overflow occured in size calculation, - DK4_E_MEMORY_ALLOCATION_FAILED
with mem.elsize and mem.nelem set if there is not enough memory available. */ dkChar * dk4path_dup_change_suffix( dkChar const *srcname, dkChar const *newsu, dk4_er_t *erp ); /** Calculate buffer size required to concatenate a directory name and a file name. @param dirname Directory name. @param filename File name. @param erp Error report, may be NULL. @return Buffer size for concatenated names including the finalizer byte on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if dirname or filename is NULL, - DK4_E_MATH_OVERFLOW
if the calculation results in a numeric overflow. */ size_t dk4path_concatenate_size( dkChar const *dirname, dkChar const *filename, dk4_er_t *erp ); /** Concatenate a directory name and a file name into an existing buffer. This function simply concatenates directory name and file name, . and .. for current and parent directory are not resolved. @param buffer Result buffer for combined file name. @param szbuf Buffer size (number of dkChar). @param dirn Directory name. @param filen File name. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if buffer, dirn or filen is NULL or szbuf is 0, - DK4_E_BUFFER_TOO_SMALL
if the buffer is too small. */ int dk4path_concatenate_buffer( dkChar *buffer, size_t szbuf, dkChar const *dirn, dkChar const *filen, dk4_er_t *erp ); /** Concatenate a directory name and a file name into newly allocated memory. This function simply concatenates directory name and file name, . and .. for current and parent directory are not resolved. @param dirn Directory name. @param filen File name. @param erp Error report, may be NULL. @return Valid pointer to newly allocated memory containing the concatenation on success, NULL on error. On success use dk4mem_free() to release the memory when done with it. Error codes: - DK4_E_INVALID_ARGUMENTS
if dirn or filen is NULL, - DK4_E_MATH_OVERFLOW
if the size calculation results in a numeric overflow. - DK4_E_MEMORY_ALLOCATION_FAILED
if the memory allocation failed, - DK4_E_BUFFER_TOO_SMALL
if the buffer is too small. */ dkChar * dk4path_concatenate_new( dkChar const *dirn, dkChar const *filen, dk4_er_t *erp ); #ifdef __cplusplus } #endif %% module #include "dk4conf.h" #include "dk4pathd.h" #if DK4_CHAR_SIZE > 1 #include "dk4pathw.h" #else #include "dk4path8.h" #endif #if DK4_HAVE_ASSERT_H #ifndef ASSERT_H_INCLUDED #include #define ASSERT_H_INCLUDED 1 #endif #endif #include "dk4mem.h" #include "dk4mpl.h" #include "dk4strd.h" $!trace-include int dk4path_is_absolute(const dkChar *path) { #if DK4_USE_ASSERT assert(NULL != path); #endif #if DK4_CHAR_SIZE > 1 return (dk4pathw_is_absolute(path)); #else return (dk4path8_is_absolute(path)); #endif } int dk4path_is_relative(const dkChar *path) { #if DK4_USE_ASSERT assert(NULL != path); #endif #if DK4_CHAR_SIZE > 1 return (dk4pathw_is_relative(path)); #else return (dk4path8_is_relative(path)); #endif } int dk4path_append( dkChar *buffer, size_t sz, const dkChar *filename, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != buffer); assert(0 < sz); assert(NULL != filename); #endif #if DK4_CHAR_SIZE > 1 return (dk4pathw_append(buffer, sz, filename, erp)); #else return (dk4path8_append(buffer, sz, filename, erp)); #endif } dkChar * dk4path_get_suffix(const dkChar *filename, dk4_er_t *erp) { #if DK4_USE_ASSERT assert(NULL != filename); #endif #if DK4_CHAR_SIZE > 1 return (dk4pathw_get_suffix(filename, erp)); #else return (dk4path8_get_suffix(filename, erp)); #endif } void dk4path_correct_sep(dkChar *filename) { #if DK4_USE_ASSERT assert(NULL != filename); #endif #if DK4_CHAR_SIZE > 1 dk4pathw_correct_sep(filename); #else dk4path8_correct_sep(filename); #endif } int dk4path_must_expand(const dkChar *filename) { #if DK4_USE_ASSERT assert(NULL != filename); #endif #if DK4_CHAR_SIZE > 1 return (dk4pathw_must_expand(filename)); #else return (dk4path8_must_expand(filename)); #endif } int dk4path_is_in_subdir(const dkChar *filename,const dkChar *parent,dk4_er_t *erp) { dkChar buf[DK4_MAX_PATH]; size_t szf; size_t szp; int back = 0; $? "+ dk4path_is_in_subdir f=\"%!ds\" p=\"%!ds\"", filename, parent #if DK4_USE_ASSERT assert(NULL != filename); assert(NULL != parent); #endif if ((NULL != filename) && (NULL != parent)) { if (0 != dk4str_cpy_s(buf, DK4_SIZEOF(buf,dkChar), filename, erp)) { szf = dk4str_len(buf); szp = dk4str_len(parent); if (szf > szp) { $? ". filename larger than parent" #if DK4_ON_WINDOWS || DK4_HAVE_BACKSLASH_AS_SEP if (buf[szp] == dkT('\\')) #else if (buf[szp] == dkT('/')) #endif { $? ". separator at right place" buf[szp] = dkT('\0'); if (0 == dk4str_pathcmp(buf, parent)) { back = 1; $? ". match" } #if DK4_ON_WINDOWS || DK4_HAVE_BACKSLASH_AS_SEP buf[szp] = dkT('\\'); #else buf[szp] = dkT('/'); #endif } } else { if (szf == szp) { $? ". equal lengths" if (0 == dk4str_pathcmp(buf, parent)) { back = 1; $? ". match" } } } } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } $? "- dk4path_is_in_subdir %d", back return back; } int dk4path_set_suffix( dkChar *pdst, size_t szdst, dkChar const *srcname, dkChar const *newsu, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != pdst); assert(0 < szdst); assert(NULL != srcname); assert(NULL != newsu); #endif #if DK4_CHAR_SIZE > 1 return (dk4pathw_set_suffix(pdst, szdst, srcname, newsu, erp)); #else return (dk4path8_set_suffix(pdst, szdst, srcname, newsu, erp)); #endif } dkChar * dk4path_dup_change_suffix( dkChar const *srcname, dkChar const *newsu, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != srcname); assert(NULL != newsu); #endif #if DK4_CHAR_SIZE > 1 return (dk4pathw_dup_change_suffix(srcname, newsu, erp)); #else return (dk4path8_dup_change_suffix(srcname, newsu, erp)); #endif } size_t dk4path_concatenate_size( dkChar const *dirname, dkChar const *filename, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != dirname); assert(NULL != filename); #endif #if DK4_CHAR_SIZE > 1 return (dk4pathw_concatenate_size(dirname, filename, erp)); #else return (dk4path8_concatenate_size(dirname, filename, erp)); #endif } int dk4path_concatenate_buffer( dkChar *buffer, size_t szbuf, dkChar const *dirn, dkChar const *filen, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != buffer); assert(0 < szbuf); assert(NULL != dirn); assert(NULL != filen); #endif #if DK4_CHAR_SIZE > 1 return (dk4pathw_concatenate_buffer(buffer, szbuf, dirn, filen, erp)); #else return (dk4path8_concatenate_buffer(buffer, szbuf, dirn, filen, erp)); #endif } dkChar * dk4path_concatenate_new( dkChar const *dirn, dkChar const *filen, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != dirn); assert(NULL != filen); #endif #if DK4_CHAR_SIZE > 1 return (dk4pathw_concatenate_new(dirn, filen, erp)); #else return (dk4path8_concatenate_new(dirn, filen, erp)); #endif }