//////////////////////////////////////////////////////////////////////////////////
// Function name    : util_RemoveLastPathElement
// Description      :
//      effectively pops off a path element from the end, except for the root dir, where it does nothing
//      it removes any slashes before and after the element
//      ///root//foo/    -> leaves "///root" ("foo"  is strElem)
//      ///root          -> leaves ""        ("root" is strElem)
//      //               -> leaves ""        (""     is strElem)
//
// Return type      : void
// Argument         :  TSTRING& strPath
// Argument         : TSTRING& strElem
/////////////////////////////////////////////////////////////////////////////////
void util_RemoveLastPathElement(TSTRING& strPath, TSTRING& strElem)
{

    // remove all trailing separators
    util_RemoveTrailingSeps(strPath);

    // find the last separator
    TSTRING::size_type lastSep = strPath.rfind(TW_SLASH);

    // if separator was found, take all chars after it
    if (lastSep != TSTRING::npos)
    {
        strElem = strPath.substr(lastSep + 1);
        strPath.resize(lastSep + 1);
    }
    else // no seps in name, take whole string
    {
        // last element
        strElem = strPath;
        strPath.erase();
    }

    // remove all trailing separators
    util_RemoveTrailingSeps(strPath);
}
////////////////////////////////////////////////////////////////////////////////
// Function name    : util_RemoveDuplicateSeps
// Description      :
// takes all adjacent slashes and replaces them with a single slash
//      ///root//foo -> /root/foo
//      rel//foo///  -> rel/foo/
//
// Return type      : void
// Argument         : TSTRING& strPath
///////////////////////////////////////////////////////////////////////////////
void util_RemoveDuplicateSeps(TSTRING& strPath)
{
    bool              fLastCharWasSep = false;
    TSTRING::iterator iter            = strPath.begin();
    while (iter != strPath.end())
    {
        bool fErasedChar = false;
        // if we've found a char that's not '/', then it's not the root
        if (*iter == TW_SLASH)
        {
            // if this char is a duplicate sep, erase it
            if (fLastCharWasSep)
            {
                iter        = strPath.erase(iter);
                fErasedChar = true;
            }

            fLastCharWasSep = true;
        }
        else
        {
            fLastCharWasSep = false;
        }

        // don't go past end of string (could happen with erase)
        if (!fErasedChar)
            iter++;
    }
}
///////////////////////////////////////////////////////////////////////////////
// Function name    : util_PathFind
// Description      :
//      takes single-element executible filename and looks in path env var for it
//      assumes path is colon-delimited string of directories.
//
// Return type      : bool
// Argument         :  TSTRING& strFullPath
// Argument         : const TSTRING& strFilename
///////////////////////////////////////////////////////////////////////////////
bool util_PathFind(TSTRING& strFullPath, const TSTRING& strFilename)
{
    bool fFoundFile = false;

    if (strFilename.empty())
        return false;

    //
    // get the path environment variable
    //
    TCHAR* pszPathVar = getenv("PATH");
    if (pszPathVar != NULL)
    {
        //
        // cycle over characters in path looking for the ':'
        //
        TSTRING strCurPath;
        TCHAR*  pchTemp    = pszPathVar;
        bool    fMorePaths = true;
        do // while still more paths and haven't found file
        {
            //
            // are we at the ':'?
            //
            if (*pchTemp && *pchTemp != _T(':')) // if we're not at the end of the path
            {
                strCurPath += *pchTemp;
            }
            else // we have found the ':'
            {
                //
                // expand current path into a fully qualified path
                // if it's empty, use current directory
                //
                TSTRING strFP;
                if (strCurPath.empty())
                    strCurPath = _T(".");
                if (iFSServices::GetInstance()->FullPath(strFP, strCurPath))
                    strCurPath = strFP;

                //
                // put the file together with the path dir
                //
                TSTRING strFullName = strCurPath;
                util_TrailingSep(strFullName, true);
                strFullName += strFilename;

                //
                // the file must exist and be executable
                //
                if (util_FileIsExecutable(strFullName))
                {
                    strFullPath = strFullName;
                    fFoundFile  = true;
                }
                else
                    strCurPath.erase(); // start over
            }

            //
            // keep searching if we're not at the end of the path string
            //

            if (*pchTemp)
                pchTemp++;
            else
                fMorePaths = false;
        } while (!fFoundFile && fMorePaths);
    }

    return (fFoundFile);
}