Index: src/uk/me/parabola/imgfmt/app/net/Numbers.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/net/Numbers.java	(revision 3540)
+++ src/uk/me/parabola/imgfmt/app/net/Numbers.java	(working copy)
@@ -13,6 +13,7 @@
 package uk.me.parabola.imgfmt.app.net;
 
 import uk.me.parabola.log.Logger;
+import uk.me.parabola.mkgmap.general.CityInfo;
 
 /**
  * Describes the house numbering from a node in the road.
@@ -20,28 +21,50 @@
  */
 public class Numbers {
 	private static final Logger log = Logger.getLogger(Numbers.class);
-
+	public static final boolean LEFT = true;
+	public static final boolean RIGHT = false;
+	
 	// The node in the road where these numbers apply.  In the polish notation it is the
 	// node in the road, whereas in the NET file it is the number of the routing node.
 	private int nodeNumber; // node in road index
 	private Integer rnodNumber; // routing node index
+	// the data on side of the road
+	private RoadSide leftSide,rightSide;
+	
+	private class RoadSide {
+		NumDesc numbers;
+		// to be added
+		CityInfo cityInfo; 
+		String zipCode;
+		
+		boolean isEmpty(){
+			return cityInfo == null && zipCode == null && numbers == null;
+		}
+	}
 
-	// On the left hand side of the road.
-	private NumberStyle leftNumberStyle;
-	private int leftStart;
-	private int leftEnd;
+	private class NumDesc{
+		NumberStyle numberStyle;
+		int start,end;
+		
+		public NumDesc(NumberStyle numberStyle, int start, int end) {
+			this.numberStyle = numberStyle;
+			this.start = start;
+			this.end = end;
+		}
 
-	// On the right hand side of the road.
-	private NumberStyle rightNumberStyle;
-	private int rightStart;
-	private int rightEnd;
-
+		@Override
+		public String toString() {
+			return String.format("%s,%d,%d", numberStyle, start,end);
+		}
+			
+	}
+	
 	public Numbers() {
 	}
 
 	/**
 	 * This constructor takes a comma separated list as in the polish format. Also used in testing as
-	 * it is an easy way to set all the parameters at once.
+	 * it is an easy way to set all common parameters at once.
 	 *
 	 * @param spec Node number, followed by left and then right parameters as in the polish format.
 	 */
@@ -48,14 +71,79 @@
 	public Numbers(String spec) {
 		String[] strings = spec.split(",");
 		nodeNumber = Integer.valueOf(strings[0]);
-		leftNumberStyle = NumberStyle.fromChar(strings[1]);
-		leftStart = Integer.valueOf(strings[2]);
-		leftEnd = Integer.valueOf(strings[3]);
-		rightNumberStyle = NumberStyle.fromChar(strings[4]);
-		rightStart = Integer.valueOf(strings[5]);
-		rightEnd = Integer.valueOf(strings[6]);
+		NumberStyle numberStyle = NumberStyle.fromChar(strings[1]);
+		int start = Integer.valueOf(strings[2]);
+		int end = Integer.valueOf(strings[3]);
+		setNumbers(LEFT, numberStyle, start, end);
+		numberStyle = NumberStyle.fromChar(strings[4]);
+		start = Integer.valueOf(strings[5]);
+		end = Integer.valueOf(strings[6]);
+		setNumbers(RIGHT, numberStyle, start, end);
 	}
 
+	public void setNumbers(boolean left, NumberStyle numberStyle, int start, int end){
+		if (numberStyle != NumberStyle.NONE || start != -1 || end != -1){
+			RoadSide rs = assureSideIsAllocated(left);
+			rs.numbers = new NumDesc(numberStyle, start, end);
+		} else {
+			RoadSide rs = (left) ? leftSide : rightSide;
+			if (rs != null)
+				rs.numbers = null;
+			removeIfEmpty(left);
+		}
+	}
+
+	public void setCityInfo(boolean left, CityInfo ci){
+		if (ci != null){
+			RoadSide rs = assureSideIsAllocated(left);
+			rs.cityInfo = ci;
+		} else {
+			RoadSide rs = (left) ? leftSide : rightSide;
+			if (rs != null)
+				rs.cityInfo = null;
+			removeIfEmpty(left);
+		}
+	}
+	
+	public CityInfo getCityInfo(boolean left){
+		RoadSide rs = (left) ? leftSide : rightSide;
+		return (rs != null) ? rs.cityInfo : null;
+	}
+
+	public String getZipCode(boolean left){
+		RoadSide rs = (left) ? leftSide : rightSide;
+		return (rs != null) ? rs.zipCode : null; 
+	}
+	
+
+	public void setZipCode(boolean left, String zipCode){
+		if (zipCode != null){
+			RoadSide rs = assureSideIsAllocated(left);
+			rs.zipCode = zipCode;
+		} else {
+			RoadSide rs = (left) ? leftSide : rightSide;
+			if (rs != null)
+				rs.zipCode= null;
+			removeIfEmpty(left);
+		}
+	}
+	
+	private void removeIfEmpty(boolean left){
+		if (left && leftSide != null && leftSide.isEmpty())
+			leftSide = null;
+		if (!left && rightSide != null && rightSide.isEmpty())
+			rightSide = null;
+	}
+	
+	// allocate or return allocated RoadSide instance for the given road side
+	private RoadSide assureSideIsAllocated(boolean left){
+		if (left && leftSide == null)
+			leftSide = new RoadSide();
+		if (!left && rightSide == null)
+			rightSide = new RoadSide();
+		return (left) ? leftSide : rightSide;
+	}
+	
 	public int getNodeNumber() {
 		return nodeNumber;
 	}
@@ -80,54 +168,27 @@
 		this.rnodNumber = rnodNumber;
 	}
 
