From 8fa82633d459c3f5f5d4648fc9d925e6be26d930 Mon Sep 17 00:00:00 2001 From: Arndt Date: Thu, 19 Jun 2014 09:15:51 +0200 Subject: [PATCH] 1.0 preparations --- .../java/btools/router/RoutingContext.java | 10 +- .../java/btools/router/RoutingEngine.java | 79 ++++---- .../expressions/BExpressionContext.java | 142 ++++++-------- .../expressions/BExpressionMetaData.java | 91 +++++++++ .../btools/expressions/EncodeDecodeTest.java | 5 +- .../btools/mapcreator/MapCreatorBase.java | 12 +- .../main/java/btools/mapcreator/NodeData.java | 20 +- .../java/btools/mapcreator/NodeFilter.java | 6 +- .../java/btools/mapcreator/NodeIterator.java | 5 +- .../java/btools/mapcreator/OsmCutter.java | 18 +- .../main/java/btools/mapcreator/OsmNodeP.java | 74 ++++---- .../java/btools/mapcreator/OsmNodePT.java | 3 - .../java/btools/mapcreator/PosUnifier.java | 5 +- .../btools/mapcreator/RelationMerger.java | 17 +- .../java/btools/mapcreator/WayLinker.java | 48 +++-- .../java/btools/mapaccess/MicroCache.java | 89 +++------ .../java/btools/mapaccess/NodesCache.java | 8 +- .../main/java/btools/mapaccess/OsmFile.java | 2 + .../main/java/btools/mapaccess/OsmNode.java | 52 +++-- .../btools/mapaccess/OsmTransferNode.java | 3 + .../java/btools/mapaccess/PhysicalFile.java | 4 +- brouter-routing-app/AndroidManifest.xml | 4 +- brouter-routing-app/assets/profiles2.zip | Bin 9013 -> 11406 bytes .../btools/routingapp/BInstallerView.java | 4 +- .../java/btools/routingapp/BRouterView.java | 12 +- .../java/btools/util/BitCoderContext.java | 4 +- .../java/btools/util/ByteArrayUnifier.java | 8 +- .../java/btools/util}/ByteDataReader.java | 170 +++++++++-------- .../java/btools/util}/ByteDataWriter.java | 178 +++++++++++------- .../src/main/java/btools/util/Crc32.java | 3 +- .../btools/util/DiffCoderDataInputStream.java | 49 +++++ .../util/DiffCoderDataOutputStream.java | 45 +++++ .../java/btools/util/BitCoderContextTest.java | 6 +- .../test/java/btools/util/ByteDataIOTest.java | 28 +++ 34 files changed, 742 insertions(+), 462 deletions(-) create mode 100644 brouter-expressions/src/main/java/btools/expressions/BExpressionMetaData.java rename {brouter-mapaccess/src/main/java/btools/mapaccess => brouter-util/src/main/java/btools/util}/ByteDataReader.java (67%) rename {brouter-mapaccess/src/main/java/btools/mapaccess => brouter-util/src/main/java/btools/util}/ByteDataWriter.java (64%) create mode 100644 brouter-util/src/main/java/btools/util/DiffCoderDataInputStream.java create mode 100644 brouter-util/src/main/java/btools/util/DiffCoderDataOutputStream.java create mode 100644 brouter-util/src/test/java/btools/util/ByteDataIOTest.java diff --git a/brouter-core/src/main/java/btools/router/RoutingContext.java b/brouter-core/src/main/java/btools/router/RoutingContext.java index ae776a0..1bf3ef5 100644 --- a/brouter-core/src/main/java/btools/router/RoutingContext.java +++ b/brouter-core/src/main/java/btools/router/RoutingContext.java @@ -50,13 +50,13 @@ public final class RoutingContext implements DistanceChecker public void readGlobalConfig( BExpressionContext expctxGlobal ) { - downhillcostdiv = (int)expctxGlobal.getVariableValue( "downhillcost" ); - downhillcutoff = (int)(expctxGlobal.getVariableValue( "downhillcutoff" )*10000); - uphillcostdiv = (int)expctxGlobal.getVariableValue( "uphillcost" ); - uphillcutoff = (int)(expctxGlobal.getVariableValue( "uphillcutoff" )*10000); + downhillcostdiv = (int)expctxGlobal.getVariableValue( "downhillcost", 0.f ); + downhillcutoff = (int)(expctxGlobal.getVariableValue( "downhillcutoff", 0.f )*10000); + uphillcostdiv = (int)expctxGlobal.getVariableValue( "uphillcost", 0.f ); + uphillcutoff = (int)(expctxGlobal.getVariableValue( "uphillcutoff", 0.f )*10000); if ( downhillcostdiv != 0 ) downhillcostdiv = 1000000/downhillcostdiv; if ( uphillcostdiv != 0 ) uphillcostdiv = 1000000/uphillcostdiv; - carMode = 0.f != expctxGlobal.getVariableValue( "validForCars" ); + carMode = 0.f != expctxGlobal.getVariableValue( "validForCars", 0.f ); pass1coefficient = expctxGlobal.getVariableValue( "pass1coefficient", 1.5f ); pass2coefficient = expctxGlobal.getVariableValue( "pass2coefficient", 0.f ); } diff --git a/brouter-core/src/main/java/btools/router/RoutingEngine.java b/brouter-core/src/main/java/btools/router/RoutingEngine.java index c271fff..a48dd75 100644 --- a/brouter-core/src/main/java/btools/router/RoutingEngine.java +++ b/brouter-core/src/main/java/btools/router/RoutingEngine.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.List; import btools.expressions.BExpressionContext; +import btools.expressions.BExpressionMetaData; import btools.mapaccess.NodesCache; import btools.mapaccess.OsmLink; import btools.mapaccess.OsmLinkHolder; @@ -70,18 +71,20 @@ public class RoutingEngine extends Thread profileDir = new File( profileBaseDir ); profileFile = new File( profileDir, rc.localFunction + ".brf" ) ; } - BExpressionContext expctxGlobal = new BExpressionContext( "global" ); - expctxGlobal.readMetaData( new File( profileDir, "lookups.dat" ) ); + + BExpressionMetaData meta = new BExpressionMetaData(); + + BExpressionContext expctxGlobal = new BExpressionContext( "global", meta ); + rc.expctxWay = new BExpressionContext( "way", meta ); + rc.expctxNode = new BExpressionContext( "node", 1024, meta ); + + meta.readMetaData( new File( profileDir, "lookups.dat" ) ); + expctxGlobal.parseFile( profileFile, null ); expctxGlobal.evaluate( new int[0] ); rc.readGlobalConfig(expctxGlobal); - rc.expctxWay = new BExpressionContext( "way", 4096 ); - rc.expctxWay.readMetaData( new File( profileDir, "lookups.dat" ) ); rc.expctxWay.parseFile( profileFile, "global" ); - - rc.expctxNode = new BExpressionContext( "node", 1024 ); - rc.expctxNode.readMetaData( new File( profileDir, "lookups.dat" ) ); rc.expctxNode.parseFile( profileFile, "global" ); } } @@ -372,7 +375,6 @@ public class RoutingEngine extends Thread if ( matchPath != null ) { track = mergeTrack( matchPath, nearbyTrack ); - isDirty = true; } maxRunningTime += System.currentTimeMillis() - startTime; // reset timeout... } @@ -432,7 +434,8 @@ public class RoutingEngine extends Thread private void resetCache() { nodesMap = new OsmNodesMap(); - nodesCache = new NodesCache(segmentDir, nodesMap, routingContext.expctxWay.lookupVersion,routingContext.expctxWay.lookupMinorVersion, routingContext.carMode, nodesCache ); + BExpressionContext ctx = routingContext.expctxWay; + nodesCache = new NodesCache(segmentDir, nodesMap, ctx.meta.lookupVersion, ctx.meta.lookupMinorVersion, ctx.meta.readVarLength, routingContext.carMode, nodesCache ); } private OsmNode getStartNode( long startId ) @@ -566,11 +569,13 @@ public class RoutingEngine extends Thread } } - private OsmTrack findTrack( String operationName, MatchedWaypoint startWp, MatchedWaypoint endWp, OsmTrack costCuttingTrack, OsmTrack refTrack, boolean reducedTimeoutWhenUnmatched ) + private OsmTrack findTrack( String operationName, MatchedWaypoint startWp, MatchedWaypoint endWp, OsmTrack costCuttingTrack, OsmTrack refTrack, boolean fastPartialRecalc ) { boolean verbose = guideTrack != null; int maxTotalCost = 1000000000; + int firstMatchCost = 1000000000; + int firstEstimate = 1000000000; logInfo( "findtrack with maxTotalCost=" + maxTotalCost + " airDistanceCostFactor=" + airDistanceCostFactor ); @@ -607,7 +612,7 @@ public class RoutingEngine extends Thread { if ( maxRunningTime > 0 ) { - long timeout = ( matchPath == null && reducedTimeoutWhenUnmatched ) ? maxRunningTime/3 : maxRunningTime; + long timeout = ( matchPath == null && fastPartialRecalc ) ? maxRunningTime/3 : maxRunningTime; if ( System.currentTimeMillis() - startTime > timeout ) { throw new IllegalArgumentException( operationName + " timeout after " + (timeout/1000) + " seconds" ); @@ -627,6 +632,11 @@ public class RoutingEngine extends Thread } maxAdjCostFromQueue = path.adjustedCost; + if ( matchPath != null && fastPartialRecalc && firstMatchCost < 500 && path.cost > 30L*firstMatchCost ) + { + throw new IllegalArgumentException( "early exit for a close recalc" ); + } + nodesVisited++; linksProcessed++; @@ -645,6 +655,32 @@ public class RoutingEngine extends Thread logInfo( "found track at cost " + path.cost + " nodesVisited = " + nodesVisited ); return compileTrack( path, verbose ); } + + // check for a match with the cost-cutting-track + if ( costCuttingTrack != null ) + { + OsmPathElement pe = costCuttingTrack.getLink( sourceNodeId, currentNodeId ); + if ( pe != null ) + { + // remember first match cost for fast termination of partial recalcs + int parentcost = path.originElement == null ? 0 : path.originElement.cost; + if ( parentcost < firstMatchCost ) firstMatchCost = parentcost; + + int costEstimate = path.cost + + path.elevationCorrection( routingContext ) + + ( costCuttingTrack.cost - pe.cost ); + if ( costEstimate <= maxTotalCost ) + { + if ( matchPath == null ) firstEstimate = costEstimate; + matchPath = new OsmPathElement( path ); + } + if ( costEstimate < maxTotalCost ) + { + logInfo( "maxcost " + maxTotalCost + " -> " + costEstimate ); + maxTotalCost = costEstimate; + } + } + } } // recheck cutoff before doing expensive stuff @@ -743,27 +779,6 @@ public class RoutingEngine extends Thread int airDistance = isFinalLink ? 0 : nextNode.calcDistance( endPos ); bestPath.setAirDistanceCostAdjustment( (int)( airDistance * airDistanceCostFactor ) ); - // check for a match with the cost-cutting-track - if ( costCuttingTrack != null ) - { - OsmPathElement pe = costCuttingTrack.getLink( currentNodeId, targetNodeId ); - if ( pe != null ) - { - int costEstimate = bestPath.cost - + bestPath.elevationCorrection( routingContext ) - + ( costCuttingTrack.cost - pe.cost ); - if ( costEstimate <= maxTotalCost ) - { - matchPath = new OsmPathElement( bestPath ); - } - if ( costEstimate < maxTotalCost ) - { - logInfo( "maxcost " + maxTotalCost + " -> " + costEstimate + " airDistance=" + airDistance ); - maxTotalCost = costEstimate; - } - } - } - if ( isFinalLink || bestPath.cost + airDistance <= maxTotalCost + 10 ) { // add only if this may beat an existing path for that link diff --git a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java index b67584b..f7a5026 100644 --- a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java +++ b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java @@ -23,11 +23,8 @@ import btools.util.Crc32; public final class BExpressionContext { - private static final String CONTEXT_TAG = "---context:"; - private static final String VERSION_TAG = "---lookupversion:"; - private static final String MINOR_VERSION_TAG = "---minorversion:"; - private static final String VARLENGTH_TAG = "---readvarlength"; - + private static final String CONTEXT_TAG = "---context:"; + private String context; private boolean _inOurContext = false; private BufferedReader _br = null; @@ -55,7 +52,6 @@ public final class BExpressionContext private byte[][] _arrayBitmap; private int currentHashBucket = -1; private byte[] currentByteArray = null; - private boolean currentInversion = false; public List expressionList; @@ -79,13 +75,12 @@ public final class BExpressionContext private int linenr; - public short lookupVersion = -1; - public short lookupMinorVersion = -1; - public boolean readVarLength = false; + public BExpressionMetaData meta; + private boolean lookupDataValid = false; - public BExpressionContext( String context ) + public BExpressionContext( String context, BExpressionMetaData meta ) { - this( context, 4096 ); + this( context, 4096, meta ); } /** @@ -94,9 +89,15 @@ public final class BExpressionContext * @param context global, way or node - context of that instance * @param hashSize size of hashmap for result caching */ - public BExpressionContext( String context, int hashSize ) + public BExpressionContext( String context, int hashSize, BExpressionMetaData meta ) { - this.context = context; + this.context = context; + this.meta = meta; + + meta.registerListener(context, this ); + + if ( Boolean.getBoolean( "disableExpressionCache" ) ) hashSize = 1; + _arrayBitmap = new byte[hashSize][]; _arrayCostfactor = new float[hashSize]; @@ -105,18 +106,18 @@ public final class BExpressionContext _arrayNodeAccessGranted = new float[hashSize]; } - /** * encode internal lookup data to a byte array */ public byte[] encode() { + if ( !lookupDataValid ) throw new IllegalArgumentException( "internal error: encoding undefined data?" ); return encode( lookupData ); } public byte[] encode( int[] ld ) { - if ( !readVarLength ) return encodeFix( ld ); + if ( !meta.readVarLength ) return encodeFix( ld ); // start with first bit hardwired ("reversedirection") BitCoderContext ctx = new BitCoderContext( abBuf ); @@ -134,16 +135,16 @@ public final class BExpressionContext skippedTags++; continue; } - ctx.encodeDistance( skippedTags+1 ); + ctx.encodeVarBits( skippedTags+1 ); nonNullTags++; skippedTags = 0; // 0 excluded already, 1 (=unknown) we rotate up to 8 // to have the good code space for the popular values int dd = d < 2 ? 7 : ( d < 9 ? d - 2 : d - 1); - ctx.encodeDistance( dd ); + ctx.encodeVarBits( dd ); } - ctx.encodeDistance( 0 ); + ctx.encodeVarBits( 0 ); if ( nonNullTags == 0) return null; @@ -200,6 +201,7 @@ public final class BExpressionContext public void decode( byte[] ab ) { decode( lookupData, ab ); + lookupDataValid = true; } /** @@ -207,7 +209,7 @@ public final class BExpressionContext */ public void decode( int[] ld, byte[] ab ) { - if ( !readVarLength ) { decodeFix( ld, ab ); return; } + if ( !meta.readVarLength ) { decodeFix( ld, ab ); return; } BitCoderContext ctx = new BitCoderContext(ab); @@ -218,14 +220,14 @@ public final class BExpressionContext int inum = 1; for(;;) { - int delta = ctx.decodeDistance(); + int delta = ctx.decodeVarBits(); if ( delta == 0) break; if ( inum + delta > ld.length ) break; // higher minor version is o.k. while ( delta-- > 1 ) ld[inum++] = 0; // see encoder for value rotation - int dd = ctx.decodeDistance(); + int dd = ctx.decodeVarBits(); int d = dd == 7 ? 1 : ( dd < 7 ? dd + 2 : dd + 1); if ( d >= lookupValues.get(inum).length ) d = 1; // map out-of-range to unknown ld[inum++] = d; @@ -265,7 +267,7 @@ public final class BExpressionContext public String getCsvDescription( boolean inverseDirection, byte[] ab ) { - int inverseBitByteIndex = readVarLength ? 0 : 7; + int inverseBitByteIndex = meta.readVarLength ? 0 : 7; int abLen = ab.length; byte[] ab_copy = new byte[abLen]; System.arraycopy( ab, 0, ab_copy, 0 , abLen ); @@ -275,8 +277,10 @@ public final class BExpressionContext decode( lookupData, ab_copy ); for( int inum = 0; inum < lookupValues.size(); inum++ ) // loop over lookup names { - BExpressionLookupValue[] va = lookupValues.get(inum); - sb.append( '\t' ).append( va[lookupData[inum]].toString() ); + int idx = meta.readVarLength ? (inum+1)%lookupValues.size() : inum; // reversebit at the end.. + + BExpressionLookupValue[] va = lookupValues.get(idx); + sb.append( '\t' ).append( va[lookupData[idx]].toString() ); } return sb.toString(); } @@ -284,9 +288,10 @@ public final class BExpressionContext public String getCsvHeader() { StringBuilder sb = new StringBuilder( 200 ); - for( String name: lookupNames ) + for( int inum = 0; inum < lookupNames.size(); inum++ ) // loop over lookup names { - sb.append( '\t' ).append( name ); + int idx = meta.readVarLength ? (inum+1)%lookupValues.size() : inum; // reversebit at the end.. + sb.append( '\t' ).append( lookupNames.get(idx) ); } return sb.toString(); } @@ -307,42 +312,11 @@ public final class BExpressionContext return sb.toString(); } - public void readMetaData( File lookupsFile ) + private int parsedLines = 0; + private boolean fixTagsWritten = false; + + public void parseMetaLine( String line ) { - try - { - BufferedReader br = new BufferedReader( new FileReader( lookupsFile ) ); - - int parsedLines = 0; - boolean ourContext = false; - boolean fixTagsWritten = false; - for(;;) - { - String line = br.readLine(); - if ( line == null ) break; - line = line.trim(); - if ( line.length() == 0 || line.startsWith( "#" ) ) continue; - if ( line.startsWith( CONTEXT_TAG ) ) - { - ourContext = line.substring( CONTEXT_TAG.length() ).equals( context ); - continue; - } - if ( line.startsWith( VERSION_TAG ) ) - { - lookupVersion = Short.parseShort( line.substring( VERSION_TAG.length() ) ); - continue; - } - if ( line.startsWith( MINOR_VERSION_TAG ) ) - { - lookupMinorVersion = Short.parseShort( line.substring( MINOR_VERSION_TAG.length() ) ); - continue; - } - if ( line.startsWith( VARLENGTH_TAG ) ) - { - readVarLength = true; - continue; - } - if ( !ourContext ) continue; parsedLines++; StringTokenizer tk = new StringTokenizer( line, " " ); String name = tk.nextToken(); @@ -350,7 +324,7 @@ public final class BExpressionContext int idx = name.indexOf( ';' ); if ( idx >= 0 ) name = name.substring( 0, idx ); - if ( readVarLength ) + if ( meta.readVarLength ) { if ( !fixTagsWritten ) { @@ -358,28 +332,24 @@ public final class BExpressionContext if ( "way".equals( context ) ) addLookupValue( "reversedirection", "yes", null ); else if ( "node".equals( context ) ) addLookupValue( "nodeaccessgranted", "yes", null ); } - if ( "reversedirection".equals( name ) ) continue; // this is hardcoded - if ( "nodeaccessgranted".equals( name ) ) continue; // this is hardcoded + if ( "reversedirection".equals( name ) ) return; // this is hardcoded + if ( "nodeaccessgranted".equals( name ) ) return; // this is hardcoded } BExpressionLookupValue newValue = addLookupValue( name, value, null ); // add aliases while( newValue != null && tk.hasMoreTokens() ) newValue.addAlias( tk.nextToken() ); - } - br.close(); + } + + public void finishMetaParsing() + { if ( parsedLines == 0 && !"global".equals(context) ) { - throw new IllegalArgumentException( lookupsFile.getAbsolutePath() - + " does not contain data for context " + context + " (old version?)" ); + throw new IllegalArgumentException( "lookup table does not contain data for context " + context + " (old version?)" ); } // post-process metadata: lookupDataFrozen = true; - } - catch( Exception e ) - { - throw new RuntimeException( e ); - } } public void evaluate( int[] lookupData2 ) @@ -400,7 +370,9 @@ public final class BExpressionContext */ public boolean evaluate( boolean inverseDirection, byte[] ab, BExpressionReceiver receiver ) { - int inverseBitByteIndex = readVarLength ? 0 : 7; + lookupDataValid = false; // this is an assertion for a nasty pifall + + int inverseBitByteIndex = meta.readVarLength ? 0 : 7; int abLen = ab.length; boolean equalsCurrent = currentHashBucket >= 0 && abLen == currentByteArray.length; @@ -685,18 +657,12 @@ public final class BExpressionContext return num == null ? defaultValue : getVariableValue( num.intValue() ); } - public float getVariableValue( String name ) - { - Integer num = variableNumbers.get( name ); - return num == null ? 0.f : getVariableValue( num.intValue() ); - } - - public float getVariableValue( int variableIdx ) + float getVariableValue( int variableIdx ) { return variableData[variableIdx]; } - public int getVariableIdx( String name, boolean create ) + int getVariableIdx( String name, boolean create ) { Integer num = variableNumbers.get( name ); if ( num == null ) @@ -714,12 +680,12 @@ public final class BExpressionContext return num.intValue(); } - public int getMinWriteIdx() + int getMinWriteIdx() { return minWriteIdx; } - public float getLookupMatch( int nameIdx, int valueIdx ) + float getLookupMatch( int nameIdx, int valueIdx ) { return lookupData[nameIdx] == valueIdx ? 1.0f : 0.0f; } @@ -730,7 +696,7 @@ public final class BExpressionContext return num == null ? -1 : num.intValue(); } - public int getLookupValueIdx( int nameIdx, String value ) + int getLookupValueIdx( int nameIdx, String value ) { BExpressionLookupValue[] values = lookupValues.get( nameIdx ); for( int i=0; i< values.length; i++ ) @@ -741,7 +707,7 @@ public final class BExpressionContext } - public String parseToken() throws Exception + String parseToken() throws Exception { for(;;) { @@ -790,13 +756,13 @@ public final class BExpressionContext } } - public float assign( int variableIdx, float value ) + float assign( int variableIdx, float value ) { variableData[variableIdx] = value; return value; } - public void expressionWarning( String message ) + void expressionWarning( String message ) { _arrayBitmap[currentHashBucket] = null; // no caching if warnings if ( _receiver != null ) _receiver.expressionWarning( context, message ); diff --git a/brouter-expressions/src/main/java/btools/expressions/BExpressionMetaData.java b/brouter-expressions/src/main/java/btools/expressions/BExpressionMetaData.java new file mode 100644 index 0000000..d50c498 --- /dev/null +++ b/brouter-expressions/src/main/java/btools/expressions/BExpressionMetaData.java @@ -0,0 +1,91 @@ +// context for simple expression +// context means: +// - the local variables +// - the local variable names +// - the lookup-input variables + +package btools.expressions; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.TreeMap; + +import btools.util.BitCoderContext; +import btools.util.Crc32; + + +public final class BExpressionMetaData +{ + private static final String CONTEXT_TAG = "---context:"; + private static final String VERSION_TAG = "---lookupversion:"; + private static final String MINOR_VERSION_TAG = "---minorversion:"; + private static final String VARLENGTH_TAG = "---readvarlength"; + + public short lookupVersion = -1; + public short lookupMinorVersion = -1; + public boolean readVarLength = false; + + private HashMap listeners = new HashMap(); + + public void registerListener( String context, BExpressionContext ctx ) + { + listeners.put( context, ctx ); + } + + public void readMetaData( File lookupsFile ) + { + try + { + BufferedReader br = new BufferedReader( new FileReader( lookupsFile ) ); + + BExpressionContext ctx = null; + + for(;;) + { + String line = br.readLine(); + if ( line == null ) break; + line = line.trim(); + if ( line.length() == 0 || line.startsWith( "#" ) ) continue; + if ( line.startsWith( CONTEXT_TAG ) ) + { + ctx = listeners.get( line.substring( CONTEXT_TAG.length() ) ); + continue; + } + if ( line.startsWith( VERSION_TAG ) ) + { + lookupVersion = Short.parseShort( line.substring( VERSION_TAG.length() ) ); + continue; + } + if ( line.startsWith( MINOR_VERSION_TAG ) ) + { + lookupMinorVersion = Short.parseShort( line.substring( MINOR_VERSION_TAG.length() ) ); + continue; + } + if ( line.startsWith( VARLENGTH_TAG ) ) + { + readVarLength = true; + continue; + } + if ( ctx != null ) ctx.parseMetaLine( line ); + } + br.close(); + + for( BExpressionContext c : listeners.values() ) + { + c.finishMetaParsing(); + } + + } + catch( Exception e ) + { + throw new RuntimeException( e ); + } + } +} diff --git a/brouter-expressions/src/test/java/btools/expressions/EncodeDecodeTest.java b/brouter-expressions/src/test/java/btools/expressions/EncodeDecodeTest.java index 16e919a..aeda4e8 100644 --- a/brouter-expressions/src/test/java/btools/expressions/EncodeDecodeTest.java +++ b/brouter-expressions/src/test/java/btools/expressions/EncodeDecodeTest.java @@ -18,8 +18,9 @@ public class EncodeDecodeTest File lookupFile = new File( profileDir, "lookups.dat" ); // read lookup.dat + trekking.brf - BExpressionContext expctxWay = new BExpressionContext("way"); - expctxWay.readMetaData( lookupFile ); + BExpressionMetaData meta = new BExpressionMetaData(); + BExpressionContext expctxWay = new BExpressionContext("way", 4096, meta ); + meta.readMetaData( lookupFile ); expctxWay.parseFile( new File( profileDir, "trekking.brf" ), "global" ); String[] tags = { "highway=residential", "oneway=yes", "reversedirection=yes" }; diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/MapCreatorBase.java b/brouter-map-creator/src/main/java/btools/mapcreator/MapCreatorBase.java index 7040004..7255970 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/MapCreatorBase.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/MapCreatorBase.java @@ -15,9 +15,11 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.HashMap; +import btools.util.DiffCoderDataOutputStream; + public abstract class MapCreatorBase implements WayListener, NodeListener, RelationListener { - private DataOutputStream[] tileOutStreams; + private DiffCoderDataOutputStream[] tileOutStreams; protected File outTileDir; protected HashMap tags; @@ -102,16 +104,16 @@ public abstract class MapCreatorBase implements WayListener, NodeListener, Relat return new DataInputStream( new BufferedInputStream ( new FileInputStream( inFile ) ) ); } - protected DataOutputStream createOutStream( File outFile ) throws IOException + protected DiffCoderDataOutputStream createOutStream( File outFile ) throws IOException { - return new DataOutputStream( new BufferedOutputStream( new FileOutputStream( outFile ) ) ); + return new DiffCoderDataOutputStream( new BufferedOutputStream( new FileOutputStream( outFile ) ) ); } - protected DataOutputStream getOutStreamForTile( int tileIndex ) throws Exception + protected DiffCoderDataOutputStream getOutStreamForTile( int tileIndex ) throws Exception { if ( tileOutStreams == null ) { - tileOutStreams = new DataOutputStream[64]; + tileOutStreams = new DiffCoderDataOutputStream[64]; } if ( tileOutStreams[tileIndex] == null ) diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/NodeData.java b/brouter-map-creator/src/main/java/btools/mapcreator/NodeData.java index b8937b6..515ac16 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/NodeData.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/NodeData.java @@ -1,7 +1,7 @@ package btools.mapcreator; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import btools.util.DiffCoderDataInputStream; +import btools.util.DiffCoderDataOutputStream; /** * Container for node data on the preprocessor level @@ -23,21 +23,21 @@ public class NodeData extends MapCreatorBase ilon = (int)( ( lon + 180. )*1000000. + 0.5); } - public NodeData( DataInputStream dis ) throws Exception + public NodeData( DiffCoderDataInputStream dis ) throws Exception { - nid = readId( dis ); - ilon = dis.readInt(); - ilat = dis.readInt(); + nid = dis.readDiffed( 0 ); + ilon = (int)dis.readDiffed( 1 ); + ilat = (int)dis.readDiffed( 2 ); int mode = dis.readByte(); if ( ( mode & 1 ) != 0 ) { int dlen = dis.readByte(); description = new byte[dlen]; dis.readFully( description ); } if ( ( mode & 2 ) != 0 ) selev = dis.readShort(); } - public void writeTo( DataOutputStream dos ) throws Exception + public void writeTo( DiffCoderDataOutputStream dos ) throws Exception { - writeId( dos, nid ); - dos.writeInt( ilon ); - dos.writeInt( ilat ); + dos.writeDiffed( nid, 0 ); + dos.writeDiffed( ilon, 1 ); + dos.writeDiffed( ilat, 2 ); int mode = ( description == null ? 0 : 1 ) | ( selev == Short.MIN_VALUE ? 0 : 2 ); dos.writeByte( (byte)mode ); if ( ( mode & 1 ) != 0 ) { dos.writeByte( description.length ); dos.write( description ); } diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/NodeFilter.java b/brouter-map-creator/src/main/java/btools/mapcreator/NodeFilter.java index c113c59..cf85c82 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/NodeFilter.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/NodeFilter.java @@ -1,11 +1,11 @@ package btools.mapcreator; import java.io.BufferedOutputStream; -import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import btools.util.DenseLongMap; +import btools.util.DiffCoderDataOutputStream; import btools.util.TinyDenseLongMap; /** @@ -17,7 +17,7 @@ import btools.util.TinyDenseLongMap; */ public class NodeFilter extends MapCreatorBase { - private DataOutputStream nodesOutStream; + private DiffCoderDataOutputStream nodesOutStream; private File nodeTilesOut; protected DenseLongMap nodebitmap; @@ -61,7 +61,7 @@ public class NodeFilter extends MapCreatorBase String filename = nodefile.getName(); filename = filename.substring( 0, filename.length() - 3 ) + "tlf"; File outfile = new File( nodeTilesOut, filename ); - nodesOutStream = new DataOutputStream( new BufferedOutputStream ( new FileOutputStream( outfile ) ) ); + nodesOutStream = new DiffCoderDataOutputStream( new BufferedOutputStream ( new FileOutputStream( outfile ) ) ); } @Override diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/NodeIterator.java b/brouter-map-creator/src/main/java/btools/mapcreator/NodeIterator.java index d1f6115..c523f92 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/NodeIterator.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/NodeIterator.java @@ -1,11 +1,12 @@ package btools.mapcreator; import java.io.BufferedInputStream; -import java.io.DataInputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; +import btools.util.DiffCoderDataInputStream; + /** * Iterate over a singe nodefile or a directory * of nodetiles and feed the nodes to the callback listener @@ -48,7 +49,7 @@ public class NodeIterator extends MapCreatorBase listener.nodeFileStart( nodefile ); - DataInputStream di = new DataInputStream( new BufferedInputStream ( new FileInputStream( nodefile ) ) ); + DiffCoderDataInputStream di = new DiffCoderDataInputStream( new BufferedInputStream ( new FileInputStream( nodefile ) ) ); try { for(;;) diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/OsmCutter.java b/brouter-map-creator/src/main/java/btools/mapcreator/OsmCutter.java index 0d2085e..0769a7b 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/OsmCutter.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/OsmCutter.java @@ -13,6 +13,7 @@ import java.io.File; import java.io.FileOutputStream; import btools.expressions.BExpressionContext; +import btools.expressions.BExpressionMetaData; public class OsmCutter extends MapCreatorBase { @@ -47,7 +48,7 @@ public class OsmCutter extends MapCreatorBase private BExpressionContext _expctxNode; private BExpressionContext _expctxWayStat; - private BExpressionContext _expctxNodeStat; + // private BExpressionContext _expctxNodeStat; public void process (File lookupFile, File outTileDir, File wayFile, File relFile, File mapFile) throws Exception { @@ -56,13 +57,13 @@ public class OsmCutter extends MapCreatorBase throw new IllegalArgumentException( "lookup-file: " + lookupFile + " does not exist" ); } - _expctxWay = new BExpressionContext("way"); - _expctxWay.readMetaData( lookupFile ); -// _expctxWayStat = new BExpressionContext("way"); + BExpressionMetaData meta = new BExpressionMetaData(); - _expctxNode = new BExpressionContext("node"); - _expctxNode.readMetaData( lookupFile ); -// _expctxNodeStat = new BExpressionContext("node"); + _expctxWay = new BExpressionContext("way", meta ); + _expctxNode = new BExpressionContext("node", meta ); + meta.readMetaData( lookupFile ); +// _expctxWayStat = new BExpressionContext("way", null ); +// _expctxNodeStat = new BExpressionContext("node", null ); this.outTileDir = outTileDir; if ( !outTileDir.isDirectory() ) throw new RuntimeException( "out tile directory " + outTileDir + " does not exist" ); @@ -122,8 +123,7 @@ public class OsmCutter extends MapCreatorBase int tileIndex = getTileIndex( n.ilon, n.ilat ); if ( tileIndex >= 0 ) { - DataOutputStream dos = getOutStreamForTile( tileIndex ); - n.writeTo( dos ); + n.writeTo( getOutStreamForTile( tileIndex ) ); } } 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 1e45f11..0d5fb69 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java @@ -9,10 +9,14 @@ import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; +import sun.security.pkcs.SigningCertificateInfo; + +import btools.util.ByteDataWriter; + public class OsmNodeP implements Comparable { - public static final int EXTERNAL_BITMASK = 0x80; - public static final int VARIABLEDESC_BITMASK = 0x40; + public static final int SIGNLON_BITMASK = 0x80; + public static final int SIGNLAT_BITMASK = 0x40; public static final int TRANSFERNODE_BITMASK = 0x20; public static final int WRITEDESC_BITMASK = 0x10; public static final int SKIPDETAILS_BITMASK = 0x08; @@ -42,10 +46,12 @@ public class OsmNodeP implements Comparable public boolean isBorder = false; - public final static int BRIDGE_AND_BIT = 1; - public final static int TUNNEL_AND_BIT = 2; - public byte wayAndBits = -1; // use for bridge/tunnel logic - + public final static int NO_BRIDGE_BIT = 1; + public final static int NO_TUNNEL_BIT = 2; + public final static int LCN_BIT = 4; + public final static int CR_BIT = 8; + + public byte wayBits = 0; // interface OsmPos public int getILat() @@ -61,7 +67,7 @@ public class OsmNodeP implements Comparable public short getSElev() { // if all bridge or all tunnel, elevation=no-data - return (wayAndBits & ( BRIDGE_AND_BIT | TUNNEL_AND_BIT ) ) == 0 ? selev : Short.MIN_VALUE; + return ( wayBits & NO_BRIDGE_BIT ) == 0 || ( wayBits & NO_TUNNEL_BIT ) == 0 ? Short.MIN_VALUE : selev; } public double getElev() @@ -82,22 +88,23 @@ public class OsmNodeP implements Comparable return null; } - public void writeNodeData( DataOutputStream os, boolean writeVarLength ) throws IOException + public void writeNodeData( ByteDataWriter os, boolean writeVarLength, byte[] abBuf ) throws IOException { int lonIdx = ilon/62500; int latIdx = ilat/62500; // buffer the body to first calc size - ByteArrayOutputStream bos = new ByteArrayOutputStream( ); - DataOutputStream os2 = new DataOutputStream( bos ); - + ByteDataWriter os2 = new ByteDataWriter( abBuf ); os2.writeShort( getSElev() ); - + // hack: write node-desc as link tag (copy cycleway-bits) byte[] nodeDescription = getNodeDecsription(); for( OsmLinkP link0 = firstlink; link0 != null; link0 = link0.next ) { + int ilonref = ilon; + int ilatref = ilat; + OsmLinkP link = link0; OsmNodeP origin = this; int skipDetailBit = link0.counterLinkWritten() ? SKIPDETAILS_BITMASK : 0; @@ -160,32 +167,24 @@ public class OsmNodeP implements Comparable } } - int targetLonIdx = target.ilon/62500; - int targetLatIdx = target.ilat/62500; int bm = tranferbit | writedescbit | nodedescbit | skipDetailBit; - if ( writeVarLength ) bm |= VARIABLEDESC_BITMASK; + int dlon = target.ilon - ilonref; + int dlat = target.ilat - ilatref; + ilonref = target.ilon; + ilatref = target.ilat; + if ( dlon < 0 ) { bm |= SIGNLON_BITMASK; dlon = - dlon; } + if ( dlat < 0 ) { bm |= SIGNLAT_BITMASK; dlat = - dlat; } + os2.writeByte( bm ); + + int blon = os2.writeVarLengthUnsigned( dlon ); + int blat = os2.writeVarLengthUnsigned( dlat ); - if ( targetLonIdx == lonIdx && targetLatIdx == latIdx ) - { - // reduced position for internal target - os2.writeByte( bm ); - os2.writeShort( (short)(target.ilon - lonIdx*62500 - 31250) ); - os2.writeShort( (short)(target.ilat - latIdx*62500 - 31250) ); - } - else - { - // full position for external target - os2.writeByte( bm | EXTERNAL_BITMASK ); - os2.writeInt( target.ilon ); - os2.writeInt( target.ilat ); - } if ( writedescbit != 0 ) { // write the way description, code direction into the first bit - int len = lastDescription.length; - if ( writeVarLength ) os2.writeByte( len ); - os2.write( lastDescription, 0, len ); + if ( writeVarLength ) os2.writeByte( lastDescription.length ); + os2.write( lastDescription ); } if ( nodedescbit != 0 ) { @@ -199,7 +198,7 @@ public class OsmNodeP implements Comparable target.markLinkWritten( origin ); break; } - os2.writeShort( target.getSElev() ); + os2.writeVarLengthSigned( target.getSElev() -getSElev() ); // next link is the one (of two), does does'nt point back for( link = target.firstlink; link != null; link = link.next ) { @@ -211,12 +210,15 @@ public class OsmNodeP implements Comparable } // calculate the body size - int bodySize = bos.size(); + int bodySize = os2.size(); + + os.ensureCapacity( bodySize + 8 ); os.writeShort( (short)(ilon - lonIdx*62500 - 31250) ); os.writeShort( (short)(ilat - latIdx*62500 - 31250) ); - os.writeInt( bodySize ); - bos.writeTo( os ); + + os.writeVarLengthUnsigned( bodySize ); + os.write( abBuf, 0, bodySize ); } public String toString2() diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodePT.java b/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodePT.java index 989c4d4..f8eda68 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodePT.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodePT.java @@ -10,8 +10,6 @@ public class OsmNodePT extends OsmNodeP { public byte[] descriptionBits; - public byte wayOrBits = 0; // used to propagate bike networks to nodes - public OsmNodePT() { } @@ -25,7 +23,6 @@ public class OsmNodePT extends OsmNodeP public final byte[] getNodeDecsription() { return descriptionBits; - // return descriptionBits | (long)( (wayOrBits & 6) >> 1 ); TODO !!!!!!!!!!1 } @Override diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/PosUnifier.java b/brouter-map-creator/src/main/java/btools/mapcreator/PosUnifier.java index 0aa79df..205a5b9 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/PosUnifier.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/PosUnifier.java @@ -7,6 +7,7 @@ import java.io.File; import java.util.HashMap; import btools.util.CompactLongSet; +import btools.util.DiffCoderDataOutputStream; import btools.util.FrozenLongSet; /** @@ -21,8 +22,8 @@ import btools.util.FrozenLongSet; */ public class PosUnifier extends MapCreatorBase { - private DataOutputStream nodesOutStream; - private DataOutputStream borderNodesOut; + private DiffCoderDataOutputStream nodesOutStream; + private DiffCoderDataOutputStream borderNodesOut; private File nodeTilesOut; private CompactLongSet positionSet; diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/RelationMerger.java b/brouter-map-creator/src/main/java/btools/mapcreator/RelationMerger.java index 601d195..39557b9 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/RelationMerger.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/RelationMerger.java @@ -7,6 +7,7 @@ import java.io.File; import java.util.HashMap; import btools.expressions.BExpressionContext; +import btools.expressions.BExpressionMetaData; import btools.util.CompactLongSet; import btools.util.FrozenLongSet; @@ -29,7 +30,7 @@ public class RelationMerger extends MapCreatorBase public static void main(String[] args) throws Exception { - System.out.println("*** RelationMerger: merge relation bits into ways" ); + System.out.println("*** RelationMerger: merge relations into ways" ); if (args.length != 6) { System.out.println("usage: java RelationMerger " ); @@ -42,11 +43,15 @@ public class RelationMerger extends MapCreatorBase public void process( File wayFileIn, File wayFileOut, File relationFileIn, File lookupFile, File reportProfile, File checkProfile ) throws Exception { // read lookup + profile for relation access-check - expctxReport = new BExpressionContext("way"); - expctxReport.readMetaData( lookupFile ); + BExpressionMetaData metaReport = new BExpressionMetaData(); + expctxReport = new BExpressionContext("way", metaReport ); + metaReport.readMetaData( lookupFile ); + + BExpressionMetaData metaCheck = new BExpressionMetaData(); + expctxCheck = new BExpressionContext("way", metaCheck ); + metaCheck.readMetaData( lookupFile ); + expctxReport.parseFile( reportProfile, "global" ); - expctxCheck = new BExpressionContext("way"); - expctxCheck.readMetaData( lookupFile ); expctxCheck.parseFile( checkProfile, "global" ); // expctxStat = new BExpressionContext("way"); @@ -63,6 +68,7 @@ public class RelationMerger extends MapCreatorBase String network = dis.readUTF(); String tagname = "route_" + route + "_" + network; + CompactLongSet routeset = null; if ( expctxCheck.getLookupNameIdx(tagname) >= 0 ) { @@ -127,6 +133,7 @@ public class RelationMerger extends MapCreatorBase if ( ok ) { + expctxReport.decode( data.description ); for( String tagname : routesets.keySet() ) { CompactLongSet routeset = routesets.get( tagname ); 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 317ec31..2fdb6d4 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java @@ -8,7 +8,9 @@ import java.util.Collections; import java.util.List; import btools.expressions.BExpressionContext; +import btools.expressions.BExpressionMetaData; import btools.util.ByteArrayUnifier; +import btools.util.ByteDataWriter; import btools.util.CompactLongMap; import btools.util.CompactLongSet; import btools.util.Crc32; @@ -45,6 +47,7 @@ public class WayLinker extends MapCreatorBase private long creationTimeStamp; private BExpressionContext expctxWay; + private BExpressionContext expctxNode; private ByteArrayUnifier abUnifier; @@ -77,13 +80,19 @@ public class WayLinker extends MapCreatorBase this.borderFileIn = borderFileIn; this.dataTilesSuffix = dataTilesSuffix; + BExpressionMetaData meta = new BExpressionMetaData(); + // read lookup + profile for lookup-version + access-filter - expctxWay = new BExpressionContext("way"); - expctxWay.readMetaData( lookupFile ); - lookupVersion = expctxWay.lookupVersion; - lookupMinorVersion = expctxWay.lookupMinorVersion; - writeVarLength = expctxWay.readVarLength; + expctxWay = new BExpressionContext("way", meta); + expctxNode = new BExpressionContext("node", meta); + meta.readMetaData( lookupFile ); + + lookupVersion = meta.lookupVersion; + lookupMinorVersion = meta.lookupMinorVersion; + writeVarLength = meta.readVarLength; + expctxWay.parseFile( profileFile, "global" ); + expctxNode.parseFile( profileFile, "global" ); creationTimeStamp = System.currentTimeMillis(); @@ -158,11 +167,11 @@ public class WayLinker extends MapCreatorBase ok |= expctxWay.getCostfactor() < 10000.; if ( !ok ) return; - byte bridgeTunnel = 0; + byte wayBits = 0; expctxWay.decode( description ); - if ( expctxWay.getBooleanLookupValue( "bridge" ) ) bridgeTunnel |= OsmNodeP.BRIDGE_AND_BIT; - if ( expctxWay.getBooleanLookupValue( "tunnel" ) ) bridgeTunnel |= OsmNodeP.TUNNEL_AND_BIT; - + if ( !expctxWay.getBooleanLookupValue( "bridge" ) ) wayBits |= OsmNodeP.NO_BRIDGE_BIT; + if ( !expctxWay.getBooleanLookupValue( "tunnel" ) ) wayBits |= OsmNodeP.NO_TUNNEL_BIT; + OsmNodeP n1 = null; OsmNodeP n2 = null; for (int i=0; i size / 2 ) // garbage collection @@ -252,53 +268,6 @@ final class MicroCache return positions; } - public int readInt() - { - int i3 = ab[aboffset++]& 0xff; - int i2 = ab[aboffset++]& 0xff; - int i1 = ab[aboffset++]& 0xff; - int i0 = ab[aboffset++]& 0xff; - return (i3 << 24) + (i2 << 16) + (i1 << 8) + i0; - } - - public long readLong() - { - long i7 = ab[aboffset++]& 0xff; - long i6 = ab[aboffset++]& 0xff; - long i5 = ab[aboffset++]& 0xff; - long i4 = ab[aboffset++]& 0xff; - long i3 = ab[aboffset++]& 0xff; - long i2 = ab[aboffset++]& 0xff; - long i1 = ab[aboffset++]& 0xff; - long i0 = ab[aboffset++]& 0xff; - return (i7 << 56) + (i6 << 48) + (i5 << 40) + (i4 << 32) + (i3 << 24) + (i2 << 16) + (i1 << 8) + i0; - } - - public boolean readBoolean() - { - int i0 = ab[aboffset++]& 0xff; - return i0 != 0; - } - - public byte readByte() - { - int i0 = ab[aboffset++] & 0xff; - return (byte)(i0); - } - - public short readShort() - { - int i1 = ab[aboffset++] & 0xff; - int i0 = ab[aboffset++] & 0xff; - return (short)( (i1 << 8) | i0); - } - - public void readFully( byte[] ta ) - { - System.arraycopy( ab, aboffset, ta, 0, ta.length ); - aboffset += ta.length; - } - public boolean hasMoreData() { return aboffset < aboffsetEnd; diff --git a/brouter-mapaccess/src/main/java/btools/mapaccess/NodesCache.java b/brouter-mapaccess/src/main/java/btools/mapaccess/NodesCache.java index 95da78d..612ca1f 100644 --- a/brouter-mapaccess/src/main/java/btools/mapaccess/NodesCache.java +++ b/brouter-mapaccess/src/main/java/btools/mapaccess/NodesCache.java @@ -17,6 +17,7 @@ public final class NodesCache private OsmNodesMap nodesMap; private int lookupVersion; private int lookupMinorVersion; + private boolean readVarLength; private boolean carMode; private String currentFileName; @@ -33,12 +34,13 @@ public final class NodesCache private long cacheSum = 0; private boolean garbageCollectionEnabled = false; - public NodesCache( String segmentDir, OsmNodesMap nodesMap, int lookupVersion, int lookupMinorVersion, boolean carMode, NodesCache oldCache ) + public NodesCache( String segmentDir, OsmNodesMap nodesMap, int lookupVersion, int minorVersion, boolean varLen, boolean carMode, NodesCache oldCache ) { this.segmentDir = segmentDir; this.nodesMap = nodesMap; this.lookupVersion = lookupVersion; - this.lookupMinorVersion = lookupMinorVersion; + this.lookupMinorVersion = minorVersion; + this.readVarLength = varLen; this.carMode = carMode; if ( oldCache != null ) @@ -145,7 +147,7 @@ public final class NodesCache checkEnableCacheCleaning(); - segment = new MicroCache( osmf, lonIdx80, latIdx80, iobuffer ); + segment = new MicroCache( osmf, lonIdx80, latIdx80, iobuffer, readVarLength ); cacheSum += segment.getDataSize(); osmf.microCaches[subIdx] = segment; segmentList.add( segment ); diff --git a/brouter-mapaccess/src/main/java/btools/mapaccess/OsmFile.java b/brouter-mapaccess/src/main/java/btools/mapaccess/OsmFile.java index 9868119..22726ff 100644 --- a/brouter-mapaccess/src/main/java/btools/mapaccess/OsmFile.java +++ b/brouter-mapaccess/src/main/java/btools/mapaccess/OsmFile.java @@ -7,6 +7,8 @@ package btools.mapaccess; import java.io.IOException; import java.io.RandomAccessFile; + +import btools.util.ByteDataReader; import btools.util.Crc32; final class OsmFile diff --git a/brouter-mapaccess/src/main/java/btools/mapaccess/OsmNode.java b/brouter-mapaccess/src/main/java/btools/mapaccess/OsmNode.java index 2f24233..fbd35ad 100644 --- a/brouter-mapaccess/src/main/java/btools/mapaccess/OsmNode.java +++ b/brouter-mapaccess/src/main/java/btools/mapaccess/OsmNode.java @@ -11,8 +11,9 @@ import btools.util.ByteArrayUnifier; public class OsmNode implements OsmPos { - public static final int EXTERNAL_BITMASK = 0x80; - public static final int VARIABLEDESC_BITMASK = 0x40; + public static final int EXTERNAL_BITMASK = 0x80; // old semantic + public static final int SIGNLON_BITMASK = 0x80; + public static final int SIGNLAT_BITMASK = 0x40; public static final int TRANSFERNODE_BITMASK = 0x20; public static final int WRITEDESC_BITMASK = 0x10; public static final int SKIPDETAILS_BITMASK = 0x08; @@ -111,10 +112,10 @@ public class OsmNode implements OsmPos } - public void parseNodeBody( MicroCache is, OsmNodesMap hollowNodes, DistanceChecker dc ) + public void parseNodeBody( MicroCache is, OsmNodesMap hollowNodes, DistanceChecker dc, boolean readVarLength ) { ByteArrayUnifier abUnifier = hollowNodes.getByteArrayUnifier(); - + selev = is.readShort(); OsmLink lastlink = null; @@ -124,6 +125,9 @@ public class OsmNode implements OsmPos while( is.hasMoreData() ) { + int ilonref = ilon; + int ilatref = ilat; + OsmLink link = new OsmLink(); OsmTransferNode firstTransferNode = null; OsmTransferNode lastTransferNode = null; @@ -133,31 +137,45 @@ public class OsmNode implements OsmPos for(;;) { int bitField = is.readByte(); - if ( (bitField & EXTERNAL_BITMASK) != 0 ) + // System.out.println( "parseNodeBody: var=" + readVarLength + " bitField=" + bitField ); + if ( readVarLength ) { - // full position for external target - linklon = is.readInt(); - linklat = is.readInt(); + int dlon = is.readVarLengthUnsigned(); + int dlat = is.readVarLengthUnsigned(); + if ( (bitField & SIGNLON_BITMASK) != 0 ) { dlon = -dlon;} + if ( (bitField & SIGNLAT_BITMASK) != 0 ) { dlat = -dlat;} + linklon = ilonref + dlon; + linklat = ilatref + dlat; + ilonref = linklon; + ilatref = linklat; } else { - // reduced position for internal target - linklon = is.readShort(); - linklat = is.readShort(); - linklon += lonIdx*62500 + 31250; - linklat += latIdx*62500 + 31250; + if ( (bitField & EXTERNAL_BITMASK) != 0 ) + { + // full position for external target + linklon = is.readInt(); + linklat = is.readInt(); + } + else + { + // reduced position for internal target + linklon = is.readShort(); + linklat = is.readShort(); + linklon += lonIdx*62500 + 31250; + linklat += latIdx*62500 + 31250; + } } // read variable length or old 8 byte fixed, and ensure that 8 bytes is only fixed - boolean readFix8 = (bitField & VARIABLEDESC_BITMASK ) == 0; // old, fix length format if ( (bitField & WRITEDESC_BITMASK ) != 0 ) { - byte[] ab = new byte[readFix8 ? 8 : is.readByte()]; + byte[] ab = new byte[readVarLength ? is.readByte() : 8 ]; is.readFully( ab ); description = abUnifier.unify( ab ); } if ( (bitField & NODEDESC_BITMASK ) != 0 ) { - byte[] ab = new byte[readFix8 ? 8 : is.readByte()]; + byte[] ab = new byte[readVarLength ? is.readByte() : 8 ]; is.readFully( ab ); nodeDescription = abUnifier.unify( ab ); } @@ -185,7 +203,7 @@ public class OsmNode implements OsmPos trans.ilon = linklon; trans.ilat = linklat; trans.descriptionBitmap = description; - trans.selev = is.readShort(); + trans.selev = readVarLength ? (short)(selev + is.readVarLengthSigned()) : is.readShort(); if ( lastTransferNode == null ) { firstTransferNode = trans; diff --git a/brouter-mapaccess/src/main/java/btools/mapaccess/OsmTransferNode.java b/brouter-mapaccess/src/main/java/btools/mapaccess/OsmTransferNode.java index 5f916ee..50ad8e0 100644 --- a/brouter-mapaccess/src/main/java/btools/mapaccess/OsmTransferNode.java +++ b/brouter-mapaccess/src/main/java/btools/mapaccess/OsmTransferNode.java @@ -5,6 +5,9 @@ */ package btools.mapaccess; +import btools.util.ByteDataReader; +import btools.util.ByteDataWriter; + public final class OsmTransferNode diff --git a/brouter-mapaccess/src/main/java/btools/mapaccess/PhysicalFile.java b/brouter-mapaccess/src/main/java/btools/mapaccess/PhysicalFile.java index 11276b4..8ecaa77 100644 --- a/brouter-mapaccess/src/main/java/btools/mapaccess/PhysicalFile.java +++ b/brouter-mapaccess/src/main/java/btools/mapaccess/PhysicalFile.java @@ -6,6 +6,8 @@ package btools.mapaccess; import java.io.*; + +import btools.util.ByteDataReader; import btools.util.Crc32; final public class PhysicalFile @@ -37,7 +39,7 @@ final public class PhysicalFile if ( osmf.microCaches != null ) for( int lonIdx80=0; lonIdx80<80; lonIdx80++ ) for( int latIdx80=0; latIdx80<80; latIdx80++ ) - new MicroCache( osmf, lonIdx80, latIdx80, iobuffer ); + new MicroCache( osmf, lonIdx80, latIdx80, iobuffer, true ); // TODO: readVarLength ? } } catch( IllegalArgumentException iae ) diff --git a/brouter-routing-app/AndroidManifest.xml b/brouter-routing-app/AndroidManifest.xml index f4ec7ab..7e66d62 100644 --- a/brouter-routing-app/AndroidManifest.xml +++ b/brouter-routing-app/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="3" + android:versionName="1.0.1" package="btools.routingapp"> zOjr4`zfWVAUPL*|5$pZ^NC~uCCkIV zBU&!P{^UuWYxjrz-q~+{&s-UT3c#*)yBhVvK5eFS9D2@B8`8Rd{7{fGrOMTtwq%R$ z9$GB8&um!h+NbM_dPP{yd$vq-{yYL*CN{3j=0ez{f z_i}ES?gS>1Vr;fRkNeqWzk`T{-;36pcjgpPjsCKGdTOND|2GqwzA3zs2BNkGjnR8r zILafvZ8xCeGF_zgV6{jp=y3*KbH0O?d?qS}_ZA!ulgvDP9;O9^)j>SYn)dKz6(e z_(;TaDNVf&uz0?H+40!GoKu;OdWtFzC)6D~S`Q?NlE#>pr+7mqde@(A-E3N_VR;Y+ z5i^bfA96m*=Nh`|VqSp4oSDo`yO?*Px1rVtY#T(=^>g2S`K<%Ua1l;QFarzURA3jG zw{q@0G8%@&zR+a4;G0>}a{cH`8FSduVC1F8&r#>5%_GWT4>R#_$niq@0do9fpi%>K z>b#E{pp#Um!^}GL?cQNnZO~(Ti+jTqYe(=` z@ZkpT6G|WFVGPndWvWHVFf2Q#t^9}+O^}JQd7mz&Oa``rWLwcm@ta;kP>zmP3oWb< z6pa7~ouYX;P}(H|wx<|_}ekq*<j?kxW62_Zraa?0aaR{8AjTg{dWR=s7y#!qM>w5zdW6uYxneZqN zpa?^Na@lZH&VKMA(#gkiMHK7E1+K)HyDFT!88rI6&Vy{S47Itas5gtUM<}+Gyv$a4 z0%WF+e`i7mjjw&K;`OUP6@E+Jxkt0P42c2`e9y5UzsK}ohisinkWWjT6)outEFpCRp=n}qk!8s^YM__>fxqtD)OTmXzLipSC2b|bx_`@N`(8)6(shE*r57n_ z@@LHQOqSn1<``!{Ts;WA}ZbH2iHhbZjSdZ&wy&R)1c*AneE+drIOi6>6QPI^0lv>*BuO48+OZ>zY9V3 z?1N^Tm}YCqU^z-S{O4n*t@vMTc;33|U1HZQp$hRmu?vdq0j?!+e zMuCXn%ypv%d0IzyJh0>G$X1iE=No{Wd?YWoZX-z5>>Ndzse6Si3P0#UQjT5As9mK` zQg4thuT9AQ+yU@YS{Gd;{B@k1_<3Ng31zh#8@4u!`8p|GELx_n2wFBga<``8)_#m+nwPT4yGH_JyIW;7SfyD<_eICt>q}S`ksa zGt@eX9jKE!$@LDSo{>Z#bH3){MSVigh0tT>jN;qrb6wx$BN!gWOA^#;oI}@#nVd(Q z(S^dH8E$l1wjWGZ8GBeQRawX^tH>kB@1)R+qdZKi%BElkYtgSImT&1Ju<6y{Ch(R% ziQs^l=UYYzsWjE1F-0m)_Q#~rsUx&@>W2lA?-a}DREv`Zs{hmv+_6jm8wG`%G6t=9wi608u2mV)LknI_hXg8vI zA;ts%x&;6Lq<>YLoui|zyOS%knXy}no_yUwo69!$>}ODxArX$`xx@D-%H1_rb*A?x&kw#2A-dC-XE7r^&delQ z>jY!r$J<}B&Q~?J2=Vk0EK`i0EW8}gEn=NPw&M+l;8<}D&<}L`P{!2*UC*WW?e69& zHd0#X4;IA7<)@;&MMU*5bzLMbE~rxW(0s;b4*hyP$sc-9kTQL2s*I2LJ>h-TIN+`D zM@-XAp0XPAhqw;g{V}J3iT+ta;EGeMewJEfqWh(E3hy=Q{DrZwIL{htsO{!=I1E{`je<73=u! z6eTL7V*>MD(<9Ay(wq@utC4e-l2!|Hx~L&Axg;&M=@A|F51Ya%n#W1hi1_VuQ8yN; zpJ{%-iKRjdBZRDNB}_@`35fWzapDs#ddhAYF+yUqvSTIxD#-KE#+jSXNCq>dB<^l! z2APSO`UvKt{#iBF=+gRh+WQb9xmJ zhfd~hEo*RIK#+xwz3WzBb(Mq?h$vBqR3JBf`?5F7nM*oIW^RnQo2I7`cT3-n)h`xQ z=|z@a9~$6y{fdu1jevqw&zTE~FJZf=>Ee1NzOR=xTG3WVSvYg9`1rMxd3*{JoKq2M zlF2^wl(s?e{TVqb|NCaDMBkwVCA);aO?4o`G)JStDL!)w1IadY*tNLRXGNK?+j@ah zCjUe|6XMjN1P!}eB3>yga;lc1M0DiMcEHQ{pX&OXM4jK>L{Wh<1L@xvL`jYFZ^tjo0Qz(RbEi4E1 zC-tXhh9z@6^Kj{Wk58W;e8O)+!fz)#ClQ}7BX2hw_j@~^rUB3It!HFA_c!>JV4qxI zKpt@R{!d_TS;S5*+Nn3lM`Y%sZzE@HU1_9S4Gey_d6pt-vbi?EQlmX>a=+kdx?ZTL zhwNjso=DU%SdoDD=pI72_`VTqnVz}e{bDQpi8FVP*^O(f zwf4|P!WAj3m0$#E(R!{-6X*Z2*nH50)}EyH6KIw&tJ}w+_$3)cZ(Nn3-z@4bPpDJ9 zL3zQuiPr28vSG2CiF3|XUsxY~DY0smL!XYi-Wwvuiq%2~1x5csRX7N4oSYw|k@}l4 zuoLPk^D*Wtnd%iZs_4#x`evdvb@;?PQtQ8nSf#|}($>UdxHC}8>K5gm1h-^ZH72Oj zx7qiVS2HKPCBO|-q$SKle(3lPkB~xvo1ga>8jwkGzO%i)?z?LHRrHtT1Jp3#I>vM! zSfh<`1lG`k-RmSr-=eM^7Tn2THCCMe?umRO-1J5R!D0q6c1UwWp2#EX^no5>XzzsC zHybF7L>(Fwhwo$w;mnxE08s;&Txl5TT2s#!-R3WfxYhtY#p1eKbv<3KP$9))`E}I- zA`Te$Y@P|~vT(9vWbMvuR@`Q7TCjK8={D_jbl7WVgqdqWg8H%aa zSI(Pr$3aP6Rg=bUqgpHZPE0P+s#do&{S!6!K@QZ1D}ycN$jU$!{=nJ(P%RrhA5bpK zpmvlT#pwbgU+&hMI+G{Ht8UU)$8A>D589&?*N?yQwg@F|fyDibw@4kZ)B9Z~70U#& zz^Xn~yUokpI8zz=VZeWzX}H34&o+{8|DH`}^)CBe5TQNS-He`=pTo!gKJ9AedbCFZNVpjffpT)5B7zh_(cy zkFmb^DZ`ElM7|jzv-u^}tqs+Pl`S62H$RXP*%Z0qIu2yq$is)#$nRN6bnZE7zuf5i z0t?PyS6%H@W+a#XF~=AT)Rl5S3u-8MI02oaBWM&=vf_q|fLd4+&q(L0!MkH2c4iWn zx|MtA`m09uFHmw>CHEJLWJ(gP-A{sr(AS)U*d59cnB)+r`@b!kO&f+$k>LH0j7%qZP)k#TU+*JA3WW+@cHkoPJMn37Fu+!s}Hh4Gb zslT%H-a)OJ10>vIP5|Rh6O4hY634@&>Xrf@E7n{>_t^iCk?E9Z0ONLKG z-yn^FYvc0nf@;)zb*E!HQt_)>v@b24Gaz zGultz{XAiV*W(#p>p-JLK)`RZc6ql6*7I_@A8FwJ!O7@44Qo2%>!1<>hu}C~nT<3} znVCMRzixe%DazqSR&VC1!a%Xbeje&N?2`NmWRS_*ZQDy{C@+5K5Zk0>V3qhMK1DVv z$m{uOqeu}WsQf){p_5R?bBZ`AaKQYK@ql~{&3cNx+b%Lpri;IwBbF~rt#$KZX-rG_++#1F#CHb3lyaO z0z(h^C60}fHru<-==t2Wapd=K>6bH2a&oNXDk-=msI?__y>CZ;x zGk+9FUFeibZ93V=erb##3;)<6V=tm}tG2FXk|vO*wzV-Su(e$0403yG?$rT8gx>{h z-0$JQlq0E#e z9#5lZRN@_kOf%8gMJa%y*0ZD?Yk+k2PS69tXjg)}+oFs;wDwEBwPTc#^w(8c6HE&L z+eIV}`k<0ez#Os+Zf7>@XwF&!hsPkvsA<{z6Q0lWK9lCo6mD-&SU_IS#TA5n+5MNsM5Ax7ODDLp+1^Uvh?}E^M zf7l*Nnn_{STcZE#`^z6b9<<>Mgj)6>%uLKvy1pAq+FcN88?xvV<*X8223fkPta%FJ ziA>bx3iR#P<;UqdFsmLAmHoG$%tkkwU^!pK%;nA; z{aY5LeIICe#EHsy=~BhhI1H0}Q`U+s*xCjBBt(9(Z$jumeBxRhHTr}(4Z+SKH+Qx( z0(jDzu0zZ%D@y;?=w!PZRSUb&kkpTmO_cVyezh`fqrD(TLu6(6^w(GwNx*dC&Hi_H zE%Ow*R=Em9u&l$Er`GPSVG3j3_*W@w6hDE3UzVUV1GNS54wZexG)juZ;vUsvVR+}9-MEd`cuSpF(}Jd&5Kwa`khCGmMr9c zNI)lFY|0Qc&&+P_Xt+EiO=bR(Yuow7 zSu?VxpKUx;yX9w(H4-=$4lm-RaRXc!HvVtq?&TP?+-{ z<`hMoIJpEu{DS`MajcQ#k$Jmm+q|>-tH3UC3Cnd9)A$IjW3L6 zo(t_T`CSMT-rSCakEN?wOmy8xm}TL!IRD<7-)mp6^FTBm#H*Qc==B>nf%Dw{M752v zt8n%@uB`NHSm=DYc;s=jCn*Z!a(2c!vSZw#uPr39GhW6^%t}#ql3JQc)(NU#Eq~Qn z;q7bWbVYAVrlO<3$P61&j)w+?zBn&oqaYS#GP%*GtkdR@yEojLU-RW5)JY4|5FGNJ zO@5Uf!#WD6{)kGXsXSuWqf%ZdnerIJ3LE*i^!ozp%CFa!P67YW-@@>;;Zk&VkE{E( zR!$ad{1vE4>MeX-v`$7}^;uy5`V(;Wi!;}vu^4%~OBC1xmC z-L&uFFozkSb~bi=7^;DH;k;g zm_RWHT#w-;j>PG%V&=%JPsQ4+2wVG>-yVJ{jRx|E6wfu*=5l^Q<$yxqv>olA%4*oF zMjxr~Rh2-ARC0QBA22AL>9m01vxbj!eDK5)Q_XqACX~iLCy3lzU5KNywjisdg4%vs zQ@V{bCm&OkZ~vMOHH@x)pk*Skm{Zu`WMCy`Jy2_N92=3&Mb%}2bO&SF@u_9anKMS2 zm*q&{kO5{$EUDuAYBMCQe6yGMm)kgHX0ch_Fu`iA+-DNF!Xv$%#fjYS9vOaP!mjryR}TZa5kC^LGgZ4ahyK z>?_A254zlw(G%svYG&c9kjDO`$+1l6?rh1ySZ$+3wLr4TP-i}Y?QQfc#j{DkO8CBo zgoV&50x7+oP8rA;N~PfYT}PFCt(J~af!)iR79dhA^~MkgH=e`H<}NdE_QfwzPQPN8 zW65O3&!=0M4N-KAJr4*FkIx>f+euui?Zsb(*Gg!HqCjHBhJq|G0=z2At3!NC3bSF{u|98#Gb7L5jX5 zJua+}qS!gA@vE)o8{Nh$5k}u?X&Ni;Zt=$}DwoknTya-Q2VE8G3ZWfhhM!Lk|pWYq_Y$(n;qT7~uV&Tv0O=d9Fv#sotXG-dmn?f4> z;-W@+e|ZPnaLqV3gJxaZNZ2PsMl`;;3{g~@E3MqAYO$FY(_LwK`%JIaH^86?i&hf# z4R=r^4gXre?WDx;XuZ`(BV05u z53?9=E)qqliL37`0L_@f+$i@LWp771h8+F%m%GjY%yno*fTYhKj?P{7DY^)bhWi>3k~h40(Z-ekZI6f8*elr6dK?$Z)48 z@#$o)!rY}?J_RqD?-zPhizC$7Uvm{w?t0X+Z;4*m=l+TS5B939XMHkg`0iuQA7oKK5>=9h@#X!A^*!$;r==3Nf4`8BRl|*lf*{=1O=gO2wM4GTs=bTX~@# z<*T7zgQrHRO13Cfwe&lrne%(AcRKvVL?BG3gX!JJ>0e8)Bk^0^{UP~-<-J0 z98sz6Fo-|$L{c#uZ^>2@@gMalwpg`4kn{^l$ zeNBYDEQlUvp%8POwMsi5LY@k3u*c~0YdsnlssQW@PO}rT|cL+p|LVbGabC{>W{3zSI-3{j-nMAL8M3o@)> z*@B#(h3t%it^IP=#8j@y+;6M~^2Px$p!`WnFG0_t5-aGllfi0N1R^{*U*nqD3_;!W z?w{?n*=D!hjW(1Qa@Zel^F&18VDsd54Q&0+Zq8qrV+^gq!~`Ca0xkv(x?g^?_oUBR z=YYH@CVFV!ll*3g4+nz9OzO)HGJ!C5lQ7A@HbCt1mumMPG&l6gq%6q}sXxPBtu~wMswC`^bLoX|fi9gE@bb{u~_C@*8Yn?Zcp< z^70)6$L{rR#cdgOEafojjz?~wU2ejW2!Ud>h7DgQKlNX?DXE3IDfr?t&So8QQ#nUItYy|R} zd73(^lS^r*y|cPWxHsF(%?9>QEYqSqOP?Kx{e_r)B z^$MUet|q9ji!V?t+7vgVa<}uLshzEgry~oZ3=vQJ4vcug1y{EHV&jQxQ^3Q-Zt>f2n;V zmhAiS{7lwsud-g(U2=4zl1}CBXAz44$uF6jHf!xoz7w&cY2Z2-&DPkR!7~CM&wN+( z5n|lrXTF4@bkqrxL*b`Di%F|gn97d5m+^R(EntNsDaAeXq$BLVVLH&5kq`GWwWff89VBGze*>b|VHu$`?# z3mcb;b@zm_G!bWEmC{r4b6!XhgYliCuHoYoXuIhEj@%SNdLRl9sEu*XZwJ$RGO~fc z{@!m4dpbYDnSE2HIqZxVDBD!Pvn2hIUPz)JJK~G4exC)PXnR!eJdtP1I2Xwk$1SXT z;R7$(29o!Oy&k~nmN^oe(2|r>8*-;ML9$>$cloZUqSE28d2R$qI>2tL8 zs~;F375|07QUNWb^|ywS_6btVju(19O%>V=mptmFQRmBM!Q^7haB zm>KpMqDNwee@~h~K1l7_wDij{8+7PR>WtZt9R{WSOW|yu2icc4G5Vji7-(muJewz~ zvw~rronGcAwLc)}X~7PFqDEzxulRD@Gq*0YJE}anmR#HVeoVykoon;bd~F4dERnSk zU0CV~mll28C^1|6Z{=$U8-p<2BUiN1=3?=B`A>M1!&S$3UoGH#HVMZB&vGl=P7C%< znLu>@Foa6k5&1guS55Xw{kd!S2|Z;Aofs`-0$FVL0eam3+IiRK9J7U5j^!m4hfWgg zB3TGTA$Iuq?^N31rs5f{w}f>ntQgr6CZNZ5_Kug5iMdX#9x&~efnGclENtNKtf_qlX5QUCC?-SY-3csG#I3C`F#CemWw zxqC1=`{O@x-9*!A@eXFde$=~G;W}SK){dCJ`K}@l0f`OxU-WrNyJSqj|4kJ1kN*8< zr2j^05+ga0&i}>_{|DkfF+~XfgDw8=*ZnK^B~I2j38MbV0W&cGfPcvUYo!0?Q=+7N zay;Gt`4#w2S<-)^{sWW_1OQyE99{mOg7Ci||37LplK+3FIC&BV#TQsohW|M1{{Rmc Bzt8{x delta 7985 zcmZvhRZtze)_`}B;_kYkxVyW%yBBwN-MG8EySqCSC=@7CT)T01ivK-xAMTtxe`fNK zOx9X?NHX7iiPve91S!iwLSX_R0I+~deI@a*7h)4lNB{r^6#zg4005@OE(~twu5OGb zE*9rn+m36@r~wU&A43{OFz{}6^W?5jP za@8xCG8XJ`5F+h0`~Zx+2q6L`Nt@Zv0X`=;G0)IMJ#;#nUt^nbG|0HYxTuqxDHlHJ zl$6}lCW$Vy;d5JDN$_-5yG^UGQ|V?j$rRZMXtI~NE|^$`FJIZzXUW@yOJ$+zm5brb z5#`ZTQR3!RrK87zSLL4)7dDmsJXlt!mwQbU z)SN1lk=q2=vRlCFs!VfLTDJPCg+Z7Dz_zAHF^QuP8ux(t%J*U?+yEWo`9f$=S~iKz zvK0iU2_n>Q8FUziglmRy_kZPQ4Nl#^WSKGt;795z&-HJ4^II9<3IpwPc?+SO1(=}R zPsR9|*2Og5T4875RcX&J8Y_so*3}#>ckq1xHL8Pl+@DSd*lUxt0uhjS2D1tt7;cmcSn7q6LJ<9qJEqImn)jQN1Pj%H3%B%>g-d+i!;|KaO2X zK*yp8j77LtikX~-EqT;`7q=}4-y$@vI2qa^Q%^ox3!l&bO6{0RW1zg@o=Y7e84&Bz zS<+vqJgi5=ZW)Qy<|8+&9<7{uh5Y*`s>Wa@Ht8;Y|7tmAEC{IU{b@$|Gxi;VS8F#*p z8}57DA=}kMIHx^=nh+}jY9a@1o!e@@urpQbP5I{b=C(a&jw&6D(Pl-+B6LP<6O37g zs?m{ES$!a0<&ZWy&>K}X267j;B9!hX9NdJnJ4xmx?7epaII1HPLfFI?1^G>QYBeU% zuhYDpQY8=9VZnq|t2AO^WePlBo-s(6T-Z17NPm?CCF+3ZU?^QG9f)j{LY-Ny9EsS| z?`PGuDQXYR@?C?+O9(za5L_j(C83^eWGt&ftR8+ds|wwSCdM}C8ezhq#3gMDZiEF4xUj<|IG?`Lg7HzlOvCDD~IsQfk_m$-KH}j7~ zct>6e{$7+;fj_e|hg)K`Ge%XLJxWPFtQ z=u2NU7+T|iDtR;|L8#6k99KqsqRO6pLZFL@BXV0li&&@{3<^3v8S_)2uZBE(-q*9~60HtMD^Umu*z@jI0d=%Q4wTM4H`#rE8ySY*$d z-NIziAD1ro76;D2>79#PFnPUh=ERg*Ile6LE$t@~ zGUU7g5U$D^u?u#+j1oaijIYGe`YIZrU03qJ$^>31(A&ws*j7?M5 zlVn2S-(w|3Pa987VvK=`xd%*={xd9a+#Jm~?bjH@J6ZAGCwT3fH_`%{driV^zOhWw_ zEYOJ2DP!Yxgzrzapioi=d(TIDL7~Mg<`Hi3+fLER)7Cu+*mqf`?09C5W%G&Ym=^jm z6#y~}14o8vSqERhetJy}H0l_UYgf1gljcQEP;ah8f%=dpJJF+@Z4w3^sYy&l8>whY ziQ{H>KwNQ(<5OPOS%qpwnb;Z|z4y9&cl<6K0iU}3vm^QmghCGx9_q(uYz>?+(+f&> zewlpN>CjaJf}5@K(DWHzyoh<$?68a35|CUs*KV8r-|UI?a8;hN^~Yu)dvpz1yk7W$ z1p1Lq49e`~59~C*uj~NNL++V*w|1!%Ri}fwAPKmsaKDhw9Qlg$)NHvB$LyaQ6l@$@ z-UhY_&Aot#vc3_P{$RiA_pXJ0fOmG=A8+U&^p=(213W>K9$j;ppe$GKN4z{HSh@V9|~KkYBRQ&IUN_esTFRR~S z-h|8DGLCL3Zuf?@LC)+$I}o{oSq%kkpVmo4c-6+0XzCbRJ6ap)n3$N{*Za5YfkmgL z>#xZ|px4*yn;X@(Y1DV(fHy`V>wSj&?W;qhT-V)Hr!WgKEzL_?aRM#sk?x=4YF6Re zOLVz7O9aL`!0rU?Fph)Rw8^IBcA_!1jLf8A?Wy|xtM<>OAgmb~58LYQvzI^kBQ$7< z`fwo_#+=BW+(ZJgj>Bdg$S8S2%JZ9>$twj8F5t&jc2myp_m9cf$=Y(#h6t zB4l#(C}J%PKzjMA!d^5Ljt=MGG2ib_Z^}=aNLNkr!g3?=2K@G$xLm`xhcEW|g{k{z zx)~$3>jtW*j1aTOYqskV7<38dt~NP~3SYxqo_Aq$Dx4zJ48=0~xOD<^XlfYlcg52o zOt@1Gs9jTCJ$mo2!XC1NAmZ7_WtBv@B{#0Tkw6OhAQL35vyHS05?5tw{TJA3%v3{d z{U_LH#6?NWTT6HNFIQpNp7^R&1MUsXe!L6S5KWp7%N@#@z&5Yt7{{EK}(MF^w^p{(^xO)0*WQkdSoKzAi9F>-<_fLWN|g zZBMfiq;`f5xobK0bFBPiIPoHRj241vxf!3ePJH)zx?eu7)C}UIGhDztaUH(&$4cnP z+k3!!XDaA%8C9_)Qu1?ZHcfu5DOy)%mRlb9KF>7RGSEd5`-l0dsM?x?gQHGbr5RTU@PU(wkh<7#BpTfhcArG|q+ z;uD{i?Jz-QnWn85AAg=WM^%n{soM+BfKg+3++}=a0U^acu-%y+MR2SDYF>fsO8FNl4+< z$)f79L)9yDUjSq#4H&j$~9BsRt8`NPA z9IH=9>$4oaHEBv3*no_BZQVYIzQ7hn(B=JMf+^v8D36HjVNBYvl5u-FmYTTTNq;KX zR8!Zsbu3M!TIkz*Fd|VC1?b z-H$!?)6UI@f^RnUftWKw3VI>PLQSpbS7=+mN8E~fmDfMlL(dstza!9L91mmZfyyZ( zaH3=SyjGv9C3a;H4dkRtV$#~=P?%?~@;daNqnM3WyPio1Jx>J+zKEU(X?F^)-QE!u zG^&KLwAi28?jD7(ji943W(Z~v;}Rwx>VkFgIxNR@(U&drImu@$`f`vul`vg7#tx_b zq4dNS@fDh~Y7tJZs*p=zAEnc4L4Cy%@nZ4tHf$9T1z&=*_1Npgkc%ex1-)0)Qx7Ul zs)OJL1?JaHZ_6h)hTl!)AdSOG4u9=(EJqzkFAWr-3GHW!V)ztHsLFHW>&_Z*E7b$E z2;v8xt9yk~HF53nW|!vjhvvlF<0CZEC;htPX{oAeD^8`KqGf%%XRzv>KqsS9Cyk4h zjT2jrN!clgd-2)XEXNs5JZCaV|yo&tlcPV_M&`9qn|xn1mhO>9HOd=AWvy^VVOSOL`KzU*i>gUNO>A}dL^c^D?`Pe0HW*8L75tEALP;0#^HD^6SN ztWKYq&0`6ra16ff-lAqVH3-|#^e~3|lG)CwHQz4wF@1_*1kIOtExF4$whxnc>kXa! z;U(nsfUii+otPd$BuB@UXI4!VO$|_0_KEc!?=FkcCxZ~2+yY}t5m14zOD#2c5IK^F zSbh;`I^Vo&AM(XvnI^A^gb}uYnrr8{2f~pEIwkXXw-}f0IapR(h{-mniZi8)q0$2w zlL$^7BkSIgKu=yTQ|Jt0AHI(P{?$=*yyDdFFvFpesX`c(Ao0blOH|55(hJ018a310ElPRj zH=7i6%8io#y^xpWO=Xt|S8ezqIZql?6GhIb6j5$Ly4G^MTCv(PUJA^JgY6R0KX<6U z>aZ;AJ?gOLQAD)j+N9qov4XEx57jKbh+$55RHFJ6HB_SBus_}J^rE_(B)k{e?LHi% zDBk|+03D$``xm^Ed_GIKgXs!={yT=Md`o^Wi0g_@6s&l;j=bn;70yHCxS6kG(}gRgWD}e&$u)g1nJE@6y%J!#Im4LfI-GF#jgC!&MHvsJ|{OyXAwR1QPilJ!V^2 zp{)V|0PMo0Gy*X}3JHIGSRdInu>AKtv3Al(yDCNf3l}Yz`@35lRWlLwM?ZK}v6&R^ zTystCFm(L(`T!}Qar=@2uOZ;+vaCGiC!jGTxV4-v8=ZU~zLqxCeFx42u>w=ufopvl z*{@94+8vGfyD&p7H{I;+t|oUxSx|0$xo8~)4@!iuC%6hkP2%fw(U9#!Dab1|_l7kn zVfDjkq94^eGCeHvjd@pNV`&^5*oU)^+v8X(!|g+be@D&hcM)xmz{8(HWh=8c2rD{sXq{}|>S7>zhAmozPPt5b zNWtxn6gB{ARlxXOjT-l05Oq$;iXq~;WqKKJkvU8}b6vi{PEwwtfMpZ&3axx>WtEL~ z-ncXCQ%=6HcBCw)7UdU=(O*6c9t!ql#RAWnO%mqeNYZ+z=!WIVQ$`*st$f~45E9o{ z4?{qkJ6JWS9{;2IU0j=&iS;3~XQ(+VvQh3LCtLyKFU2VKCS`FUA9qc+PCfk6y)Egq z?PzKtb!@Wc6yKoi7W67aBB;29Eo0gdG3bucTcb=z);bV}%^?h&{v2^(p3p`TDNIT} zkPZ;rdsZ3af3*D2Pn-YzUVmgtYAx~zBL<$o+*imRPED#SyZ&V`>< z1!sc_Gi>44KFgEe381Gsrwp3^2uo?iPTNZfmyl$ z=~M=9504=IFNi+$)z#V>wLZ1gFb~HIR1dSd%$B1sJ?bz^_Xc)Fzzn0e&6G1S7l<`b zM_8V!HR6oY>6nuo8Q;cHfI^rODmMG0T94qOIle9CF=CSDAPYlC12~IOL)@uci=@x= zzTPD7Fb_-!FJHlfrbR|N2(!vd`b1FcQP~CLZeQZZe;s@|W7Bg;4R}r}b+X+TF}8(m zZ$`JE!*{-kHg(>ueYzD-;UX$>j>t@^N`?oQESpAK4BYJnX}FVd6Cr&Sly=h%@Se`2aB3C zR_uoZq3wP^t3TJ;jJj48xx!{w0sb_bP3h&&9KYq)VV}OMEk6vWFUR2BQy&=5zXigG z?EV?5c@y?%lfx8_0vF=WLO`Td|)Fa5a4YSt>{Jt{6Ik46X6B2MVnIB zopqV<_)tfw0A&d8kJJdY0hu3}n1*uNzk0q#D!T-$&wsblxgasrU`AF^6j$sq>m8&R z&gG8=ZG~}DRtR{(2scQ6A|5@ImFQeSB{y8LiHbm4`)<0vgY9zV1-IO!JGc_4FA01r zmx_CH$`KI=xQg$$U?mczWFFm&Ocm*?4$>%Y`Yj(UHB&R152+mznE?D^CQ&wWQf?HF z5~kCjI8nC5Pf0Q9k8BzAAliSz}tMFnWCySCvd#>U+xycjP zx8(4f-RkLqopOfSzjMoJ(umw`>}g>5dd`K3JnJ97MZ@%%AA3hH+9!hvO;t5ZD#8O& z{j|*H+#$L<*~yPlAvu%X(n`Z_8q|{_jGN|5=@(zS499(5_p(S@#9FvC z5TCkOLS&-%>qjAhG%?T5n0exZ0;J?B05lr2-f2B4rug~Tq@)^JElf%Q7%TARTTi%m zxvMzO4x@8F#Ssx|y1;MILV^&dnI=h)Q(}XT$UQ$;SjNcO=MTj}dy6~u{dae=QiNzj zU+&s1@j0eE+N!0s!ZYE%4zX)z1&GZruC@HXbJ+5v2eh<$W(i$iXCpD9=~ZONh7SxI zE#)C%=p$ejkCNm&>e^ZNE~kID@5;*4mlV)$-v;7CRp`;>z5aS>Pddq~yKL441$9?V zX1$~hzWZblalqHl$MP{i9c08l*|YT0q)ZTm8)?^axNto-g@F^!GLb*+X*`!65tj%OCJ29wvrWHulGx-s2ZWUJZS~ofj>0 zwS}f8k}#;e(ywf{J&IP=nqZ;hdYUNxB0T1EC&eK}%rDuc_L0~b=|PkJgTNb8UL#J8 zArdS&9cK9LIb5NbKnlsjxUZe1`RdLXcWp=gBvu#PVV)47R$CNF&_am=s>LyS&kVA@ ztc9&KbDWDv?dXK9oBpl4tUkUa>i%*1DaV(@{YtKOO3(OV5app$N1#kiftziWm1!xJ z(KcBU;N~o-S*d@wxshekVLMKxWMDXW-M=V4xWaeg0F7i6yJvIrJao%D-O1K`W6Ux> zzO)calWXxLD&iKyb7c4v zv-`Fz{c_Ak9R^c+VoznpmUFKOSUkbG_a?FWAN6P`Z%~{w->HxC!SeKR!>_p5g~7J- zT;^^MeYuF?&ruE_{O+)>utRTS@btIkd9uDsF0s-O0^W$4xr|~@6WXRt`p}!8rXKEX zN45l#4q;$8C1>TqEvq?9^(Ovzf#dutx1++{qdKi;c=p~-fXI}!u_r>Oj4_j4?8LU( z{3fg(TK;sV_rPGz&)E4#`{zOBHZJvzv;B=C1vr8bJ3AuK$XEK2rrqq@>+CVwBP7LQ zOAuTa8-5ine&H5Dl}|9c+8dE;7M28Xo?fRBte%XUod^DX&me)z@U{zLYwY5S>SBw< z``pfj{|-Vl53d{WWV|J~n@F&6kY^j1=8|ODzPbN;d`EcTxt4-tGGN*|9B^u9-j+KZ zVctvqj-ZSy_Xz?M@c(=ur|{4*=={UX|NYDQ55xR*o_`z3-yZlEt}TpR-At@)&Ho`9 z<^Rd`zpC_~xc@{Nrwq{HL;lU4vO!0{^9LOOuy=GaH~asR{1@5(w|pgb3Nt-E$v=Di VU(Wh(B{IAe8+zi; 3 + following 2-bit word ( 3..6 ) // 0001 -> 7 + following 3-bit word ( 7..14 ) etc. - public void encodeDistance( int value ) + public void encodeVarBits( int value ) { int range = 0; while ( value > range ) @@ -33,7 +33,7 @@ package btools.util; } // twin to encodeDistance - public int decodeDistance() + public int decodeVarBits() { int range = 0; int value = 0; diff --git a/brouter-util/src/main/java/btools/util/ByteArrayUnifier.java b/brouter-util/src/main/java/btools/util/ByteArrayUnifier.java index 5a9c692..a43388d 100644 --- a/brouter-util/src/main/java/btools/util/ByteArrayUnifier.java +++ b/brouter-util/src/main/java/btools/util/ByteArrayUnifier.java @@ -9,7 +9,11 @@ public final class ByteArrayUnifier public ByteArrayUnifier( int size, boolean validateImmutability ) { this.size = size; - byteArrayCache = new byte[size][]; + + if ( !Boolean.getBoolean( "disableByteArrayUnifification" ) ) + { + byteArrayCache = new byte[size][]; + } if ( validateImmutability ) crcCrosscheck = new int[size]; } @@ -22,6 +26,8 @@ public final class ByteArrayUnifier */ public byte[] unify( byte[] ab ) { + if ( byteArrayCache == null ) return ab; + int n = ab.length; int crc = Crc32.crc( ab, 0, n ); int idx = (crc & 0xfffffff) % size; diff --git a/brouter-mapaccess/src/main/java/btools/mapaccess/ByteDataReader.java b/brouter-util/src/main/java/btools/util/ByteDataReader.java similarity index 67% rename from brouter-mapaccess/src/main/java/btools/mapaccess/ByteDataReader.java rename to brouter-util/src/main/java/btools/util/ByteDataReader.java index 7ad5e25..7bc2dd8 100644 --- a/brouter-mapaccess/src/main/java/btools/mapaccess/ByteDataReader.java +++ b/brouter-util/src/main/java/btools/util/ByteDataReader.java @@ -1,75 +1,95 @@ -/** - * fast data-reading from a byte-array - * - * @author ab - */ -package btools.mapaccess; - - -final class ByteDataReader -{ - private byte[] ab; - private int aboffset; - - public ByteDataReader( byte[] byteArray ) - { - ab = byteArray; - } - - public int readInt() - { - int i3 = ab[aboffset++]& 0xff; - int i2 = ab[aboffset++]& 0xff; - int i1 = ab[aboffset++]& 0xff; - int i0 = ab[aboffset++]& 0xff; - return (i3 << 24) + (i2 << 16) + (i1 << 8) + i0; - } - - public long readLong() - { - long i7 = ab[aboffset++]& 0xff; - long i6 = ab[aboffset++]& 0xff; - long i5 = ab[aboffset++]& 0xff; - long i4 = ab[aboffset++]& 0xff; - long i3 = ab[aboffset++]& 0xff; - long i2 = ab[aboffset++]& 0xff; - long i1 = ab[aboffset++]& 0xff; - long i0 = ab[aboffset++]& 0xff; - return (i7 << 56) + (i6 << 48) + (i5 << 40) + (i4 << 32) + (i3 << 24) + (i2 << 16) + (i1 << 8) + i0; - } - - public boolean readBoolean() - { - int i0 = ab[aboffset++]& 0xff; - return i0 != 0; - } - - public byte readByte() - { - int i0 = ab[aboffset++] & 0xff; - return (byte)(i0); - } - - public short readShort() - { - int i1 = ab[aboffset++] & 0xff; - int i0 = ab[aboffset++] & 0xff; - return (short)( (i1 << 8) | i0); - } - - public void readFully( byte[] ta ) - { - System.arraycopy( ab, aboffset, ta, 0, ta.length ); - aboffset += ta.length; - } - - @Override - public String toString() - { - StringBuilder sb = new StringBuilder( "[" ); - for( int i=0; i> 1 : -(v >> 1 ); + } + + public final int readVarLengthUnsigned() + { + int v = 0; + int shift = 0; + for(;;) + { + int i7 = ab[aboffset++] & 0xff; + v |= (( i7 & 0x7f ) << shift); + if ( ( i7 & 0x80 ) == 0 ) break; + shift += 7; + } + return v; + } + + public final void readFully( byte[] ta ) + { + System.arraycopy( ab, aboffset, ta, 0, ta.length ); + aboffset += ta.length; + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder( "[" ); + for( int i=0; i> 24) & 0xff ); - ab[aboffset++] = (byte)( (v >> 16) & 0xff ); - ab[aboffset++] = (byte)( (v >> 8) & 0xff ); - ab[aboffset++] = (byte)( (v ) & 0xff ); - } - - public void writeLong( long v ) - { - ab[aboffset++] = (byte)( (v >> 56) & 0xff ); - ab[aboffset++] = (byte)( (v >> 48) & 0xff ); - ab[aboffset++] = (byte)( (v >> 40) & 0xff ); - ab[aboffset++] = (byte)( (v >> 32) & 0xff ); - ab[aboffset++] = (byte)( (v >> 24) & 0xff ); - ab[aboffset++] = (byte)( (v >> 16) & 0xff ); - ab[aboffset++] = (byte)( (v >> 8) & 0xff ); - ab[aboffset++] = (byte)( (v ) & 0xff ); - } - - public void writeBoolean( boolean v) - { - ab[aboffset++] = (byte)( v ? 1 : 0 ); - } - - public void writeByte( int v ) - { - ab[aboffset++] = (byte)( (v ) & 0xff ); - } - - public void writeShort( int v ) - { - ab[aboffset++] = (byte)( (v >> 8) & 0xff ); - ab[aboffset++] = (byte)( (v ) & 0xff ); - } - - public void write( byte[] sa ) - { - System.arraycopy( sa, 0, ab, aboffset, sa.length ); - aboffset += sa.length; - } - - @Override - public String toString() - { - StringBuilder sb = new StringBuilder( "[" ); - for( int i=0; i> 24) & 0xff ); + ab[aboffset++] = (byte)( (v >> 16) & 0xff ); + ab[aboffset++] = (byte)( (v >> 8) & 0xff ); + ab[aboffset++] = (byte)( (v ) & 0xff ); + } + + public void writeLong( long v ) + { + ab[aboffset++] = (byte)( (v >> 56) & 0xff ); + ab[aboffset++] = (byte)( (v >> 48) & 0xff ); + ab[aboffset++] = (byte)( (v >> 40) & 0xff ); + ab[aboffset++] = (byte)( (v >> 32) & 0xff ); + ab[aboffset++] = (byte)( (v >> 24) & 0xff ); + ab[aboffset++] = (byte)( (v >> 16) & 0xff ); + ab[aboffset++] = (byte)( (v >> 8) & 0xff ); + ab[aboffset++] = (byte)( (v ) & 0xff ); + } + + public void writeBoolean( boolean v) + { + ab[aboffset++] = (byte)( v ? 1 : 0 ); + } + + public void writeByte( int v ) + { + ab[aboffset++] = (byte)( (v ) & 0xff ); + } + + public void writeShort( int v ) + { + ab[aboffset++] = (byte)( (v >> 8) & 0xff ); + ab[aboffset++] = (byte)( (v ) & 0xff ); + } + + public void write( byte[] sa ) + { + System.arraycopy( sa, 0, ab, aboffset, sa.length ); + aboffset += sa.length; + } + + public void write( byte[] sa, int offset, int len ) + { + System.arraycopy( sa, offset, ab, aboffset, len ); + aboffset += len; + } + + public void ensureCapacity( int len ) + { + // TODO + } + + public byte[] toByteArray() + { + byte[] c = new byte[aboffset]; + System.arraycopy( ab, 0, c, 0, aboffset ); + return c; + } + + public int writeVarLengthSigned( int v ) + { + return writeVarLengthUnsigned( v < 0 ? ( (-v) << 1 ) | 1 : v << 1 ); + } + + public int writeVarLengthUnsigned( int v ) + { + int start = aboffset; + do + { + int i7 = v & 0x7f; + v >>= 7; + if ( v != 0 ) i7 |= 0x80; + ab[aboffset++] = (byte)( i7 & 0xff ); + } + while( v != 0 ); + return aboffset - start; + } + + public int size() + { + return aboffset; + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder( "[" ); + for( int i=0; i>> 8) ^ crctable[(crc ^ ab[j]) & 0xff]; } diff --git a/brouter-util/src/main/java/btools/util/DiffCoderDataInputStream.java b/brouter-util/src/main/java/btools/util/DiffCoderDataInputStream.java new file mode 100644 index 0000000..9fba290 --- /dev/null +++ b/brouter-util/src/main/java/btools/util/DiffCoderDataInputStream.java @@ -0,0 +1,49 @@ +/** + * DataInputStream extended by varlength diff coding + * + * @author ab + */ +package btools.util; + +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + + +public final class DiffCoderDataInputStream extends DataInputStream +{ + private long[] lastValues = new long[10]; + + public DiffCoderDataInputStream( InputStream is ) + { + super( is ); + } + + public long readDiffed( int idx ) throws IOException + { + long d = readSigned(); + long v = lastValues[idx] + d; + lastValues[idx] = v; + return v; + } + + public long readSigned() throws IOException + { + long v = readUnsigned(); + return ( v & 1 ) == 0 ? v >> 1 : -(v >> 1 ); + } + + public long readUnsigned() throws IOException + { + long v = 0; + int shift = 0; + for(;;) + { + long i7 = readByte() & 0xff; + v |= (( i7 & 0x7f ) << shift); + if ( ( i7 & 0x80 ) == 0 ) break; + shift += 7; + } + return v; + } +} diff --git a/brouter-util/src/main/java/btools/util/DiffCoderDataOutputStream.java b/brouter-util/src/main/java/btools/util/DiffCoderDataOutputStream.java new file mode 100644 index 0000000..b3e8e75 --- /dev/null +++ b/brouter-util/src/main/java/btools/util/DiffCoderDataOutputStream.java @@ -0,0 +1,45 @@ +/** + * DataOutputStream extended by varlength diff coding + * + * @author ab + */ +package btools.util; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + + +public final class DiffCoderDataOutputStream extends DataOutputStream +{ + private long[] lastValues = new long[10]; + + public DiffCoderDataOutputStream( OutputStream os ) + { + super( os ); + } + + public void writeDiffed( long v, int idx ) throws IOException + { + long d = v - lastValues[idx]; + lastValues[idx] = v; + writeSigned( d ); + } + + public void writeSigned( long v ) throws IOException + { + writeUnsigned( v < 0 ? ( (-v) << 1 ) | 1 : v << 1 ); + } + + public void writeUnsigned( long v ) throws IOException + { + do + { + long i7 = v & 0x7f; + v >>= 7; + if ( v != 0 ) i7 |= 0x80; + writeByte( (byte)( i7 & 0xff ) ); + } + while( v != 0 ); + } +} diff --git a/brouter-util/src/test/java/btools/util/BitCoderContextTest.java b/brouter-util/src/test/java/btools/util/BitCoderContextTest.java index 735f0c0..36b3b0a 100644 --- a/brouter-util/src/test/java/btools/util/BitCoderContextTest.java +++ b/brouter-util/src/test/java/btools/util/BitCoderContextTest.java @@ -9,19 +9,19 @@ import org.junit.Test; public class BitCoderContextTest { @Test - public void distanceEncodeDecodeTest() + public void varBitsEncodeDecodeTest() { byte[] ab = new byte[4000]; BitCoderContext ctx = new BitCoderContext( ab ); for( int i=0; i<1000; i++ ) { - ctx.encodeDistance( i ); + ctx.encodeVarBits( i ); } ctx = new BitCoderContext( ab ); for( int i=0; i<1000; i++ ) { - int value = ctx.decodeDistance(); + int value = ctx.decodeVarBits(); Assert.assertTrue( "distance value mismatch", value == i ); } } diff --git a/brouter-util/src/test/java/btools/util/ByteDataIOTest.java b/brouter-util/src/test/java/btools/util/ByteDataIOTest.java new file mode 100644 index 0000000..b6f1474 --- /dev/null +++ b/brouter-util/src/test/java/btools/util/ByteDataIOTest.java @@ -0,0 +1,28 @@ +package btools.util; + +import java.util.Random; +import java.util.HashSet; + +import org.junit.Assert; +import org.junit.Test; + +public class ByteDataIOTest +{ + @Test + public void varLengthEncodeDecodeTest() + { + byte[] ab = new byte[4000]; + ByteDataWriter w = new ByteDataWriter( ab ); + for( int i=0; i<1000; i++ ) + { + w.writeVarLengthUnsigned( i ); + } + ByteDataReader r = new ByteDataReader( ab ); + + for( int i=0; i<1000; i++ ) + { + int value = r.readVarLengthUnsigned(); + Assert.assertTrue( "value mismatch", value == i ); + } + } +}