[mkgmap] 01/04: Imported Upstream version 0.0.0+svn3478

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Tue Mar 3 23:13:48 UTC 2015


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository mkgmap.

commit e042a28f504f79a79a17d00dccace7f64331ebcd
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Tue Mar 3 23:01:06 2015 +0100

    Imported Upstream version 0.0.0+svn3478
---
 resources/help/en/options                          |  10 ++
 resources/mkgmap-version.properties                |   4 +-
 resources/styles/default/inc/name                  |   8 +
 resources/styles/default/lines                     |   3 +-
 .../parabola/imgfmt/app/labelenc/Utf8Decoder.java  |   1 -
 src/uk/me/parabola/imgfmt/app/mdr/Mdr20.java       |  14 +-
 src/uk/me/parabola/imgfmt/app/mdr/Mdr22.java       |   2 +-
 src/uk/me/parabola/imgfmt/app/mdr/Mdr2x.java       |  41 +++--
 src/uk/me/parabola/imgfmt/app/mdr/Mdr7.java        | 183 +++++++++++++++++++--
 src/uk/me/parabola/imgfmt/app/mdr/Mdr7Record.java  |  43 +++++
 src/uk/me/parabola/imgfmt/app/mdr/MdrConfig.java   |   9 +
 .../parabola/mkgmap/combiners/GmapsuppBuilder.java |   4 +-
 .../me/parabola/mkgmap/combiners/MdrBuilder.java   |   4 +-
 .../parabola/mkgmap/osmstyle/RuleFileReader.java   |  38 +++--
 .../me/parabola/mkgmap/scan/SyntaxException.java   |   2 +-
 test/resources/rules/multi-or-twice.test           |  18 ++
 test/resources/rules/multi-or-with-and.test        |  19 +++
 test/resources/rules/or-at-end.test                |  30 ++++
 .../mkgmap/osmstyle/RuleFileReaderTest.java        |   1 +
 19 files changed, 376 insertions(+), 58 deletions(-)

diff --git a/resources/help/en/options b/resources/help/en/options
index f13bef2..5a978e6 100644
--- a/resources/help/en/options
+++ b/resources/help/en/options
@@ -125,6 +125,16 @@ Address search options:
   same code page and sorting options (eg. --code-page, --latin1 etc) must
   be used as were used to compile the individual map tiles.
 
+--x-split-name-index
+    A temporary option to enable indexing each part of a street name separately.
+    So for example if the street is "Aleksandra Gryglewskiego" then you will be able to
+    search for it as both "Aleksandra" and "Gryglewskiego".  It will also increase the
+    size of the index.  Useful in countries where searching for the first word in name
+    is not the right thing to do.
+
+    Note that this option is still experimental and there may be problems. If you find
+    any let us know!
+
 --bounds=directory|zipfile
     A directory or a zipfile containing the preprocessed bounds files. 
     Bounds files in a zipfile must be located in the zipfiles root directory.
diff --git a/resources/mkgmap-version.properties b/resources/mkgmap-version.properties
index 78cc6d5..7a0d191 100644
--- a/resources/mkgmap-version.properties
+++ b/resources/mkgmap-version.properties
@@ -1,2 +1,2 @@
-svn.version: 3436
-build.timestamp: 2015-02-02T06:43:48+0000
+svn.version: 3478
+build.timestamp: 2015-02-26T07:49:21+0000
diff --git a/resources/styles/default/inc/name b/resources/styles/default/inc/name
index f3e9d98..67f0a62 100644
--- a/resources/styles/default/inc/name
+++ b/resources/styles/default/inc/name
@@ -13,6 +13,7 @@ operator=${name}  { delete operator; }
 brand=${name}     { delete brand; }
 
 # None of operator, brand given
+ref=* & (operator!=* & brand!=*) & (highway=bus_stop | railway=tram_stop | railway=halt | railway=station) { name '${name} ${ref}' | '${ref}' }
 ref=* & (operator!=* & brand!=*) { name '${ref} ${name}' | '${ref}' }
 
 # Both operator and brand given
@@ -24,6 +25,13 @@ operator=* & brand=* {
 }
 
 # One of operator or brand given