-	public NumberStyle getLeftNumberStyle() {
-		return leftNumberStyle;
+	private NumDesc getNumbers(boolean left) {
+		RoadSide rs = (left) ? leftSide : rightSide;
+		return (rs != null) ? rs.numbers : null;  
 	}
 
-	public void setLeftNumberStyle(NumberStyle leftNumberStyle) {
-		this.leftNumberStyle = leftNumberStyle;
+	public NumberStyle getNumberStyle(boolean left) {
+		NumDesc n = getNumbers(left);
+		return (n == null) ? NumberStyle.NONE : n.numberStyle;
 	}
 
-	public int getLeftStart() {
-		return leftStart;
+	public int getStart(boolean left) {
+		NumDesc n = getNumbers(left);
+		return (n == null) ? -1 : n.start; // -1 is the default in the polish format
 	}
 
-	public void setLeftStart(int leftStart) {
-		this.leftStart = leftStart;
+	public int getEnd(boolean left) {
+		NumDesc n = getNumbers(left);
+		return (n == null) ? -1 : n.end; // -1 is the default in the polish format
 	}
 
-	public int getLeftEnd() {
-		return leftEnd;
-	}
-
-	public void setLeftEnd(int leftEnd) {
-		this.leftEnd = leftEnd;
-	}
-
-	public NumberStyle getRightNumberStyle() {
-		return rightNumberStyle;
-	}
-
-	public void setRightNumberStyle(NumberStyle rightNumberStyle) {
-		this.rightNumberStyle = rightNumberStyle;
-	}
-
-	public int getRightStart() {
-		return rightStart;
-	}
-
-	public void setRightStart(int rightStart) {
-		this.rightStart = rightStart;
-	}
-
-	public int getRightEnd() {
-		return rightEnd;
-	}
-
-	public void setRightEnd(int rightEnd) {
-		this.rightEnd = rightEnd;
-	}
-
+	
 	public String toString() {
 		String nodeStr = "0";
 		if (nodeNumber > 0)
@@ -137,23 +198,30 @@
 
 		return String.format("%s,%s,%d,%d,%s,%d,%d",
 				nodeStr,
-				leftNumberStyle,
-				leftStart,
-				leftEnd,
-				rightNumberStyle,
-				rightStart,
-				rightEnd);
+				getNumberStyle(LEFT),
+				getStart(LEFT),
+				getEnd(LEFT),
+				getNumberStyle(RIGHT),
+				getStart(RIGHT),
+				getEnd(RIGHT));
 	}
 
-	public boolean equals(Object obj) {
-		if (!(obj instanceof Numbers))
-			return false;
-
-		Numbers other = (Numbers) obj;
-		return toString().equals(other.toString());
+	public NumberStyle getLeftNumberStyle() {
+		return getNumberStyle(LEFT);
 	}
-
-	public int hashCode() {
-		return toString().hashCode();
+	public NumberStyle getRightNumberStyle() {
+		return getNumberStyle(RIGHT);
 	}
+	public int getLeftStart(){
+		return getStart(LEFT);
+	}
+	public int getRightStart(){
+		return getStart(RIGHT);
+	}
+	public int getLeftEnd(){
+		return getEnd(LEFT);
+	}
+	public int getRightEnd(){
+		return getEnd(RIGHT);
+	}
 }
Index: src/uk/me/parabola/mkgmap/general/CityInfo.java
===================================================================
--- src/uk/me/parabola/mkgmap/general/CityInfo.java	(revision 0)
+++ src/uk/me/parabola/mkgmap/general/CityInfo.java	(working copy)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2015 Gerd Petermann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 or
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program 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
+ * General Public License for more details.
+ */
+package uk.me.parabola.mkgmap.general;
+
+public class CityInfo implements Comparable<CityInfo> {
+	private static final String UNKNOWN = "?";
+	private final String city,region,country;
+	public CityInfo (String city, String region, String country){
+		this.city = (city != null) ? city: UNKNOWN;
+		this.region = (region != null) ?  region : UNKNOWN;
+		this.country = (country != null) ? country : UNKNOWN;
+	}
+	
+
+	public String getCity() {
+		if (city == UNKNOWN)
+			return null;
+		return city;
+	}
+
+	public String getRegion() {
+		if (region == UNKNOWN)
+			return null;
+		return region;
+	}
+
+	public String getCountry() {
+		if (country == UNKNOWN)
+			return null;
+		return country;
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((city == null) ? 0 : city.hashCode());
+		result = prime * result + ((country == null) ? 0 : country.hashCode());
+		result = prime * result + ((region == null) ? 0 : region.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (!(obj instanceof CityInfo))
+			return false;
+		CityInfo other = (CityInfo) obj;
+		
+		if (city == null && other.city != null )
+			return false;
+		return city.equals(other.city) && region.equals(other.region) && country.equals(other.country);
+	}
+
+	@Override
+	public int compareTo(CityInfo o) {
+		if (this == o)
+			return 0;
+		int d = city.compareTo(o.city);
+		if (d != 0)
+			return d;
+		d = region.compareTo(o.region);
+		if (d != 0)
+			return d;
+		return country.compareTo(o.country);
+	}
+
+	@Override
+	public String toString() {
+		return city + "/" + region + " in " + country; 
+	}
+}
Index: src/uk/me/parabola/mkgmap/osmstyle/housenumber/HousenumberGenerator.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/housenumber/HousenumberGenerator.java	(revision 3540)
+++ src/uk/me/parabola/mkgmap/osmstyle/housenumber/HousenumberGenerator.java	(working copy)
@@ -430,9 +430,9 @@
 					log.info("Left: ",numbers.getLeftNumberStyle(),numbers.getRnodNumber(),"Start:",numbers.getLeftStart(),"End:",numbers.getLeftEnd(), "Remaining: "+leftNumbers);
 					log.info("Right:",numbers.getRightNumberStyle(),numbers.getRnodNumber(),"Start:",numbers.getRightStart(),"End:",numbers.getRightEnd(), "Remaining: "+rightNumbers);
 				}
+				if (numbers.getLeftNumberStyle() != NumberStyle.NONE || numbers.getRightNumberStyle() != NumberStyle.NONE)
+					numbersListing.add(numbers);
 				
-				numbersListing.add(numbers);
-				
 				lastRoutableNodeIndex = nodeIndex;
 				nodeIndex++;
 				n++;
@@ -482,23 +482,10 @@
 				
 				int start = housenumbers.get(0).getHousenumber();
 				int end = housenumbers.get(maxN).getHousenumber();
-				if (left) { 
-					numbers.setLeftStart(start);
-					numbers.setLeftEnd(end);
-				} else {
-					numbers.setRightStart(start);
-					numbers.setRightEnd(end);
-				}
-				
+				numbers.setNumbers(left, style, start, end);
 				housenumbers.subList(0, maxN+1).clear();
 			}
 		}
-		
-		if (left)
-			numbers.setLeftNumberStyle(style);
-		else
-			numbers.setRightNumberStyle(style);
-		
 	}
 	
 	/**
Index: test/func/lib/NumberReader.java
===================================================================
--- test/func/lib/NumberReader.java	(revision 3540)
+++ test/func/lib/NumberReader.java	(working copy)
@@ -291,15 +291,9 @@
 
 		Numbers n = new Numbers();
 		n.setRnodNumber(nodeCounter);
+		n.setNumbers(Numbers.LEFT, leftStyle, leftStart, leftEnd);
+		n.setNumbers(Numbers.RIGHT, rightStyle, rightStart, rightEnd);
 
-		n.setLeftNumberStyle(leftStyle);
-		n.setLeftStart(leftStart);
-		n.setLeftEnd(leftEnd);
-
-		n.setRightNumberStyle(rightStyle);
-		n.setRightStart(rightStart);
-		n.setRightEnd(rightEnd);
-
 		numbers.add(n);
 		nodeCounter++;
 
@@ -331,26 +325,11 @@
 		adjustValues();
 
 		Numbers n = new Numbers();
-		if (leftStyle == NONE) {
-			n.setRnodNumber(nodeCounter);
-			n.setRightNumberStyle(rightStyle);
-			n.setRightStart(rightStart);
-			n.setRightEnd(rightEnd);
-
-			n.setLeftNumberStyle(NONE);
-			n.setLeftStart(-1);
-			n.setLeftEnd(-1);
-		}
-		else {
-			n.setRnodNumber(nodeCounter);
-			n.setLeftNumberStyle(leftStyle);
-			n.setLeftStart(leftStart);
-			n.setLeftEnd(leftEnd);
-
-			n.setRightNumberStyle(NONE);
-			n.setRightStart(-1);
-			n.setRightEnd(-1);
-		}
+		n.setRnodNumber(nodeCounter);
+		if (leftStyle == NONE) 
+			n.setNumbers(Numbers.RIGHT, rightStyle, rightStart, rightEnd);
+		else 
+			n.setNumbers(Numbers.LEFT, leftStyle, leftStart, leftEnd);
 		numbers.add(n);
 		nodeCounter++;
 	}
