Windows Explorer 文件名排序算法

Windows Explorer里对文件名的排序有别于普通字符串字典序排序,它调用的排序函数是 StrCmpLogicalW ,这个函数的说明请参考链接页面。那么,它是如何实现的呢?我在Windows XP SP1的系统源代码中,找到了它,现在把它贴在下面,供参考。

源代码文件路径 E:\NT\shell\shlwapi\strings.c

STDAPI_(int) StrCmpLogicalW(PCWSTR psz1, PCWSTR psz2)
{
    int iRet = 0;
    int iCmpNum = 0;
    while (iRet == 0 && (*psz1 || *psz2))
    {
        int cch1 = 0;
        int cch2 = 0;
        BOOL fIsDigit1 = IS_DIGITW(*psz1);
        BOOL fIsDigit2 = IS_DIGITW(*psz2);
        ASSERT(fIsDigit1 == TRUE || fIsDigit1 == FALSE);
        ASSERT(fIsDigit2 == TRUE || fIsDigit2 == FALSE);
        //  using bit wise XOR as logical XOR
        //  if the numbers are mismatched then n
        if (fIsDigit1 ^ fIsDigit2)
        {
            iRet = _StrCmpLocaleW(NORM_IGNORECASE, psz1, -1, psz2, -1);
        }
        else if (fIsDigit1 && fIsDigit2)
        {
            int cchZero1 = 0;
            int cchZero2 = 0;

            // eat leading zeros
            while (*psz1 == TEXT('0'))
            {
                psz1++;
                cchZero1++;
            }

            while (*psz2 == TEXT('0'))
            {
                psz2++;
                cchZero2++;
            }
            
            while (IS_DIGITW(psz1[cch1])) 
                cch1++;

            while (IS_DIGITW(psz2[cch2])) 
                cch2++;

            if (cch1 != cch2)
            {
                iRet = cch1 > cch2 ? 1 : -1;
            }
            else 
            {
                //  remember the first numerical difference
                iRet = _StrCmpLocaleW(NORM_IGNORECASE, psz1, cch1, psz2, cch2);
                if (iRet == 0 && iCmpNum == 0 && cchZero1 != cchZero2)
                {
                    iCmpNum = cchZero2 > cchZero1 ? 1 : -1;
                }
            }
        }
        else
        {
            while (psz1[cch1] && !IS_DIGITW(psz1[cch1]))
                cch1++;

            while (psz2[cch2] && !IS_DIGITW(psz2[cch2]))
                cch2++;

            iRet = _StrCmpLocaleW(NORM_IGNORECASE, psz1, cch1, psz2, cch2);

        }

        //  at this point they should be numbers or terminators or different
        psz1 = &psz1[cch1];
        psz2 = &psz2[cch2];
    }

    if (iRet == 0 && iCmpNum)
        iRet = iCmpNum;
    
    return iRet;
}


版权声明:本文为ganxinjiang原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。