+operator=* & brand!=* & (highway=bus_stop | railway=tram_stop | railway=halt | railway=station) {
+ name '${name} ${ref} ${operator}' |
+      '${name} ${operator}' |
+      '${ref} ${operator}' |
+      '${operator}'
+}
+
 operator=* & brand!=* {
  name '${operator}: ${ref} ${name}' |
       '${operator}: ${name}' |
diff --git a/resources/styles/default/lines b/resources/styles/default/lines
index c43a29c..e2d79c0 100644
--- a/resources/styles/default/lines
+++ b/resources/styles/default/lines
@@ -163,7 +163,8 @@ power=line [0x29 resolution 21]
 
 railway=abandoned [0x0a road_class=0 road_speed=1 resolution 22]
 railway=platform [0x16 road_class=0 road_speed=0 resolution 23]
-railway=* & !(tunnel=yes) [0x14 resolution 22]
+# Railway lines, note that many devices display type 0x14 only at resolution 24 
+(railway=rail | railway=tram | railway=disused | railway=subway | railway=narrow_gauge | railway=light_rail | railway=preserved) & !(tunnel=yes) [0x14 resolution 22]
 
 (man_made=cable|(man_made=* & man_made ~ '.*pipe.*')) & area!=yes &
 tunnel!=yes & location != underground
diff --git a/src/uk/me/parabola/imgfmt/app/labelenc/Utf8Decoder.java b/src/uk/me/parabola/imgfmt/app/labelenc/Utf8Decoder.java
index 73345fc..fe0ed56 100644
--- a/src/uk/me/parabola/imgfmt/app/labelenc/Utf8Decoder.java
+++ b/src/uk/me/parabola/imgfmt/app/labelenc/Utf8Decoder.java
@@ -42,7 +42,6 @@ public class Utf8Decoder implements CharacterDecoder {
 	public boolean addByte(int b) {
 		if (b == 0) {
 			needreset = true;
-			out.write(0);
 			return true;
 		}
 
diff --git a/src/uk/me/parabola/imgfmt/app/mdr/Mdr20.java b/src/uk/me/parabola/imgfmt/app/mdr/Mdr20.java
index 3791d31..a2096ca 100644
--- a/src/uk/me/parabola/imgfmt/app/mdr/Mdr20.java
+++ b/src/uk/me/parabola/imgfmt/app/mdr/Mdr20.java
@@ -88,15 +88,17 @@ public class Mdr20 extends Mdr2x {
 		Collator collator = getConfig().getSort().getCollator();
 
 		String lastName = null;
+		String lastPartialName = null;
 		Mdr5Record lastCity = null;
 		int record = 0;
-		int cityRecord = 0;
+		int cityRecord = 1;
 		int lastMapNumber = 0;
 
 		for (SortKey<Mdr7Record> key : keys) {
 			Mdr7Record street = key.getObject();
 
 			String name = street.getName();
+			String partialName = street.getPartialName();
 			Mdr5Record city = street.getCity();
 
 			boolean citySameByName = city.isSameByName(collator, lastCity);
@@ -104,18 +106,24 @@ public class Mdr20 extends Mdr2x {
 			int mapNumber = city.getMapIndex();
 
 			// Only save a single copy of each street name.
-			if (!citySameByName || mapNumber != lastMapNumber || lastName == null || collator.compare(name, lastName) != 0) {
+			if (!citySameByName || mapNumber != lastMapNumber || lastName == null || lastPartialName == null
+					|| !name.equals(lastName)
+					|| !partialName.equals(lastPartialName))
+			{
 				record++;
 
 				streets.add(street);
 				lastName = name;
+				lastPartialName = partialName;
 			}
 
 			// The mdr20 value changes for each new city name
 			if (citySameByName) {
+				assert cityRecord!=0;
 				city.setMdr20(cityRecord);
 			} else {
 				// New city name, this marks the start of a new section in mdr20
+				assert cityRecord != 0;
 				cityRecord = record;
 				city.setMdr20(cityRecord);
 				lastCity = city;
@@ -137,6 +145,6 @@ public class Mdr20 extends Mdr2x {
 	 * Unknown.
 	 */
 	public int getExtraValue() {
-		return isForDevice() ? 0xa : 0x8800;
+		return isForDevice() ? 0xe : 0x8800;
 	}
 }
diff --git a/src/uk/me/parabola/imgfmt/app/mdr/Mdr22.java b/src/uk/me/parabola/imgfmt/app/mdr/Mdr22.java
index 379d3b4..afd8a35 100644
--- a/src/uk/me/parabola/imgfmt/app/mdr/Mdr22.java
+++ b/src/uk/me/parabola/imgfmt/app/mdr/Mdr22.java
@@ -104,7 +104,7 @@ public class Mdr22 extends Mdr2x {
 	 */
 	public int getExtraValue() {
 		if (isForDevice())
-			return 0x600a;
+			return 0x600e;
 		else
 			return 0x11000;
 	}
diff --git a/src/uk/me/parabola/imgfmt/app/mdr/Mdr2x.java b/src/uk/me/parabola/imgfmt/app/mdr/Mdr2x.java
index bade6d8..d0c1fdf 100644
--- a/src/uk/me/parabola/imgfmt/app/mdr/Mdr2x.java
+++ b/src/uk/me/parabola/imgfmt/app/mdr/Mdr2x.java
@@ -16,7 +16,6 @@ import java.util.ArrayList;
 import java.util.List;
 
 import uk.me.parabola.imgfmt.app.ImgFileWriter;
-import uk.me.parabola.imgfmt.app.Label;
 
 /**
  * Common code for 20, 21, 22 which are all lists of streets ordered in
@@ -39,30 +38,45 @@ public abstract class Mdr2x extends MdrMapSection implements HasHeaderFlags {
 		int size = getSizes().getStreetSizeFlagged();
 
 		boolean hasLabel = hasFlag(0x2);
+
+		String lastPartial = null;
 		int recordNumber = 0;
 		for (Mdr7Record street : streets) {
 			assert street.getMapIndex() == street.getCity().getMapIndex() : street.getMapIndex() + "/" + street.getCity().getMapIndex();
 			addIndexPointer(street.getMapIndex(), ++recordNumber);
 
 			int index = street.getIndex();
-			String name = Label.stripGarminCodes(street.getName());
-			
-			int flag = 1;
+
+			String name = street.getName();
+
+			int repeat = 1;
 			if (name.equals(lastName) && sameGroup(street, prev))
-				flag = 0;
-			lastName = name;
-			prev = street;
+				repeat = 0;
 
 			if (hasLabel) {
 				putMapIndex(writer, street.getMapIndex());
 				int offset = street.getLabelOffset();
-				if (flag != 0)
+				if (repeat != 0)
+					offset |= 0x800000;
+
+				int trailing = 0;
+				String partialName = street.getPartialName();
+				if (!partialName.equals(lastPartial)) {
+					trailing |= 1;
 					offset |= 0x800000;
+				}
+
 				writer.put3(offset);
-				writer.put((byte) flag);
-			}
-			else
-				putN(writer, size, (index << 1) | flag);
+				writer.put(street.getOutNameOffset());
+
+				writer.put((byte) trailing);
+
+				lastPartial = partialName;
+			} else
+				putN(writer, size, (index << 1) | repeat);
+
+			lastName = name;
+			prev = street;
 		}
 	}
 
@@ -78,7 +92,8 @@ public abstract class Mdr2x extends MdrMapSection implements HasHeaderFlags {
 	public int getItemSize() {
 		int size;
 		if (isForDevice()) {
-			size = getSizes().getMapSize() + 3 + 1;
+			// map-index, label, name-offset, 1byte flag
+			size = getSizes().getMapSize() + 3 + 1 + 1;
 		} else {
 			size = getSizes().getStreetSizeFlagged();
 		}
diff --git a/src/uk/me/parabola/imgfmt/app/mdr/Mdr7.java b/src/uk/me/parabola/imgfmt/app/mdr/Mdr7.java
index 6e43a30..e4f1af6 100644
--- a/src/uk/me/parabola/imgfmt/app/mdr/Mdr7.java
+++ b/src/uk/me/parabola/imgfmt/app/mdr/Mdr7.java
@@ -16,8 +16,10 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import uk.me.parabola.imgfmt.MapFailedException;
 import uk.me.parabola.imgfmt.app.ImgFileWriter;
-import uk.me.parabola.imgfmt.app.Label;
+import uk.me.parabola.imgfmt.app.srt.MultiSortKey;
+import uk.me.parabola.imgfmt.app.srt.Sort;
 import uk.me.parabola.imgfmt.app.srt.SortKey;
 
 /**
@@ -27,69 +29,211 @@ import uk.me.parabola.imgfmt.app.srt.SortKey;
  * @author Steve Ratcliffe
  */
 public class Mdr7 extends MdrMapSection {
+	public static final int MDR7_HAS_STRING = 0x01;
+	public static final int MDR7_HAS_NAME_OFFSET = 0x20;
+	public static final int MDR7_PARTIAL_SHIFT = 6;
+	public static final int MDR7_U1 = 0x2;
+	public static final int MDR7_U2 = 0x4;
+
+	private static final int MAX_NAME_OFFSET = 127;
+
+	private final int codepage;
+	private final boolean isMulti;
+	private final boolean splitName;
+
 	private List<Mdr7Record> allStreets = new ArrayList<>();
 	private List<Mdr7Record> streets = new ArrayList<>();
 
+	private final int u2size = 1;
+
 	public Mdr7(MdrConfig config) {
 		setConfig(config);
+		Sort sort = config.getSort();
+		splitName = config.isSplitName();
+		codepage = sort.getCodepage();
+		isMulti = sort.isMulti();
 	}
 
 	public void addStreet(int mapId, String name, int lblOffset, int strOff, Mdr5Record mdrCity) {
+		// Find a name prefix, which is either a shield or a word ending 0x1e. We are treating
+		// a shield as a prefix of length one.
+		int prefix = 0;
+		if (name.charAt(0) < 7)
+			prefix = 1;
+		int sep = name.indexOf(0x1e);
+		if (sep > 0)
+			prefix = sep + 1;
+
+		// Find a name suffix which begins with 0x1f
+		sep = name.indexOf(0x1f);
+		int suffix = 0;
+		if (sep > 0)
+			suffix = sep;
+
+		// Large values can't actually work.
+		if (prefix >= MAX_NAME_OFFSET || suffix >= MAX_NAME_OFFSET)
+			return;
+
 		Mdr7Record st = new Mdr7Record();
 		st.setMapIndex(mapId);
 		st.setLabelOffset(lblOffset);
 		st.setStringOffset(strOff);
 		st.setName(name);
 		st.setCity(mdrCity);
+		st.setPrefixOffset((byte) prefix);
+		st.setSuffixOffset((byte) suffix);
 		allStreets.add(st);
+
+		if (!splitName)
+			return;
+
+		boolean start = false;
+		boolean inWord = false;
+
+		int c;
+		int outOffset = 0;
+
+		int end = Math.min((suffix > 0) ? suffix : name.length() - prefix - 1, MAX_NAME_OFFSET);
+		for (int nameOffset = 0; nameOffset < end; nameOffset += Character.charCount(c)) {
+			c = name.codePointAt(prefix + nameOffset);
+
+			// Don't use any word after a bracket
+			if (c == '(')
+				break;
+
+			if (!Character.isLetterOrDigit(c)) {
+				start = true;
+				inWord = false;
+			} else if (start && Character.isLetterOrDigit(c)) {
+				inWord = true;
+			}
+
+			if (start && inWord && outOffset > 0) {
+				st = new Mdr7Record();
+				st.setMapIndex(mapId);
+				st.setLabelOffset(lblOffset);
+				st.setStringOffset(strOff);
+				st.setName(name);
+				st.setCity(mdrCity);
+				st.setNameOffset((byte) nameOffset);
+				st.setOutNameOffset((byte) outOffset);
+				st.setPrefixOffset((byte) prefix);
+				st.setSuffixOffset((byte) suffix);
+				//System.out.println(st.getName() + ": add partial " + st.getPartialName());
+				allStreets.add(st);
+				start = false;
+			}
+
+			outOffset += outSize(c);
+			if (outOffset > MAX_NAME_OFFSET)
+				break;
+		}
+	}
+
+	/**
+	 * Return the number of bytes that the given character will consume in the output encoded
+	 * format.
+	 */
+	private int outSize(int c) {
+		if (codepage == 65001) {
+			// For unicode a simple lookup gives the number of bytes.
+			if (c < 0x80) {
+				return 1;
+			} else if (c <= 0x7FF) {
+				return 2;
+			} else if (c <= 0xFFFF) {
+				return 3;
+			} else if (c <= 0x10FFFF) {
+				return 4;
+			} else {
+				throw new MapFailedException(String.format("Invalid code point: 0x%x", c));
+			}
+		} else if (!isMulti) {
+			// The traditional single byte code-pages, always one byte.
+			return 1;
+		} else {
+			// Other multi-byte code-pages (eg ms932); can't currently create index for these anyway.
+			return 0;
+		}
 	}
 
 	/**
 	 * Since we change the number of records by removing some after sorting,
 	 * we sort and de-duplicate here.
+	 * This is a performance critical part of the index creation process
+	 * as it requires a lot of heap to store the sort keys. 	  	 
 	 */
 	protected void preWriteImpl() {
-		List<SortKey<Mdr7Record>> sortedStreets = MdrUtils.sortList(getConfig().getSort(), allStreets);
+		Sort sort = getConfig().getSort();
+		List<SortKey<Mdr7Record>> sortedStreets = new ArrayList<>(allStreets.size());
+		for (Mdr7Record m : allStreets) {
+			String partialName = m.getPartialName();
+			String name = m.getName();
+			SortKey<Mdr7Record> nameKey = sort.createSortKey(m, m.getName(), m.getMapIndex());
+			SortKey<Mdr7Record> partialKey = name.equals(partialName) ? nameKey : sort.createSortKey(m, partialName);
+			MultiSortKey<Mdr7Record> sortKey = new MultiSortKey<>(partialKey, nameKey, null);
+			sortedStreets.add(sortKey);
+		}
+		Collections.sort(sortedStreets);
 
 		// De-duplicate the street names so that there is only one entry
 		// per map for the same name.
 		int recordNumber = 0;
 		Mdr7Record last = new Mdr7Record();
-		for (SortKey<Mdr7Record> sk : sortedStreets) {
+		for (int i = 0; i < sortedStreets.size(); i++){ 
+			SortKey<Mdr7Record> sk = sortedStreets.get(i);
 			Mdr7Record r = sk.getObject();
-			if (r.getMapIndex() != last.getMapIndex() || !r.getName().equals(last.getName())) {
+			if (r.getMapIndex() == last.getMapIndex()
+					&& r.getName().equals(last.getName())  // currently think equals is correct, not collator.compare()
+					&& r.getPartialName().equals(last.getPartialName()))
+			{
+				// This has the same name (and map number) as the previous one. Save the pointer to that one
+				// which is going into the file.
+				r.setIndex(recordNumber);
+			} else {
 				recordNumber++;
 				last = r;
 				r.setIndex(recordNumber);
 				streets.add(r);
-			} else {
-				// This has the same name (and map number) as the previous one. Save the pointer to that one
-				// which is going into the file.
-				r.setIndex(recordNumber);
 			}
+			// release memory 
+			sortedStreets.set(i, null);
 		}
 	}
 
 	public void writeSectData(ImgFileWriter writer) {
 		String lastName = null;
-		boolean hasStrings = hasFlag(0x1);
+		String lastPartial = null;
+		boolean hasStrings = hasFlag(MDR7_HAS_STRING);
+		boolean hasNameOffset = hasFlag(MDR7_HAS_NAME_OFFSET);
+
 		for (Mdr7Record s : streets) {
 			addIndexPointer(s.getMapIndex(), s.getIndex());
 
 			putMapIndex(writer, s.getMapIndex());
 			int lab = s.getLabelOffset();
-			String name = Label.stripGarminCodes(s.getName());
-			int trailingFlags = 0;
+			String name = s.getName();
 			if (!name.equals(lastName)) {
 				lab |= 0x800000;
 				lastName = name;
-				trailingFlags = 1;
 			}
+
+			String partialName = s.getPartialName();
+			int trailingFlags = 0;
+			if (!partialName.equals(lastPartial)) {
+				trailingFlags |= 1;
+				lab |= 0x800000;  // If it is not a partial repeat, then it is not a complete repeat either
+			}
+			lastPartial = partialName;
+
 			writer.put3(lab);
 			if (hasStrings)
 				putStringOffset(writer, s.getStringOffset());
-			
-			writer.put((byte) trailingFlags);
+
+			if (hasNameOffset)
+				writer.put(s.getOutNameOffset());
+
+			putN(writer, u2size, trailingFlags);
 		}
 	}
 
@@ -99,9 +243,11 @@ public class Mdr7 extends MdrMapSection {
 	 */
 	public int getItemSize() {
 		PointerSizes sizes = getSizes();
-		int size = sizes.getMapSize() + 3 + 1;
+		int size = sizes.getMapSize() + 3 + u2size;
 		if (!isForDevice())
 			size += sizes.getStrOffSize();
+		if ((getExtraValue() & MDR7_HAS_NAME_OFFSET) != 0)
+			size += 1;
 		return size;
 	}
 
@@ -113,11 +259,12 @@ public class Mdr7 extends MdrMapSection {
 	 * Value of 3 possibly the existence of the lbl field.
 	 */
 	public int getExtraValue() {
-		int magic = 0x42;
+		int magic = MDR7_U1 | MDR7_HAS_NAME_OFFSET | (u2size << MDR7_PARTIAL_SHIFT);
+
 		if (isForDevice()) {
-			magic |= 0x4;
+			magic |= MDR7_U2;
 		} else {
-			magic |= 0x1; //strings
+			magic |= MDR7_HAS_STRING;
 		}
 
 		return magic;
diff --git a/src/uk/me/parabola/imgfmt/app/mdr/Mdr7Record.java b/src/uk/me/parabola/imgfmt/app/mdr/Mdr7Record.java
index d26af18..6a3562e 100644
--- a/src/uk/me/parabola/imgfmt/app/mdr/Mdr7Record.java
+++ b/src/uk/me/parabola/imgfmt/app/mdr/Mdr7Record.java
@@ -23,6 +23,12 @@ public class Mdr7Record extends RecordBase implements NamedRecord {
 	private int index;
 	private Mdr5Record city;
 
+	// For searching on partial names
+	private byte nameOffset; // offset into the name where matching should start
+	private byte outNameOffset; // offset into the encoded output name
+	private byte prefixOffset;  // offset after 0x1e prefix
+	private byte suffixOffset;  // offset just before 0x1f suffix
+
 	public int getLabelOffset() {
 		return labelOffset;
 	}
@@ -63,6 +69,43 @@ public class Mdr7Record extends RecordBase implements NamedRecord {
 		return city;
 	}
 
+	public void setNameOffset(byte nameOffset) {
+		this.nameOffset = nameOffset;
+	}
+
+	public byte getOutNameOffset() {
+		return outNameOffset;
+	}
+
+	public void setOutNameOffset(byte outNameOffset) {
+		this.outNameOffset = outNameOffset;
+	}
+
+	public void setPrefixOffset(byte prefixOffset) {
+		this.prefixOffset = prefixOffset;
+	}
+
+	public void setSuffixOffset(byte suffixOffset) {
+		this.suffixOffset = suffixOffset;
+	}
+
+	/**
+	 * Get the name starting at the given nameOffset.
+	 *
+	 * To avoid creating unnecessary objects, a check is made for an offset of zero
+	 * and the original name string is returned.
+	 *
+	 * @return A substring of name, starting at the nameOffset value.
+	 */
+	public String getPartialName() {
+		if (nameOffset == 0 && prefixOffset == 0 && suffixOffset == 0)
+			return name;
+		else if ((suffixOffset & 0xff) > 0)
+			return name.substring((nameOffset & 0xff) + (prefixOffset & 0xff), (suffixOffset & 0xff));
+		else
+			return name.substring((nameOffset & 0xff) + (prefixOffset & 0xff));
+	}
+
 	public String toString() {
 		return name + " in " + city.getName();
 	}
diff --git a/src/uk/me/parabola/imgfmt/app/mdr/MdrConfig.java b/src/uk/me/parabola/imgfmt/app/mdr/MdrConfig.java
index 893e83f..a3bcf6e 100644
--- a/src/uk/me/parabola/imgfmt/app/mdr/MdrConfig.java
+++ b/src/uk/me/parabola/imgfmt/app/mdr/MdrConfig.java
@@ -32,6 +32,7 @@ public class MdrConfig {
 	private int headerLen = DEFAULT_HEADER_LEN;
 	private Sort sort;
 	private File outputDir;
+	private boolean splitName;
 
 	/**
 	 * True if we are creating the file, rather than reading it.
@@ -87,4 +88,12 @@ public class MdrConfig {
 		if (outputDir != null)
 			this.outputDir = new File(outputDir);
 	}
+
+	public void setSplitName(boolean splitName) {
+		this.splitName = splitName;
+	}
+
+	public boolean isSplitName() {
+		return splitName;
+	}
 }
diff --git a/src/uk/me/parabola/mkgmap/combiners/GmapsuppBuilder.java b/src/uk/me/parabola/mkgmap/combiners/GmapsuppBuilder.java
index f173a2c..8c9005a 100644
--- a/src/uk/me/parabola/mkgmap/combiners/GmapsuppBuilder.java
+++ b/src/uk/me/parabola/mkgmap/combiners/GmapsuppBuilder.java
@@ -83,6 +83,7 @@ public class GmapsuppBuilder implements Combiner {
 	// There is a separate MDR and SRT file for each family id in the gmapsupp
 	private final Map<Integer, MdrBuilder> mdrBuilderMap = new LinkedHashMap<Integer, MdrBuilder>();
 	private final Map<Integer, Sort> sortMap = new LinkedHashMap<Integer, Sort>();
+	private boolean splitName;
 
 
 	public void init(CommandArgs args) {
@@ -90,6 +91,7 @@ public class GmapsuppBuilder implements Combiner {
 		mapsetName = args.get("mapset-name", "OSM map set");
 		overallDescription = args.getDescription();
 		outputDir = args.getOutputDir();
+		splitName = args.get("split-name-index", false);
 	}
 
 	/**
@@ -106,7 +108,7 @@ public class GmapsuppBuilder implements Combiner {
 			return mdrBuilder;
 
 		mdrBuilder = new MdrBuilder();
-		mdrBuilder.initForDevice(sort, outputDir);
+		mdrBuilder.initForDevice(sort, outputDir, splitName);
 		mdrBuilderMap.put(familyId, mdrBuilder);
 		return mdrBuilder;
 	}
diff --git a/src/uk/me/parabola/mkgmap/combiners/MdrBuilder.java b/src/uk/me/parabola/mkgmap/combiners/MdrBuilder.java
index 63362bd..487cfc4 100644
--- a/src/uk/me/parabola/mkgmap/combiners/MdrBuilder.java
+++ b/src/uk/me/parabola/mkgmap/combiners/MdrBuilder.java
@@ -111,6 +111,7 @@ public class MdrBuilder implements Combiner {
 		config.setForDevice(false);
 		config.setOutputDir(outputDir);
 		config.setSort(sort);
+		config.setSplitName(args.get("split-name-index", false));
 
 		// Wrap the MDR channel with the MDRFile object
 		mdrFile = new MDRFile(mdrChan, config);
@@ -128,13 +129,14 @@ public class MdrBuilder implements Combiner {
 		}
 	}
 
-	void initForDevice(Sort sort, String outputDir) {
+	void initForDevice(Sort sort, String outputDir, boolean splitName) {
 		// Set the options that we are using for the mdr.
 		MdrConfig config = new MdrConfig();
 		config.setHeaderLen(568);
 		config.setWritable(true);
 		config.setForDevice(true);
 		config.setSort(sort);
+		config.setSplitName(splitName);
 
 		// Wrap the MDR channel with the MDRFile object
 		try {
diff --git a/src/uk/me/parabola/mkgmap/osmstyle/RuleFileReader.java b/src/uk/me/parabola/mkgmap/osmstyle/RuleFileReader.java
index 1d69c56..ff6b4f9 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/RuleFileReader.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/RuleFileReader.java
@@ -352,28 +352,34 @@ public class RuleFileReader {
 			// Transform ((first | second) & topSecond)
 			// into (first & topSecond) | (second & topSecond)
 
-			Op first = op1.getFirst();
-			OrOp orOp = new OrOp();
+			return distrubute(op1, top.getSecond());
+		} else {
+			// This shouldn't happen
+			throw new SyntaxException("X3:" + op1.getType());
+		}
+		return top;
+	}
 
-			Op topSecond = top.getSecond();
+	private static OrOp distrubute(Op op1, Op topSecond) {
+		Op first = op1.getFirst();
+		OrOp orOp = new OrOp();
 
-			AndOp and1 = new AndOp();
-			and1.setFirst(first);
-			and1.setSecond(topSecond);
+		BinaryOp and1 = new AndOp();
+		and1.setFirst(first);
+		and1.setSecond(topSecond);
 
-			AndOp and2 = new AndOp();
-			Op second = rearrangeExpression(op1.getSecond());
+		BinaryOp and2 = new AndOp();
+		Op second = rearrangeExpression(op1.getSecond());
+		if (second.isType(OR)) {
+			and2 = distrubute(second, topSecond);
+		} else {
 			and2.setFirst(second);
 			and2.setSecond(topSecond);
-
-			orOp.setFirst(and1);
-			orOp.setSecond(and2);
-			return orOp;
-		} else {
-			// This shouldn't happen
-			throw new SyntaxException("X3:" + op1.getType());
 		}
-		return top;
+		orOp.setFirst(and1);
+		orOp.setSecond(and2);
+
+		return orOp;
 	}
 
 	/**
diff --git a/src/uk/me/parabola/mkgmap/scan/SyntaxException.java b/src/uk/me/parabola/mkgmap/scan/SyntaxException.java
index 66c80da..e533913 100644
--- a/src/uk/me/parabola/mkgmap/scan/SyntaxException.java
+++ b/src/uk/me/parabola/mkgmap/scan/SyntaxException.java
@@ -47,7 +47,7 @@ public class SyntaxException extends RuntimeException {
 		if (fileName != null)
 			fmt.format("(%s:%d): ", fileName, lineNumber);
 
-		fmt.format(super.getMessage());
+		fmt.format("%s", super.getMessage());
 		return fmt.toString();
 	}
 }
diff --git a/test/resources/rules/multi-or-twice.test b/test/resources/rules/multi-or-twice.test
new file mode 100644
index 0000000..30e97df
--- /dev/null
+++ b/test/resources/rules/multi-or-twice.test
@@ -0,0 +1,18 @@
+
+WAY
+highway=primary
+name=b
+a=2
+b=5
+
+<<<lines>>>
+
+(highway=secondary | a=2 | b=5) & (highway=service | a=0 | b=5) { set name='a${name}' }
+
+highway=* [0x2]
+
+<finalize>
+highway=* {name '${name}' }
+
+<<<results>>>
+WAY 1: Line 0x2, labels=[ab, null, null, null], res=24-24 (1/1),(2/2),
diff --git a/test/resources/rules/multi-or-with-and.test b/test/resources/rules/multi-or-with-and.test
new file mode 100644
index 0000000..e9d3267
--- /dev/null
+++ b/test/resources/rules/multi-or-with-and.test
@@ -0,0 +1,19 @@
+
+WAY
+highway=primary
+name=b
+c=60
+d=50
+
+<<<lines>>>
+
+(highway=primary | name=b | d=50) & highway=primary {
+	set name='a${name}'
+}
+
+highway=primary [0x2]
+
+<finalize>
+highway=* {name '${name}'}
+<<<results>>>
+WAY 1: Line 0x2, labels=[ab, null, null, null], res=24-24 (1/1),(2/2),
diff --git a/test/resources/rules/or-at-end.test b/test/resources/rules/or-at-end.test
new file mode 100644
index 0000000..3ff0d02
--- /dev/null
+++ b/test/resources/rules/or-at-end.test
@@ -0,0 +1,30 @@
+
+WAY
+highway=tertiary
+name=b
+oneway=1
+cycleway=opposite
+
+WAY 2
+highway=tertiary
+name=b
+oneway=1
+cycleway=opposite_lane
+
+
+<<<lines>>>
+highway ~ '(secondary|tertiary|unclassified|residential|minor|living_street|service)'
+	& oneway=*
+	& (cycleway=opposite | cycleway=opposite_lane | cycleway=opposite_track )
+	{ set name='a${name}' }
+	[0x2 ]
+
+
+<finalize>
+highway=* {name '${name}' }
+
+<<<results>>>
+WAY 1: Line 0x2, labels=[ab, null, null, null], res=24-24 oneway (1/1),(2/2),
+WAY 2: Line 0x2, labels=[ab, null, null, null], res=24-24 oneway (1/1),(2/2),
+
+
diff --git a/test/uk/me/parabola/mkgmap/osmstyle/RuleFileReaderTest.java b/test/uk/me/parabola/mkgmap/osmstyle/RuleFileReaderTest.java
index c9423b6..99ef40c 100644
--- a/test/uk/me/parabola/mkgmap/osmstyle/RuleFileReaderTest.java
+++ b/test/uk/me/parabola/mkgmap/osmstyle/RuleFileReaderTest.java
@@ -406,6 +406,7 @@ public class RuleFileReaderTest {
 		type = getFirstType(rs, el);
 		assertNotNull(type);
 
+		el = el.copy();  // Copy for LinkedOp which remembers the last matched element
 		el.addTag("cycleway", "opposite_lane");
 		type = getFirstType(rs, el);
 		assertNotNull(type);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/mkgmap.git



More information about the Pkg-grass-devel mailing list