1
0
Fork 0
mirror of https://github.com/geometer/FBReaderJ.git synced 2025-10-03 17:59:33 +02:00

natural order comparison

This commit is contained in:
Nikolay Pultsin 2015-10-14 16:39:50 +03:00
parent 87ddf72ee1
commit 9af3f9ddfd
4 changed files with 158 additions and 12 deletions

View file

@ -0,0 +1,134 @@
package org.fbreader.util;
/*
NaturalOrderComparator.java -- Perform 'natural order' comparisons of strings in Java.
Copyright (C) 2003 by Pierre-Luc Paour <natorder@paour.com>
Based on the C version by Martin Pool, of which this is more or less a straight conversion.
Copyright (C) 2000 by Martin Pool <mbp@humbug.org.au>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
import java.util.Comparator;
public class NaturalOrderComparator implements Comparator<String> {
int compareRight(String a, String b) {
int bias = 0;
int ia = 0;
int ib = 0;
// The longest run of digits wins. That aside, the greatest
// value wins, but we can't know that it will until we've scanned
// both numbers to know that they have the same magnitude, so we
// remember it in BIAS.
for (;; ia++, ib++) {
char ca = charAt(a, ia);
char cb = charAt(b, ib);
if (!Character.isDigit(ca) && !Character.isDigit(cb)) {
return bias;
} else if (!Character.isDigit(ca)) {
return -1;
} else if (!Character.isDigit(cb)) {
return +1;
} else if (ca < cb) {
if (bias == 0) {
bias = -1;
}
} else if (ca > cb) {
if (bias == 0)
bias = +1;
} else if (ca == 0 && cb == 0) {
return bias;
}
}
}
public int compare(String a, String b) {
if ((!a.toLowerCase().equals(a) || !b.toLowerCase().equals(b)) && !a.equalsIgnoreCase(b)) {
return compare(a.toLowerCase(), b.toLowerCase());
}
int ia = 0, ib = 0;
int nza = 0, nzb = 0;
char ca, cb;
int result;
while (true) {
// only count the number of zeroes leading the last number compared
nza = nzb = 0;
ca = charAt(a, ia);
cb = charAt(b, ib);
// skip over leading spaces or zeros
while (Character.isSpaceChar(ca) || ca == '0') {
if (ca == '0') {
nza++;
} else {
// only count consecutive zeroes
nza = 0;
}
ca = charAt(a, ++ia);
}
while (Character.isSpaceChar(cb) || cb == '0') {
if (cb == '0') {
nzb++;
} else {
// only count consecutive zeroes
nzb = 0;
}
cb = charAt(b, ++ib);
}
// process run of digits
if (Character.isDigit(ca) && Character.isDigit(cb)) {
if ((result = compareRight(a.substring(ia), b.substring(ib))) != 0) {
return result;
}
}
if (ca == 0 && cb == 0) {
// The strings compare the same. Perhaps the caller
// will want to call strcmp to break the tie.
return nza - nzb;
}
if (ca < cb) {
return -1;
} else if (ca > cb) {
return +1;
}
++ia;
++ib;
}
}
static char charAt(String s, int i) {
if (i >= s.length()) {
return 0;
} else {
return s.charAt(i);
}
}
}

View file

@ -21,6 +21,7 @@ package org.geometerplus.fbreader.library;
import java.util.*;
import org.fbreader.util.NaturalOrderComparator;
import org.fbreader.util.Pair;
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
@ -30,6 +31,19 @@ import org.geometerplus.fbreader.book.*;
import org.geometerplus.fbreader.tree.FBTree;
public class FileTree extends LibraryTree {
private static final NaturalOrderComparator ourNaturalOrderComparator =
new NaturalOrderComparator();
private static final Comparator<ZLFile> ourFileComparator = new Comparator<ZLFile>() {
public int compare(ZLFile file0, ZLFile file1) {
final boolean isDir = file0.isDirectory();
if (isDir != file1.isDirectory()) {
return isDir ? -1 : 1;
}
return ourNaturalOrderComparator.compare(file0.getShortName(), file1.getShortName());
}
};
private final ZLFile myFile;
private final String myName;
private final String mySummary;
@ -168,16 +182,6 @@ public class FileTree extends LibraryTree {
return myFile.equals(((FileTree)o).myFile);
}
private static final Comparator<ZLFile> ourFileComparator = new Comparator<ZLFile>() {
public int compare(ZLFile file0, ZLFile file1) {
final boolean isDir = file0.isDirectory();
if (isDir != file1.isDirectory()) {
return isDir ? -1 : 1;
}
return file0.getShortName().compareToIgnoreCase(file1.getShortName());
}
};
@Override
public int compareTo(FBTree tree) {
return ourFileComparator.compare(myFile, ((FileTree)tree).myFile);

View file

@ -26,7 +26,11 @@ import java.util.Map;
import android.annotation.TargetApi;
import android.os.Build;
import org.fbreader.util.NaturalOrderComparator;
public abstract class TitledEntity<T extends TitledEntity<T>> implements Comparable<T> {
private static final NaturalOrderComparator ourComparator = new NaturalOrderComparator();
private String myTitle;
private String mySortKey;
@ -66,7 +70,7 @@ public abstract class TitledEntity<T extends TitledEntity<T>> implements Compara
@Override
public int compareTo(T other) {
return getSortKey().compareTo(other.getSortKey());
return ourComparator.compare(getSortKey(), other.getSortKey());
}
private final static Map<String, String[]> ARTICLES = new HashMap<String, String[]>();

View file

@ -13,6 +13,8 @@ import group.pals.android.lib.ui.filechooser.services.IFileProvider;
import java.util.Comparator;
import org.fbreader.util.NaturalOrderComparator;
/**
* {@link IFile} comparator.<br>
* Rules:<br>
@ -24,6 +26,8 @@ import java.util.Comparator;
* @since v1.91
*/
public class FileComparator implements Comparator<IFile> {
private static final NaturalOrderComparator ourNaturalOrderComparator =
new NaturalOrderComparator();
private final IFileProvider.SortType mSortType;
private final IFileProvider.SortOrder mSortOrder;
@ -45,7 +49,7 @@ public class FileComparator implements Comparator<IFile> {
public int compare(IFile lhs, IFile rhs) {
if ((lhs.isDirectory() && rhs.isDirectory()) || (lhs.isFile() && rhs.isFile())) {
// default is to compare by name (case insensitive)
int res = lhs.getSecondName().compareToIgnoreCase(rhs.getSecondName());
int res = ourNaturalOrderComparator.compare(lhs.getSecondName(), rhs.getSecondName());
switch (mSortType) {
case SortByName: