Changeset 85384 in vbox for trunk/src/VBox/Runtime/common/path/RTPathFindCommon.cpp
- Timestamp:
- Jul 18, 2020 9:17:43 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/path/RTPathFindCommon.cpp
r85382 r85384 30 30 *********************************************************************************************************************************/ 31 31 #include "internal/iprt.h" 32 #include <iprt/path.h> 33 34 #include <iprt/alloca.h> 32 35 #include <iprt/assert.h> 33 36 #include <iprt/errcore.h> 34 #include <iprt/path.h> 37 #include <iprt/mem.h> 38 #include <iprt/string.h> 39 #include <iprt/uni.h> 40 41 42 #define RTPATH_TEMPLATE_CPP_H "RTPathFindCommon.cpp.h" 43 #include "rtpath-expand-template.cpp.h" 35 44 36 45 37 46 RTDECL(size_t) RTPathFindCommonEx(size_t cPaths, const char * const *papszPaths, uint32_t fFlags) 38 47 { 48 /* 49 * Validate input. 50 */ 51 AssertReturn(RTPATH_STR_F_IS_VALID(fFlags, RTPATHFINDCOMMON_F_IGNORE_DOTDOT), 0); 39 52 AssertReturn(cPaths > 0, 0); 40 53 AssertPtrReturn(papszPaths, 0); 41 AssertReturn(RTPATH_STR_F_IS_VALID(fFlags, 0), 0); 54 size_t i = cPaths; 55 while (i-- > 0) 56 AssertPtrReturn(papszPaths[i], 0); 42 57 43 /** @todo r=bird: Extremely naive code. 44 * - The original idea of taking either '/' or '\\' as separators is very out of 45 * touch with the rest of path.h. On DOS based systems we need to handle both 46 * of those as well as ':'. 47 * - Why compare pszRef with itself? 48 * - Why derefernece pszRef[cch] for each other path. 49 * - Why perform NULL checks for each outer iteration. 50 * - Why perform '\0' check before comparing with pszRef[cch]? 51 * It's sufficient to check if pszRef[cch] is '\0'. 52 * - Why backtrack to the last path separator? It won't return the expected 53 * result for cPaths=1, unless the path ends with a separator. 54 * - Multiple consequtive path separators must be treated as a single one (most 55 * of the time anyways - UNC crap). 58 /* 59 * Duplicate papszPaths so we can have individual positions in each path. 60 * Use the stack if we haven't got too many paths. 56 61 */ 57 const char *pszRef = papszPaths[0]; /* The reference we're comparing with. */ 58 const char chNaiveSep = (fFlags & RTPATH_STR_F_STYLE_MASK) == RTPATH_STR_F_STYLE_HOST 59 ? RTPATH_SLASH 60 : (fFlags & RTPATH_STR_F_STYLE_MASK) == RTPATH_STR_F_STYLE_DOS ? '\\' : '/'; 62 void *pvFree; 63 const char **papszCopy; 64 size_t cbNeeded = cPaths * sizeof(papszCopy[0]); 65 if (cbNeeded <= _2K) 66 { 67 pvFree = NULL; 68 papszCopy = (const char **)alloca(cbNeeded); 69 } 70 else 71 { 72 pvFree = RTMemTmpAlloc(cbNeeded); 73 papszCopy = (const char **)pvFree; 74 } 75 AssertReturn(papszCopy, 0); 76 memcpy(papszCopy, papszPaths, cbNeeded); 61 77 62 size_t cch = 0; 63 do 78 /* 79 * Invoke the worker for the selected path style. 80 */ 81 size_t cchRet; 82 switch (fFlags & RTPATH_STR_F_STYLE_MASK) 64 83 { 65 for (size_t i = 0; i < cPaths; ++i) 66 { 67 const char *pcszPath = papszPaths[i]; 68 if ( pcszPath 69 && pcszPath[cch] 70 && pcszPath[cch] == pszRef[cch]) 71 continue; 84 #if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS 85 case RTPATH_STR_F_STYLE_HOST: 86 #endif 87 case RTPATH_STR_F_STYLE_DOS: 88 cchRet= rtPathFindCommonStyleDos(cPaths, papszCopy, fFlags); 89 break; 72 90 73 while ( cch 74 && pszRef[--cch] != chNaiveSep) { } 91 #if RTPATH_STYLE != RTPATH_STR_F_STYLE_DOS 92 case RTPATH_STR_F_STYLE_HOST: 93 #endif 94 case RTPATH_STR_F_STYLE_UNIX: 95 cchRet = rtPathFindCommonStyleUnix(cPaths, papszCopy, fFlags); 96 break; 75 97 76 return cch ? cch + 1 : 0;77 }78 } while (++cch);98 default: 99 AssertFailedStmt(cchRet = 0); /* impossible */ 100 } 79 101 80 return 0; 102 /* 103 * Clean up and return. 104 */ 105 if (pvFree) 106 RTMemTmpFree(pvFree); 107 return cchRet; 81 108 } 82 109 RT_EXPORT_SYMBOL(RTPathFindCommonEx);
Note:
See TracChangeset
for help on using the changeset viewer.