From 135e2ce27b646ee99e578d74eaeef71bb57708ca Mon Sep 17 00:00:00 2001 From: Olof Larsson Date: Fri, 12 Apr 2013 15:07:34 +0200 Subject: [PATCH] Use NaturalOrderComparator instead of built in Java one for strings. --- .../mcore/NaturalOrderComparator.java | 188 ++++++++++++++++++ src/com/massivecraft/mcore/store/Coll.java | 6 + src/com/massivecraft/mcore/store/Entity.java | 3 +- 3 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 src/com/massivecraft/mcore/NaturalOrderComparator.java diff --git a/src/com/massivecraft/mcore/NaturalOrderComparator.java b/src/com/massivecraft/mcore/NaturalOrderComparator.java new file mode 100644 index 00000000..93a1edc9 --- /dev/null +++ b/src/com/massivecraft/mcore/NaturalOrderComparator.java @@ -0,0 +1,188 @@ +/* + NaturalOrderComparator.java -- Perform 'natural order' comparisons of strings in Java. + Copyright (C) 2003 by Pierre-Luc Paour + + Based on the C version by Martin Pool, of which this is more or less a straight conversion. + Copyright (C) 2000 by Martin Pool + + 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. + */ + +/* +This version has been slightly modified for usage in the MCore library. +Check out the original at: https://github.com/paour/natorder/blob/master/NaturalOrderComparator.java +*/ + +package com.massivecraft.mcore; + +import java.util.*; + +public class NaturalOrderComparator implements Comparator +{ + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static transient NaturalOrderComparator i = new NaturalOrderComparator(); + public static NaturalOrderComparator get() { return i; } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public int compare(Object o1, Object o2) + { + String a = o1.toString(); + String b = o2.toString(); + + 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; + } + } + + // -------------------------------------------- // + // UTIL + // -------------------------------------------- // + + 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; + } + } + } + + static char charAt(String s, int i) + { + if (i >= s.length()) + { + return 0; + } + else + { + return s.charAt(i); + } + } +} \ No newline at end of file diff --git a/src/com/massivecraft/mcore/store/Coll.java b/src/com/massivecraft/mcore/store/Coll.java index d1512633..e60f1f84 100644 --- a/src/com/massivecraft/mcore/store/Coll.java +++ b/src/com/massivecraft/mcore/store/Coll.java @@ -16,6 +16,7 @@ import org.bukkit.plugin.Plugin; import com.massivecraft.mcore.MCore; import com.massivecraft.mcore.MPlugin; +import com.massivecraft.mcore.NaturalOrderComparator; import com.massivecraft.mcore.Predictate; import com.massivecraft.mcore.store.accessor.Accessor; import com.massivecraft.mcore.store.idstrategy.IdStrategy; @@ -618,6 +619,11 @@ public class Coll implements CollInterface } this.collDriverObject = db.getCollDriverObject(this); + if (idComparator == null) + { + idComparator = NaturalOrderComparator.get(); + } + // STORAGE this.id2entity = new ConcurrentSkipListMap(idComparator); this.entity2id = new ConcurrentSkipListMap(entityComparator); diff --git a/src/com/massivecraft/mcore/store/Entity.java b/src/com/massivecraft/mcore/store/Entity.java index 0845516d..911d39b8 100644 --- a/src/com/massivecraft/mcore/store/Entity.java +++ b/src/com/massivecraft/mcore/store/Entity.java @@ -1,6 +1,7 @@ package com.massivecraft.mcore.store; import com.massivecraft.mcore.MCore; +import com.massivecraft.mcore.NaturalOrderComparator; import com.massivecraft.mcore.store.accessor.Accessor; import com.massivecraft.mcore.xlib.gson.Gson; @@ -120,7 +121,7 @@ public abstract class Entity> implements Comparable if (thisId == null) return -1; if (thatId == null) return +1; - int ret = thisId.compareTo(thatId); + int ret = NaturalOrderComparator.get().compare(thisId, thatId); // The id's may be the same if these are objects from different collections // We avoid zero in an ugly way like this.