/* Copyright (C) 2015-2020, Dirk Krause SPDX-License-Identifier: BSD-3-Clause */ /* WARNING: This file was generated by the dkct program (see http://dktools.sourceforge.net/ for details). Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: dk4path8.ctr */ /** @file dk4path8.c The dk4path8 module. */ #line 248 "dk4path8.ctr" #include "dk4conf.h" #include "dk4path8.h" #include "dk4mem.h" #include "dk4str8.h" #include "dk4maasz.h" #if DK4_HAVE_STRING_H #ifndef STRING_H_INCLUDED #include #define STRING_H_INCLUDED 1 #endif #endif #if DK4_HAVE_ASSERT_H #ifndef ASSERT_H_INCLUDED #include #define ASSERT_H_INCLUDED 1 #endif #endif #include "dk4unused.h" #line 275 "dk4path8.ctr" /** Constant keywords used by the dk4path8 module. */ static const char * const dk4path8_kw[] = { #if DK4_HAVE_BACKSLASH_AS_SEP /* 0 */ "\\", /* 1 */ "/", #else /* 0 */ "/", /* 1 */ "\\", #endif /* 2 */ ".", /* 3 */ "..", /* 4 */ ":" }; /** Get last character from a string. CRT on Windows: Not used. @param str String to test. @return Last character from string. */ static char dk4path8_lastchar(const char *str) { char back = '\0'; #if DK4_USE_ASSERT assert(NULL != str); #endif if (str) { while ('\0' != *str) { back = *(str++); } } return back; } int dk4path8_is_absolute(const char *path) { int back = 0; #if DK4_ON_WINDOWS char c; #endif #if DK4_USE_ASSERT assert(NULL != path); #endif if (NULL != path) { #if DK4_ON_WINDOWS c = *path; if ( *(dk4path8_kw[0]) == c ) { back = 1; } else { if ((('a' <= c) && ('z' >= c)) || (('A' <= c) && ('Z' >= c))) { if ( *(dk4path8_kw[4]) == path[1] ) { c = path[2]; if ( ( *(dk4path8_kw[0]) == c ) || ( '\0' == c ) ) { back = 1; } } } } #else if ( *(dk4path8_kw[0]) == *path ) { back = 1; } #endif } return back; } int dk4path8_is_relative(const char *path) { int back = 0; #if DK4_USE_ASSERT assert(NULL != path); #endif if (NULL != path) { if (NULL != dk4str8_chr(path, *(dk4path8_kw[0]))) { if (0 == dk4path8_is_absolute(path)) { back = 1; } } } return back; } int dk4path8_append(char *buffer, size_t sz, const char *filename, dk4_er_t *erp) { char *pc; /* Current path part to append */ char *pn; /* Next part to append */ char *pd; /* Part to delete */ char *mycp = NULL; /* Private copy */ #if DK4_ON_WINDOWS int ischr; #endif int back = 0; /* Function result */ int failed = 0; /* Definitely failed */ char lch; /* Last character from string */ #if DK4_USE_ASSERT assert(NULL != buffer); assert(0 < sz); assert(NULL != filename); #endif if ((NULL != buffer) && (NULL != filename) && (0 < sz)) { mycp = dk4str8_dup(filename, erp); if (NULL != mycp) { pc = mycp; while ((NULL != pc) && (0 == failed)) { pn = dk4str8_chr(pc, *(dk4path8_kw[0])); if (NULL != pn) { *(pn++) = '\0'; } if (0 != dk4str8_cmp(pc, dk4path8_kw[2])) { if (0 == dk4str8_cmp(pc, dk4path8_kw[3])) { /* Remove from buffer */ pd = dk4str8_rchr(buffer, *(dk4path8_kw[0])); if (NULL != pd) { *pd = '\0'; if (0 < dk4str8_len(&(pd[1]))) { #if DK4_ON_WINDOWS if (2 == dk4str8_len(buffer)) { ischr = 0; if (('A' <= buffer[0]) && ('Z' >= buffer[0])) { ischr = 1; } if (('a' <= buffer[0]) && ('z' >= buffer[0])) { ischr = 1; } if (1 == ischr) { if (':' == buffer[1]) { buffer[2] = *(dk4path8_kw[0]); buffer[3] = '\0'; } } } #else if (0 == dk4str8_len(buffer)) { *pd = *(dk4path8_kw[0]); pd++; *pd = '\0'; } #endif } else { failed = 1; dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } else { failed = 1; dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } else { /* Add to buffer */ lch = dk4path8_lastchar(buffer); if (lch != *(dk4path8_kw[0])) { if (0 != dk4str8_cat_s(buffer, sz, dk4path8_kw[0], erp)) { if (0 == dk4str8_cat_s(buffer, sz, pc, erp)) { failed = 1; } } else { failed = 1; } } else { if (0 == dk4str8_cat_s(buffer, sz, pc, erp)) { failed = 1; } } } } pc = pn; } if (0 == failed) { back = 1; } dk4mem_release(mycp); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; } char * dk4path8_get_suffix(const char *filename, dk4_er_t *erp) { const char *back = NULL; #if DK4_USE_ASSERT assert(NULL != filename); #endif if (NULL != filename) { while ('\0' != *filename) { if (('\\' == *filename) || ('/' == *filename)) { back = NULL; } else { if ('.' == *filename) { back = filename; } } filename++; } if (NULL == back) { dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return ((char *)back); } void dk4path8_correct_sep(char *filename) { #if DK4_USE_ASSERT assert(NULL != filename); #endif if (NULL != filename) { while ('\0' != *filename) { #if DK4_HAVE_BACKSLASH_AS_SEP if ('/' == *filename) { *filename = '\\'; } #else if ('\\' == *filename) { *filename = '/'; } #endif filename++; } } } int dk4path8_must_expand( #if DK4_ON_WINDOWS const char *filename #else const char * DK4_ARG_UNUSED(filename) #endif ) { #if DK4_ON_WINDOWS int back = 0; #if DK4_USE_ASSERT assert(NULL != filename); #endif if (NULL != filename) { while(('\0' != *filename) && (0 == back)) { switch (*filename) { case '*': case '?': { back = 1; } break; default: { filename++; } break; } } } return back; #else DK4_UNUSED_ARG(filename) return 0; #endif } int dk4path8_set_suffix( char *pdst, size_t szdst, char const *srcname, char const *newsu, dk4_er_t *erp ) { char *sp = NULL; int back = 0; #if DK4_USE_ASSERT assert(NULL != pdst); assert(0 < szdst); assert(NULL != srcname); assert(NULL != newsu); #endif if ((NULL == pdst) || (NULL == srcname) || (NULL == newsu) || (0 == szdst)) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } if (0 == dk4str8_cpy_s(pdst, szdst, srcname, erp)) { goto finished; } sp = dk4path8_get_suffix(pdst, NULL); if (NULL != sp) { *sp = '\0'; } back = dk4str8_cat_s(pdst, szdst, newsu, erp); finished: return back; } char * dk4path8_dup_change_suffix( char const *srcname, char const *newsu, dk4_er_t *erp ) { dk4_er_t er; char *sp; char *back = NULL; size_t lold; size_t lsuff; size_t lnew; #if DK4_USE_ASSERT assert(NULL != srcname); assert(NULL != newsu); #endif if ((NULL == srcname) || (NULL == newsu)) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } sp = dk4path8_get_suffix(srcname, NULL); lold = strlen(srcname); lsuff = 0; if (NULL != sp) { lsuff = strlen(sp); } if (lsuff > lold) { /* BUG */ dk4error_set_simple_error_code(erp, DK4_E_BUG); goto finished; } lold -= lsuff; lsuff = strlen(newsu); dk4error_init(&er); lnew = dk4ma_size_t_add(lold, lsuff, &er); lnew = dk4ma_size_t_add(lnew, 1, &er); if (DK4_E_NONE != er.ec) { dk4error_copy(erp, &er); goto finished; } back = dk4mem_new(char,lnew,erp); if (NULL == back) { goto finished; } /* 2018-04-04 Bugfix The new file name may be shorter than the original file name, so we must not copy the original name into the new buffer! */ #if 0 /* 2018-04-04 Performance Performance should be better using strncpy. */ for (i = 0; i < lold; i++) { back[i] = srcname[i]; } #endif #if 0 strncpy(back, srcname, lold); #endif DK4_MEMCPY(back,srcname,lold); back[lold] = '\0'; strcat(back, newsu); finished: return back; } size_t dk4path8_concatenate_size( char const *dirname, char const *filename, dk4_er_t *erp ) { dk4_er_t er; /* Test for math overflow */ size_t back = 0; /* Function result */ size_t sldir = 0; /* Length of dirname */ size_t slfil = 0; /* Length of filename */ size_t toadd = 2; /* Path separator and finalizer byte */ #line 667 "dk4path8.ctr" #if DK4_USE_ASSERT assert(NULL != dirname); assert(NULL != filename); #endif if ((NULL != dirname) && (NULL != filename)) { sldir = dk4str8_len(dirname); slfil = dk4str8_len(filename); if (0 < sldir) { if (*(dk4path8_kw[0]) == dirname[sldir - 1]) { toadd = 1; } } dk4error_init(&er); back = dk4ma_size_t_add( dk4ma_size_t_add(sldir, slfil, &er), toadd, &er ); if (DK4_E_NONE != er.ec) { dk4error_copy(erp, &er); back = 0; } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } #line 688 "dk4path8.ctr" return back; } int dk4path8_concatenate_buffer( char *buffer, size_t szbuf, char const *dirn, char const *filen, dk4_er_t *erp ) { size_t sld; int back = 0; int sep = 1; #line 706 "dk4path8.ctr" #if DK4_USE_ASSERT assert(NULL != buffer); assert(0 < szbuf); assert(NULL != dirn); assert(NULL != filen); #endif if ((NULL != buffer) && (NULL != dirn) && (NULL != filen) && (0 != szbuf)) { sld = dk4str8_len(dirn); if (0 < sld) { if (dirn[sld - 1] == *(dk4path8_kw[0])) { sep = 0; } } back = dk4str8_cpy_s(buffer, szbuf, dirn, erp); if (0 != back) { if (0 != sep) { back = dk4str8_cat_s(buffer, szbuf, dk4path8_kw[0], erp); } } if (0 != back) { back = dk4str8_cat_s(buffer, szbuf, filen, erp); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } if ((0 == back) && (NULL != buffer) && (0 < szbuf)) { buffer[0] = '\0'; } #line 730 "dk4path8.ctr" return back; } char * dk4path8_concatenate_new( char const *dirn, char const *filen, dk4_er_t *erp ) { char *back = NULL; size_t bl = 0; #line 745 "dk4path8.ctr" #if DK4_USE_ASSERT assert(NULL != dirn); assert(NULL != filen); #endif if ((NULL != dirn) && (NULL != filen)) { bl = dk4path8_concatenate_size(dirn, filen, erp); if (0 != bl) { back = dk4mem_new(char,bl,erp); if (NULL != back) { if (0 == dk4path8_concatenate_buffer(back, bl, dirn, filen, erp)) { dk4mem_free(back); back = NULL; } #if TRACE_DEBUG if (NULL != back) { #line 761 "dk4path8.ctr" } #endif } } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } #line 770 "dk4path8.ctr" return back; }