diff --git a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java index d600025..b67584b 100644 --- a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java +++ b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java @@ -17,7 +17,8 @@ import java.util.Map; import java.util.StringTokenizer; import java.util.TreeMap; -import btools.util.*; +import btools.util.BitCoderContext; +import btools.util.Crc32; public final class BExpressionContext @@ -122,6 +123,7 @@ public final class BExpressionContext ctx.encodeBit( ld[0] != 0 ); int skippedTags = 0; + int nonNullTags= 0; // all others are generic for( int inum = 1; inum < lookupValues.size(); inum++ ) // loop over lookup names @@ -133,6 +135,7 @@ public final class BExpressionContext continue; } ctx.encodeDistance( skippedTags+1 ); + nonNullTags++; skippedTags = 0; // 0 excluded already, 1 (=unknown) we rotate up to 8 @@ -141,15 +144,53 @@ public final class BExpressionContext ctx.encodeDistance( dd ); } ctx.encodeDistance( 0 ); + + if ( nonNullTags == 0) return null; + int len = ctx.getEncodedLength(); byte[] ab = new byte[len]; System.arraycopy( abBuf, 0, ab, 0, len ); + + + // crosscheck: decode and compare + int[] ld2 = new int[lookupValues.size()]; + decode( ld2, ab ); + for( int inum = 0; inum < lookupValues.size(); inum++ ) // loop over lookup names + { + if ( ld2[inum] != ld[inum] ) throw new RuntimeException( "assertion failed encoding " + getKeyValueDescription(ab) ); + } + return ab; } - private byte[] encodeFix( int[] ld ) + /** + * encode lookup data to a 64-bit word + */ + public byte[] encodeFix( int[] ld ) { - throw new IllegalArgumentException( "encoding fixed-length not supporte" ); + long w = 0; + for( int inum = 0; inum < lookupValues.size(); inum++ ) // loop over lookup names + { + int n = lookupValues.get(inum).length - 1; + int d = ld[inum]; + if ( n == 2 ) { n = 1; d = d == 2 ? 1 : 0; } // 1-bit encoding for booleans + + while( n != 0 ) { n >>= 1; w <<= 1; } + w |= (long)d; + } + if ( w == 0) return null; + + byte[] ab = new byte[8]; + int aboffset = 0; + ab[aboffset++] = (byte)( (w >> 56) & 0xff ); + ab[aboffset++] = (byte)( (w >> 48) & 0xff ); + ab[aboffset++] = (byte)( (w >> 40) & 0xff ); + ab[aboffset++] = (byte)( (w >> 32) & 0xff ); + ab[aboffset++] = (byte)( (w >> 24) & 0xff ); + ab[aboffset++] = (byte)( (w >> 16) & 0xff ); + ab[aboffset++] = (byte)( (w >> 8) & 0xff ); + ab[aboffset++] = (byte)( (w ) & 0xff ); + return ab; } @@ -186,7 +227,7 @@ public final class BExpressionContext // see encoder for value rotation int dd = ctx.decodeDistance(); int d = dd == 7 ? 1 : ( dd < 7 ? dd + 2 : dd + 1); - if ( d >= lookupValues.get(inum).length ) d = 1; // map out-of-range to unkown + if ( d >= lookupValues.get(inum).length ) d = 1; // map out-of-range to unknown ld[inum++] = d; } while( inum < ld.length ) ld[inum++] = 0; @@ -257,10 +298,7 @@ public final class BExpressionContext for( int inum = 0; inum < lookupValues.size(); inum++ ) // loop over lookup names { BExpressionLookupValue[] va = lookupValues.get(inum); - int dataIdx = lookupData[inum]; - if ( dataIdx >= va.length ) - throw new RuntimeException( "ups, inum=" + inum + " dataIdx=" + dataIdx + " va.length=" + va.length + " sb=" + sb ); - String value = va[dataIdx].toString(); + String value = va[lookupData[inum]].toString(); if ( value != null && value.length() > 0 ) { sb.append( " " + lookupNames.get( inum ) + "=" + value ); @@ -576,7 +614,7 @@ public final class BExpressionContext public boolean getBooleanLookupValue( String name ) { Integer num = lookupNumbers.get( name ); - return num != null && lookupData[num.intValue()] != 0; + return num != null && lookupData[num.intValue()] == 2; } public void parseFile( File file, String readOnlyContext ) diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java b/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java index 88251f4..1e45f11 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java @@ -82,7 +82,7 @@ public class OsmNodeP implements Comparable return null; } - public void writeNodeData( DataOutputStream os ) throws IOException + public void writeNodeData( DataOutputStream os, boolean writeVarLength ) throws IOException { int lonIdx = ilon/62500; int latIdx = ilat/62500; @@ -131,45 +131,68 @@ public class OsmNodeP implements Comparable OsmNodeP target = link.targetNode; int tranferbit = target.isTransferNode() ? TRANSFERNODE_BITMASK : 0; - int writedescbit = link.descriptionBitmap != lastDescription ? WRITEDESC_BITMASK : 0; int nodedescbit = nodeDescription != null ? NODEDESC_BITMASK : 0; - if ( skipDetailBit != 0 ) + int writedescbit = 0; + if ( skipDetailBit == 0 ) // check if description changed { - writedescbit = 0; + int inverseBitByteIndex = writeVarLength ? 0 : 7; + boolean inverseDirection = link instanceof OsmLinkPReverse; + byte[] ab = link.descriptionBitmap; + int abLen = ab.length; + int lastLen = lastDescription == null ? 0 : lastDescription.length; + boolean equalsCurrent = abLen == lastLen; + if ( equalsCurrent ) + { + for( int i=0; i 1 ) os2.write( dbytes, 1, len-1 ); + int len = lastDescription.length; + if ( writeVarLength ) os2.writeByte( len ); + os2.write( lastDescription, 0, len ); } if ( nodedescbit != 0 ) { - os2.writeByte( nodeDescription.length ); os2.write( nodeDescription ); + if ( writeVarLength ) os2.writeByte( nodeDescription.length ); + os2.write( nodeDescription ); nodeDescription = null; } - lastDescription = link.descriptionBitmap; if ( tranferbit == 0) { diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java b/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java index a667ed1..317ec31 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java @@ -40,6 +40,7 @@ public class WayLinker extends MapCreatorBase private CompactLongSet borderSet; private short lookupVersion; private short lookupMinorVersion; + private boolean writeVarLength; private long creationTimeStamp; @@ -81,6 +82,7 @@ public class WayLinker extends MapCreatorBase expctxWay.readMetaData( lookupFile ); lookupVersion = expctxWay.lookupVersion; lookupMinorVersion = expctxWay.lookupMinorVersion; + writeVarLength = expctxWay.readVarLength; expctxWay.parseFile( profileFile, "global" ); creationTimeStamp = System.currentTimeMillis(); @@ -268,7 +270,7 @@ public class WayLinker extends MapCreatorBase for( int ni=0; ni