diff options
Diffstat (limited to 'src/utilcode/makepath.cpp')
-rw-r--r-- | src/utilcode/makepath.cpp | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/utilcode/makepath.cpp b/src/utilcode/makepath.cpp index 3d948d53a1..37b7202dba 100644 --- a/src/utilcode/makepath.cpp +++ b/src/utilcode/makepath.cpp @@ -15,6 +15,7 @@ #include "utilcode.h" #include "ex.h" +#ifndef FEATURE_CORECLR /*** *void _makepath() - build path name from components * @@ -165,6 +166,146 @@ void MakePath ( *path = _T('\0'); } } +#endif // !FEATURE_CORECLR + +/*** +*void Makepath() - build path name from components +* +*Purpose: +* create a path name from its individual components +* +*Entry: +* CQuickWSTR &szPath - Buffer for constructed path +* WCHAR *drive - pointer to drive component, may or may not contain +* trailing ':' +* WCHAR *dir - pointer to subdirectory component, may or may not include +* leading and/or trailing '/' or '\' characters +* WCHAR *fname - pointer to file base name component +* WCHAR *ext - pointer to extension component, may or may not contain +* a leading '.'. +* +*Exit: +* path - pointer to constructed path name +* +*Exceptions: +* +*******************************************************************************/ + +void MakePath ( + __out CQuickWSTR &szPath, + __in LPCWSTR drive, + __in LPCWSTR dir, + __in LPCWSTR fname, + __in LPCWSTR ext + ) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END + + SIZE_T maxCount = 4 // Possible separators between components, plus null terminator + + (drive != nullptr ? 2 : 0) + + (dir != nullptr ? wcslen(dir) : 0) + + (fname != nullptr ? wcslen(fname) : 0) + + (ext != nullptr ? wcslen(ext) : 0); + LPWSTR path = szPath.AllocNoThrow(maxCount); + + const WCHAR *p; + DWORD count = 0; + + /* we assume that the arguments are in the following form (although we + * do not diagnose invalid arguments or illegal filenames (such as + * names longer than 8.3 or with illegal characters in them) + * + * drive: + * A ; or + * A: + * dir: + * \top\next\last\ ; or + * /top/next/last/ ; or + * either of the above forms with either/both the leading + * and trailing / or \ removed. Mixed use of '/' and '\' is + * also tolerated + * fname: + * any valid file name + * ext: + * any valid extension (none if empty or null ) + */ + + /* copy drive */ + + if (drive && *drive) { + *path++ = *drive; + *path++ = _T(':'); + count += 2; + } + + /* copy dir */ + + if ((p = dir)) { + while (*p) { + *path++ = *p++; + count++; + + _ASSERTE(count < maxCount); + } + +#ifdef _MBCS + if (*(p=_mbsdec(dir,p)) != _T('/') && *p != _T('\\')) { +#else /* _MBCS */ + // suppress warning for the following line; this is safe but would require significant code + // delta for prefast to understand. +#ifdef _PREFAST_ + #pragma warning( suppress: 26001 ) +#endif + if (*(p-1) != _T('/') && *(p-1) != _T('\\')) { +#endif /* _MBCS */ + *path++ = _T('\\'); + count++; + + _ASSERTE(count < maxCount); + } + } + + /* copy fname */ + + if ((p = fname)) { + while (*p) { + *path++ = *p++; + count++; + + _ASSERTE(count < maxCount); + } + } + + /* copy ext, including 0-terminator - check to see if a '.' needs + * to be inserted. + */ + + if ((p = ext)) { + if (*p && *p != _T('.')) { + *path++ = _T('.'); + count++; + + _ASSERTE(count < maxCount); + } + + while ((*path++ = *p++)) { + count++; + + _ASSERTE(count < maxCount); + } + } + else { + /* better add the 0-terminator */ + *path = _T('\0'); + } + + szPath.Shrink(count + 1); +} #if !defined(FEATURE_CORECLR) static LPCWSTR g_wszProcessExePath = NULL; |