On 30/03/11 22:41, Dermot McNally wrote:
It looks like we may not be out of the woods yet on this one - with
the latest patch, trying to build a map of Ireland (from the Geofabrik
extract) fails, where it had succeeded before. Single tile, no
splitting:

java.lang.ArrayIndexOutOfBoundsException: 36
        at 
uk.me.parabola.imgfmt.app.srt.SrtSortKey.compareTo(SrtSortKey.java:41)

Thanks for trying out the patch. That is indeed a problem, please try
the updated patch attached.

Best wishes
..Steve
Index: src/uk/me/parabola/imgfmt/app/Label.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/Label.java	(revision 1650)
+++ src/uk/me/parabola/imgfmt/app/Label.java	(revision )
@@ -56,10 +56,6 @@
 		return text;
 	}
 
-	public String getTextSansGarminCodes() {
-		return stripGarminCodes(text);
-	}
-
 	// highway shields and "thin" separators
 	private final static Pattern SHIELDS = Pattern.compile("[\u0001-\u0006\u001b-\u001c]");
 
Index: test/uk/me/parabola/imgfmt/app/srt/SortTest.java
===================================================================
--- test/uk/me/parabola/imgfmt/app/srt/SortTest.java	(revision 1873)
+++ test/uk/me/parabola/imgfmt/app/srt/SortTest.java	(revision )
@@ -47,7 +47,7 @@
 
 	@Test
 	public void testDifferentLengths() {
-		SortKey<Object> k1 = sort.createSortKey(null, "aabb");
+		SortKey<Object> k1 = sort.createSortKey(null, "aabbbb");
 		SortKey<Object> k2 = sort.createSortKey(null, "aab");
 
 		assertEquals(1, k1.compareTo(k2));
@@ -158,6 +158,11 @@
 		assertEquals(-1, collator.compare("AA", "AAA"));
 	}
 
+	@Test
+	public void testIgnorableCharacters() {
+		checkOrder("aa", "\004aa");
+	}
+
 	private void checkOrder(int i1, int i2) {
 		String s = "aaa";
 		SortKey<Object> k1 = sort.createSortKey(null, s, i1);
Index: src/uk/me/parabola/imgfmt/app/srt/Sort.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/srt/Sort.java	(revision 1873)
+++ src/uk/me/parabola/imgfmt/app/srt/Sort.java	(revision )
@@ -93,22 +93,42 @@
 			ByteBuffer out = encoder.encode(inb);
 			byte[] bval = out.array();
 			byte[] key = new byte[bval.length * 3 + 3];
-			int length = bval.length;
-			for (int i = 0; i < length; i++) {
-				int b = bval[i] & 0xff;
-				key[i] = primary[b];
-				key[length + 1 + i] = secondary[b];
-				key[2*length + 2 + i] = tertiary[b];
-			}
-			key[length] = 0;
-			key[2 * length + 1] = 0;
-			key[3 * length + 2] = 0;
+
+			int start = fillKey(primary, bval, key, 0);
+			start = fillKey(secondary, bval, key, start);
+			fillKey(tertiary, bval, key, start);
+
 			return new SrtSortKey<T>(object, key, second);
 		} catch (CharacterCodingException e) {
 			return new SrtSortKey<T>(object, ZERO_KEY);
 		}
 	}
 
+	/**
+	 * Fill in the output key for a given strength.
+	 *
+	 * @param sortPositions An array giving the sort position for each of the 256 characters.
+	 * @param input The input string in a particular 8 bit codepage.
+	 * @param outKey The output sort key.
+	 * @param start The index into the output key to start at.
+	 * @return The next position in the output key.
+	 */
+	private int fillKey(byte[] sortPositions, byte[] input, byte[] outKey, int start) {
+		int index = start;
+		for (byte inb : input) {
+			int b = inb & 0xff;
+
+			// I am guessing that a sort position of 0 means that the character is ignorable at this
+			// strength. In other words it is as if it is not present in the string.  This appears to
+			// be true for shield symbols, but perhaps not for other kinds of control characters.
+			if (sortPositions[b] != 0)
+				outKey[index++] = sortPositions[b];
+		}
+
+		outKey[index++] = '\0';
+		return index;
+	}
+
 	public <T> SortKey<T> createSortKey(T object, String s) {
 		return createSortKey(object, s, 0);
 	}
