/* * @(#)NaturalOrderComparator.java * * Copyright 2010 Instituto Superior Tecnico * Founding Authors: Anil Kassamali * * https://fenix-ashes.ist.utl.pt/ * * This file is part of the Correspondence Registry Module. * * The Correspondence Registry Module is free software: you can * redistribute it and/or modify it under the terms of the GNU Lesser General * Public License as published by the Free Software Foundation, either version * 3 of the License, or (at your option) any later version. * * The Correspondence Registry Module is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the Correspondence Registry Module. If not, see . * */ package module.mailtracking.utilities; import java.util.Comparator; /** * * @author Anil Kassamali * */ public class NaturalOrderComparator implements Comparator { 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; } } } @Override public int compare(String o1, String o2) { String a = o1; String b = o2; 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); } } }