summaryrefslogtreecommitdiff
path: root/src/utilcode/makepath.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/utilcode/makepath.cpp')
-rw-r--r--src/utilcode/makepath.cpp141
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;