Index: src/uk/me/parabola/imgfmt/app/net/NETFile.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/net/NETFile.java	(revision 1870)
+++ src/uk/me/parabola/imgfmt/app/net/NETFile.java	(revision )
@@ -71,8 +71,7 @@
 				Label[] l = rd.getLabels();
 				for(int i = 0; i < l.length && l[i] != null; ++i) {
 					if(l[i].getLength() != 0) {
-						String cleanName = l[i].getTextSansGarminCodes();
-						SortKey<LabeledRoadDef> sortKey = sort.createSortKey(new LabeledRoadDef(l[i], rd), cleanName);
+						SortKey<LabeledRoadDef> sortKey = sort.createSortKey(new LabeledRoadDef(l[i], rd), l[i].getText());
 						sortKeys.add(sortKey);
 					}
 				}
@@ -107,7 +106,7 @@
 		List<LabeledRoadDef> out = new ArrayList<LabeledRoadDef>(in.size());
 		while(!in.isEmpty()) {
 			LabeledRoadDef firstLabeledRoadDef = in.get(0).getObject();
-			String name0 = firstLabeledRoadDef.label.getTextSansGarminCodes();
+			String name0 = firstLabeledRoadDef.label.getText();
 			RoadDef road0 = firstLabeledRoadDef.roadDef;
 
 			City city0 = road0.getCity();
@@ -119,7 +118,7 @@
 			// firstly determine the entries whose name and city match
 			// name0 and city0
 			for(n = 0; (n < in.size() &&
-						name0.equalsIgnoreCase(in.get(n).getObject().label.getTextSansGarminCodes()) &&
+						name0.equalsIgnoreCase(in.get(n).getObject().label.getText()) &&
 						city0 == in.get(n).getObject().roadDef.getCity()); ++n) {
 				// relax
 			}
Index: src/uk/me/parabola/imgfmt/app/srt/SrtSortKey.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/srt/SrtSortKey.java	(revision 1870)
+++ src/uk/me/parabola/imgfmt/app/srt/SrtSortKey.java	(revision )
@@ -36,9 +36,11 @@
 	}
 
 	public int compareTo(SortKey<T> o) {
-		for (int i = 0; i < this.key.length; i++) {
+		SrtSortKey<T> other = (SrtSortKey<T>) o;
+		int length = Math.min(this.key.length, other.key.length);
+		for (int i = 0; i < length; i++) {
 			int k1 = this.key[i] & 0xff;
-			int k2 = ((SrtSortKey) o).key[i] & 0xff;
+			int k2 = other.key[i] & 0xff;
 			if (k1 < k2) {
 				return -1;
 			} else if (k1 > k2) {
@@ -46,9 +48,14 @@
 			}
 		}
 
-		if (second == ((SrtSortKey) o).second)
+		if (this.key.length < other.key.length)
+			return -1;
+		else if (this.key.length > other.key.length)
+			return 1;
+
+		if (second == other.second)
 			return 0;
-		else if (second < ((SrtSortKey) o).second)
+		else if (second < other.second)
 			return -1;
 		else
 			return 1;
Index: src/uk/me/parabola/imgfmt/app/mdr/MDRFile.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/mdr/MDRFile.java	(revision 1870)
+++ src/uk/me/parabola/imgfmt/app/mdr/MDRFile.java	(revision )
@@ -203,7 +203,8 @@
 			String cleanName = cleanUpName(name);
 			int strOff = createString(cleanName);
 
-			// XXX not sure: we sort on the dirty name (ie with the Garmin shield codes).
+			// We sort on the dirty name (ie with the Garmin shield codes) although those codes do not
+			// affect the sort order. The string for mdr15 does not include the shield codes.
 			mdr7.addStreet(currentMap, name, lab.getOffset(), strOff, mdrCity);
 		}
 	}
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev

Reply via email to