int _RTLENTRY _EXPFUNC _tfnsplit(const _TCHAR *pathP, _TCHAR *driveP, _TCHAR *dirP, _TCHAR *nameP, _TCHAR *extP) { register _TCHAR *pB; register int Wrk; int Ret; _TCHAR buf[ MAXPATH+2 ]; /* Set all string to default value zero */ Ret = 0; if (driveP) *driveP = 0; if (dirP) *dirP = 0; if (nameP) *nameP = 0; if (extP) *extP = 0; /* Copy filename into template up to MAXPATH characters */ pB = buf; if ((Wrk = _tcslen(pathP)) > MAXPATH) Wrk = MAXPATH; *pB++ = 0; _tcsncpy(pB, pathP, Wrk); *(pB += Wrk) = 0; /* Split the filename and fill corresponding nonzero pointers */ Wrk = 0; for (; ; ) { #if defined(_MBCS) && !defined(_UNICODE) if (_mbsbtype(buf+1, (pB-1) - (buf+1)) == _MBC_TRAIL) { pB -= 2; continue; } #endif switch (*--pB) { case _TEXT('.') : if (!Wrk && (*(pB+1) == _TEXT('\0'))) #if defined(_MBCS) && !defined(_UNICODE) Wrk = DotFound(buf+1, pB); #else Wrk = DotFound(pB); #endif if ((!Wrk) && ((Ret & EXTENSION) == 0)) { Ret |= EXTENSION; CopyIt(extP, pB, MAXEXT - 1); *pB = 0; } continue; case _TEXT(':') : if (pB != &buf[2]) continue; case _TEXT('\0') : if (Wrk) { if (*++pB) Ret |= DIRECTORY; CopyIt(dirP, pB, MAXDIR - 1); *pB-- = 0; break; } case _TEXT('/') : case _TEXT('\\') : if (!Wrk) { Wrk++; if (*++pB) Ret |= FILENAME; CopyIt(nameP, pB, MAXFILE - 1); *pB-- = 0; if (*pB == 0 || (*pB == _TEXT(':') && pB == &buf[2])) break; } continue; case _TEXT('*') : case _TEXT('?') : if (!Wrk) Ret |= WILDCARDS; default : continue; } break; } if (*pB == _TEXT(':')) { if (buf[1]) Ret |= DRIVE; CopyIt(driveP, &buf[1], MAXDRIVE - 1); } return (Ret); }
// FNSplit differs from fnsplit in that it can split the path without // splitting a DBCS character whose trail byte can have the value of // 0x5C that also represents '\\' in the ASCII set. Int16u FNSplit(const char * pathP, char * driveP, char * dirP, char * nameP, char * extP) { register char * pB; register Int16u Wrk; Int16u Ret; char buf[MAXPATH + 2]; //Set all string to default value zero Ret = 0; if (driveP) *driveP = 0; if (dirP) *dirP = 0; if (nameP) *nameP = 0; if (extP) *extP = 0; // Copy filename into template up to MAXPATH characters pB = buf; while (*pathP == ' ') pathP++; if ((Wrk = lstrlen(pathP)) > MAXPATH) Wrk = MAXPATH; pB [0] = 0; // put a stopper at string beginning _tcsnccpy(pB + 1, pathP, Wrk); pB [++Wrk] = '\0'; // forward-scan pathname and record occurences of '/', '\\', or '.' TokenIndexList * slashList = 0, * bkSlashList = 0, * dotList = 0; RegisterTokens (slashList, pB, '/'); RegisterTokens (bkSlashList, pB, '\\'); RegisterTokens (dotList, pB, '.'); //Split the filename and fill corresponding nonzero pointers Int16s index = Wrk; Wrk = 0; // from this point on, Wrk serves as a Boolean flag // indicating whether a directory is detected for ( ; ; ) { --index; switch (pB [index]) { case '.' : if (!IsAsciiToken (dotList, index)) continue; if (!Wrk && (pB [index + 1] == '\0')) Wrk = IsDirDot(slashList, bkSlashList, pB, index); if ((!Wrk) && ((Ret & EXTENSION) == 0)) { Ret |= EXTENSION; CopyIt (extP, pB + index, MAXEXT - 1); pB [index] = 0; } continue; case ':' : if (index != 2) // i.e., if not second char continue; case '\0' : if (Wrk) // directory exists { if (pB [index + 1]) Ret |= DIRECTORY; CopyIt(dirP, pB + index + 1, MAXDIR - 1); pB [index + 1] = 0; Int16u dirL = lstrlen (dirP); if (dirL == 0) break; switch (dirP [dirL - 1]) { case '\\': if (IsAsciiToken (bkSlashList, index + dirL)) break; case '/': if (IsAsciiToken (slashList, index + dirL)) break; default: // add trailing slash dirP [dirL] = '\\'; dirP [dirL + 1] = '\0'; } break; } case '/' : case '\\' : if (!Wrk && (pB [index] == '\0' || IsAsciiToken (pB [index] == '/' ? slashList : bkSlashList, index))) { Wrk++; if (pB [index + 1]) Ret |= FILENAME; CopyIt(nameP, pB + index + 1, MAXFILE - 1); pB [index + 1] = 0; if (pB [index] == 0 || (pB [index] == ':' && index == 2)) break; } continue; case '*' : case '?' : if (!Wrk) Ret |= WILDCARDS; default : continue; } // switch break; } // for if (pB [2] == ':') { if (pB [0]) Ret |= DRIVE; CopyIt(driveP, &pB [1], MAXDRIVE - 1); } DeleteIndexList (slashList); DeleteIndexList (bkSlashList); DeleteIndexList (dotList); return (Ret); }