Ticket #3596: natural_sort.patch

File natural_sort.patch, 3.9 KB (added by plasm, 15 years ago)

Implements the desired functionality

  • src/kits/tracker/WidgetAttributeText.cpp

     
    6363
    6464const int32 kGenericReadBufferSize = 1024;
    6565
    66 
    6766template <class View>
    6867float
    6968TruncStringBase(BString *result, const char *str, int32 length,
     
    595594    if (fValueDirty)
    596595        ReadValue(&fFullValueText);
    597596
    598     return strcasecmp(fFullValueText.String(), compareTo->ValueAsText(view));
     597    return NaturalCompare(fFullValueText.String(), compareTo->ValueAsText(view));
    599598}
    600599
    601600
     
    782781    if (NameAttributeText::sSortFolderNamesFirst)
    783782        return fModel->CompareFolderNamesFirst(attr.TargetModel());
    784783
    785     return strcasecmp(fFullValueText.String(), compareTo->ValueAsText(view));
     784    return NaturalCompare(fFullValueText.String(), compareTo->ValueAsText(view));
    786785}
    787786
    788787
  • src/kits/tracker/Model.cpp

     
    321321    } else if (resolvedCompareModel->IsDirectory())
    322322        return 1;
    323323
    324     return strcasecmp(Name(), compareModel->Name());
     324    return NaturalCompare(Name(), compareModel->Name());
    325325}
    326326
    327327
  • src/kits/tracker/Utilities.h

     
    176176void DisallowMetaKeys(BTextView *);
    177177void DisallowFilenameKeys(BTextView *);
    178178
     179struct Chunk {
     180    int32 type;
     181    char *ascii;
     182        // Type = 0
     183    int32 num;
     184        // Type = 1
     185};
     186
     187inline bool
     188IsDigit(const char c)
     189{
     190    if ((c >= 48 && c <= 57) || c == 32)
     191        return true;
     192    else
     193        return false;
     194}
     195
     196// Compares two strings naturally, as opposed to lexicographically
     197inline int
     198NaturalCompare(const char *s1, const char *s2)
     199{
     200    Chunk a, b;
     201    size_t len1 = strlen(s1), len2 = strlen(s2);
     202    char bufferA[len1 + 1], bufferB[len2 + 1];
     203    uint32 i = 0, j = 0;
     204
     205    while (true) {
     206        if (i == len1)
     207            a.type = -1;
     208        else if (IsDigit(s1[i]))
     209            a.type = 1;
     210        else
     211            a.type = 0;
     212
     213        if (j == len2)
     214            b.type = -1;
     215        else if (IsDigit(s2[j]))
     216            b.type = 1;
     217        else
     218            b.type = 0;
     219
     220        if (a.type == b.type && a.type == -1)
     221            return 0;
     222        else {
     223            if (a.type == 0) {
     224                int32 k = i;
     225                while (!IsDigit(s1[k]) && s1[k] != 0) {
     226                    bufferA[k - i] = s1[k];
     227                    k++;
     228                }
     229                bufferA[k - i] = 0;
     230                a.ascii = bufferA;
     231                i += k - i;
     232            } else if (a.type == 1) {
     233                int32 k = i;
     234                while (IsDigit(s1[k]) && s1[k] != 0) {
     235                    bufferA[k - i] = s1[k];
     236                    k++;
     237                }
     238                bufferA[k - i] = 0;
     239                a.ascii = bufferA;
     240                a.num = atoi(bufferA);
     241                i += k - i;
     242            }
     243
     244            if (b.type == 0) {
     245                int32 k = j;
     246                while (!IsDigit(s2[k]) && s2[k] != 0) {
     247                    bufferB[k - j] = s2[k];
     248                    k++;
     249                }
     250                bufferB[k - j] = 0;
     251                b.ascii = bufferB;
     252                j += k - j;
     253            }
     254
     255            else if (b.type == 1) {
     256                int32 k = j;
     257                while (IsDigit(s2[k]) && s2[k] != 0) {
     258                    bufferB[k - j] = s2[k];
     259                    k++;
     260                }
     261                bufferB[k - j] = 0;
     262                b.ascii = bufferB;
     263                b.num = atoi(bufferB);
     264                j += k - j;
     265            }
     266        }
     267
     268        if (a.type == -1)
     269            return -1;
     270        if (b.type == -1)
     271            return 1;
     272
     273        if (a.type == b.type) {
     274            if (a.type == 0) {
     275                if (strcasecmp(a.ascii, b.ascii))
     276                    return strcasecmp(a.ascii, b.ascii);
     277            } else {
     278                if (a.num != b.num) {
     279                    if (a.num < b.num)
     280                        return -1;
     281                    if (a.num > b.num)
     282                        return 1;
     283                }
     284            }
     285        } else
     286            return strcasecmp(a.ascii, b.ascii);
     287    }
     288  return 0;
     289}
     290
    179291bool ValidateStream(BMallocIO *, uint32, int32 version);
    180292
    181293uint32 HashString(const char *string, uint32 seed);
    182294uint32 AttrHashString(const char *string, uint32 type);
    183295
    184 
    185296class OffscreenBitmap {
    186297    // a utility class for setting up offscreen bitmaps
    187298    public: