[osrm] 02/05: Imported Upstream version 0.4.2

Andreas Tille tille at debian.org
Thu Jul 10 14:50:42 UTC 2014


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

tille pushed a commit to branch master
in repository osrm.

commit 4afb219d8ecf1a77c5611958e4091603d0fd0604
Author: Andreas Tille <tille at debian.org>
Date:   Thu Jul 10 16:43:58 2014 +0200

    Imported Upstream version 0.4.2
---
 .clang-format                                      |   54 +
 .gitignore                                         |   12 +-
 .travis.yml                                        |   54 +
 AUTHORS.TXT                                        |   11 -
 Algorithms/BFSComponentExplorer.h                  |  148 ++
 Algorithms/Bresenham.h                             |   49 -
 Algorithms/CRC32.cpp                               |   85 --
 Algorithms/CRC32.h                                 |   45 -
 Algorithms/DouglasPeucker.cpp                      |  183 +++
 Algorithms/DouglasPeucker.h                        |  149 +-
 Algorithms/ExtractRouteNames.h                     |  169 +++
 Algorithms/IteratorBasedCRC32.h                    |  185 ++-
 Algorithms/ObjectToBase64.h                        |  100 +-
 Algorithms/PolylineCompressor.cpp                  |  118 ++
 Algorithms/PolylineCompressor.h                    |  151 +-
 Algorithms/StronglyConnectedComponents.h           |  628 ++++----
 CMakeLists.txt                                     |  344 ++++-
 Contractor/ContractionCleanup.h                    |  261 ----
 Contractor/Contractor.h                            | 1313 ++++++++++-------
 Contractor/EdgeBasedGraphFactory.cpp               | 1049 ++++++++-----
 Contractor/EdgeBasedGraphFactory.h                 |  234 ++-
 Contractor/GeometryCompressor.cpp                  |  227 +++
 Contractor/GeometryCompressor.h                    |   65 +
 Contractor/TemporaryStorage.cpp                    |  226 +--
 Contractor/TemporaryStorage.h                      |  165 +--
 DataStructures/BinaryHeap.h                        |  340 +++--
 DataStructures/ConcurrentQueue.h                   |  120 +-
 DataStructures/Coordinate.cpp                      |  446 ++++++
 DataStructures/Coordinate.h                        |  108 --
 DataStructures/DeallocatingVector.h                |  487 +++---
 DataStructures/DynamicGraph.h                      |  443 +++---
 DataStructures/EdgeBasedNode.h                     |   90 ++
 DataStructures/GridEdge.h                          |   82 --
 DataStructures/HashTable.h                         |  125 +-
 DataStructures/HilbertValue.cpp                    |  100 ++
 DataStructures/HilbertValue.h                      |  104 +-
 DataStructures/ImportEdge.cpp                      |  107 ++
 DataStructures/ImportEdge.h                        |  218 ++-
 DataStructures/ImportNode.cpp                      |   64 +
 DataStructures/ImportNode.h                        |   71 +-
 DataStructures/InputReaderFactory.h                |  127 +-
 DataStructures/JSONContainer.h                     |  237 +++
 DataStructures/LRUCache.h                          |   87 +-
 DataStructures/MercatorUtil.h                      |   38 -
 DataStructures/NNGrid.h                            |  602 --------
 DataStructures/NodeBasedGraph.h                    |  166 +++
 DataStructures/NodeCoords.h                        |   69 -
 DataStructures/NodeInformationHelpDesk.h           |  159 --
 DataStructures/OriginalEdgeData.h                  |   60 +
 DataStructures/Percent.h                           |  127 +-
 DataStructures/PhantomNodes.h                      |  225 ++-
 DataStructures/QueryEdge.h                         |   94 +-
 DataStructures/QueryNode.h                         |   85 ++
 DataStructures/RangeTable.h                        |  231 +++
 DataStructures/RawRouteData.h                      |   80 +
 DataStructures/Restriction.h                       |  155 +-
 DataStructures/RestrictionMap.cpp                  |  224 +++
 DataStructures/RestrictionMap.h                    |  126 ++
 DataStructures/RouteParameters.cpp                 |   89 ++
 DataStructures/SearchEngine.cpp                    |   89 --
 DataStructures/SearchEngine.h                      |   96 +-
 DataStructures/SearchEngineData.cpp                |  105 +-
 DataStructures/SearchEngineData.h                  |   79 +-
 DataStructures/SegmentInformation.h                |   92 +-
 DataStructures/SharedMemoryFactory.h               |  370 +++++
 DataStructures/SharedMemoryVectorWrapper.h         |  156 ++
 DataStructures/SimpleStack.h                       |   71 -
 DataStructures/StaticGraph.h                       |  279 ++--
 DataStructures/StaticKDTree.h                      |  245 +--
 DataStructures/StaticRTree.h                       | 1557 +++++++++++---------
 DataStructures/TimingUtil.h                        |   50 -
 DataStructures/TurnInstructions.h                  |  132 +-
 DataStructures/XORFastHash.h                       |   84 +-
 DataStructures/XORFastHashStorage.h                |  107 +-
 Descriptors/BaseDescriptor.h                       |   94 +-
 Descriptors/DescriptionFactory.cpp                 |  253 +---
 Descriptors/DescriptionFactory.h                   |  233 ++-
 Descriptors/GPXDescriptor.h                        |  141 +-
 Descriptors/JSONDescriptor.h                       |  777 +++++-----
 Extractor/BaseParser.cpp                           |  187 +--
 Extractor/BaseParser.h                             |   82 +-
 Extractor/ExtractionContainers.cpp                 |  566 ++++---
 Extractor/ExtractionContainers.h                   |   96 +-
 Extractor/ExtractionHelperFunctions.h              |  122 +-
 Extractor/ExtractionWay.h                          |   79 +
 Extractor/ExtractorCallbacks.cpp                   |  255 ++--
 Extractor/ExtractorCallbacks.h                     |   86 +-
 Extractor/ExtractorStructs.h                       |  260 +---
 Extractor/InternalExtractorEdge.h                  |  120 ++
 Extractor/PBFParser.cpp                            | 1056 +++++++------
 Extractor/PBFParser.h                              |  119 +-
 Extractor/ScriptingEnvironment.cpp                 |  195 +--
 Extractor/ScriptingEnvironment.h                   |   70 +-
 Extractor/XMLParser.cpp                            |  583 ++++----
 Extractor/XMLParser.h                              |   68 +-
 Gemfile.lock                                       |   30 +-
 Include/osrm/Coordinate.h                          |  105 ++
 Include/osrm/Header.h                              |   53 +
 Include/osrm/Reply.h                               |   74 +
 Include/osrm/RouteParameters.h                     |   83 ++
 Include/osrm/ServerPaths.h                         |   38 +
 LICENCE.TXT                                        |  683 +--------
 Library/OSRM.h                                     |   52 +
 Library/OSRM_impl.cpp                              |  167 +++
 Library/OSRM_impl.h                                |   65 +
 Plugins/BasePlugin.h                               |   63 +-
 Plugins/DistanceTablePlugin.h                      |  146 ++
 Plugins/HelloWorldPlugin.h                         |  135 +-
 Plugins/LocatePlugin.h                             |  152 +-
 Plugins/NearestPlugin.h                            |  171 +--
 Plugins/PluginMapFactory.h                         |   34 -
 Plugins/RawRouteData.h                             |   45 -
 Plugins/RouteParameters.h                          |  107 --
 Plugins/TimestampPlugin.h                          |  106 +-
 Plugins/ViaRoutePlugin.h                           |  397 +++--
 README.TXT => README.md                            |   17 +-
 Rakefile                                           |   62 +-
 RoutingAlgorithms/AlternativePathRouting.h         | 1129 +++++++++-----
 RoutingAlgorithms/BasicRoutingInterface.h          |  512 +++++--
 RoutingAlgorithms/ManyToManyRouting.h              |  264 ++++
 RoutingAlgorithms/ShortestPathRouting.h            |  399 +++--
 Server/APIGrammar.h                                |   54 +-
 Server/BasicDatastructures.h                       |  157 --
 Server/Connection.cpp                              |  174 +++
 Server/Connection.h                                |  247 ++--
 Server/DataStructures/BaseDataFacade.h             |  125 ++
 Server/DataStructures/InternalDataFacade.h         |  430 ++++++
 Server/DataStructures/QueryObjectsStorage.cpp      |  100 --
 Server/DataStructures/QueryObjectsStorage.h        |   47 -
 Server/DataStructures/SharedBarriers.h             |   60 +
 Server/DataStructures/SharedDataFacade.h           |  398 +++++
 Server/DataStructures/SharedDataType.h             |  190 +++
 Server/Http/CompressionType.h                      |   41 +
 Server/Http/Reply.cpp                              |  123 ++
 Server/Http/Request.h                              |   48 +
 Server/RequestHandler.cpp                          |  142 ++
 Server/RequestHandler.h                            |  138 +-
 Server/RequestParser.cpp                           |  306 ++++
 Server/RequestParser.h                             |  345 +----
 Server/Server.h                                    |  166 ++-
 Server/ServerConfiguration.h                       |   28 -
 Server/ServerFactory.h                             |  107 +-
 Tools/componentAnalysis.cpp                        |  102 --
 Tools/components.cpp                               |  136 ++
 Tools/io-benchmark.cpp                             |  348 +++++
 Tools/simpleclient.cpp                             |  131 ++
 Tools/unlock_all_mutexes.cpp                       |   52 +
 Util/Azimuth.h                                     |   79 +-
 Util/BaseConfiguration.h                           |  107 --
 Util/BoostFileSystemFix.h                          |  147 ++
 Util/ComputeAngle.h                                |   57 +
 Util/ContainerUtils.h                              |   71 +-
 Util/DataStoreOptions.h                            |  284 ++++
 Util/FingerPrint.cpp.in                            |  106 ++
 Util/FingerPrint.h                                 |   60 +
 Util/GitDescription.cpp.in                         |   29 +
 Util/GitDescription.h                              |   33 +
 Util/GraphLoader.h                                 |  533 +++----
 Util/IniFileUtil.h                                 |   49 +
 Util/InputFileUtil.h                               |   46 -
 Util/LinuxStackTrace.h                             |  156 --
 Util/LuaUtil.h                                     |   81 +-
 Util/MachineInfo.h                                 |  109 +-
 Util/MercatorUtil.h                                |   43 +
 Util/OSRMException.h                               |   46 +
 Util/OpenMPWrapper.h                               |   34 -
 Util/ProgramOptions.h                              |  270 ++++
 Util/SimpleLogger.h                                |  158 ++
 Util/StdHashExtensions.h                           |   73 +
 Util/StringUtil.h                                  |  353 +++--
 Util/TimingUtil.h                                  |   39 +
 Util/TrigonometryTables.h                          |  790 ++++++++++
 appveyor.yml                                       |   67 +
 cmake/CheckCXXCompilerFlag.cmake                   |   29 +
 cmake/FindLua52.cmake                              |   82 ++
 cmake/FindLuaJIT.cmake                             |   93 ++
 cmake/FindLuabind.cmake                            |    4 +-
 cmake/FindSTXXL.cmake                              |    2 +-
 cmake/FindTBB.cmake                                |  283 ++++
 cmake/FingerPrint-Config.cmake                     |   10 +
 cmake/GetGitRevisionDescription.cmake.in           |   38 +
 cmake/cmake_options_script.py                      |   45 +
 cmake/pkgconfig.in                                 |   11 +
 config/cucumber.yml                                |    8 +-
 contractor.ini                                     |    1 -
 createHierarchy.cpp                                |  276 ----
 datastore.cpp                                      |  575 ++++++++
 extractor.cpp                                      |  339 +++--
 extractor.ini                                      |    2 -
 features/bicycle/access.feature                    |  322 ++--
 features/bicycle/access_node.feature               |  116 +-
 features/bicycle/area.feature                      |  186 +--
 features/bicycle/barrier.feature                   |   68 +-
 features/bicycle/cycleway.feature                  |  150 +-
 features/bicycle/destination.feature               |  134 +-
 features/bicycle/ferry.feature                     |  120 +-
 features/bicycle/maxspeed.feature                  |  130 +-
 features/bicycle/mode.feature                      |  146 +-
 features/bicycle/names.feature                     |   66 +-
 features/bicycle/oneway.feature                    |  252 ++--
 features/bicycle/pushing.feature                   |  200 +--
 features/bicycle/ref.feature                       |   76 +-
 features/bicycle/restrictions.feature              |  574 ++++----
 features/bicycle/roundabout.feature                |   30 +
 features/bicycle/stop_area.feature                 |   58 +-
 features/bicycle/surface.feature                   |   40 +
 features/bicycle/train.feature                     |   70 +-
 features/bicycle/turn_penalty.feature              |   42 +-
 features/bicycle/way.feature                       |   73 +-
 features/car/access.feature                        |  266 ++--
 features/car/barrier.feature                       |   66 +-
 features/car/destination.feature                   |  134 +-
 features/car/ferry.feature                         |   48 +-
 features/car/maxspeed.feature                      |  113 +-
 features/car/names.feature                         |   56 +-
 features/car/oneway.feature                        |  132 +-
 features/car/restrictions.feature                  |  561 +++----
 features/car/roundabout.feature                    |   30 +
 features/car/shuttle_train.feature                 |   52 +-
 features/car/speed.feature                         |   24 +
 features/car/way.feature                           |   58 +-
 features/foot/access.feature                       |   95 ++
 features/foot/access_node.feature                  |   50 +
 features/foot/area.feature                         |  103 ++
 features/foot/barrier.feature                      |   39 +
 features/foot/ferry.feature                        |   63 +
 features/foot/maxspeed.feature                     |   31 +-
 features/foot/names.feature                        |   33 +
 features/foot/oneway.feature                       |  110 +-
 features/foot/ref.feature                          |   41 +
 features/foot/restrictions.feature                 |  288 ++++
 features/foot/roundabout.feature                   |   34 +
 features/foot/surface.feature                      |   15 +
 features/foot/way.feature                          |   56 +-
 features/investigate/weird.feature                 |   42 -
 features/locate/locate.feature                     |  197 +++
 features/nearest/pick.feature                      |  128 +-
 features/nearest/projection.feature                |  184 +--
 features/options/extract/files.feature             |   30 +
 features/options/extract/help.feature              |   47 +
 features/options/extract/invalid.feature           |   12 +
 features/options/extract/version.feature           |   22 +
 features/options/prepare/files.feature             |   30 +
 features/options/prepare/help.feature              |   50 +
 features/options/prepare/invalid.feature           |   12 +
 features/options/prepare/version.feature           |   22 +
 features/options/routed/files.feature              |   27 +
 features/options/routed/help.feature               |   77 +
 features/options/routed/invalid.feature            |   19 +
 features/options/routed/version.feature            |   22 +
 features/step_definitions/data.rb                  |   59 +-
 .../step_definitions/{nearest.rb => locate.rb}     |   22 +-
 features/step_definitions/nearest.rb               |   12 +-
 features/step_definitions/options.rb               |   49 +
 features/step_definitions/requests.rb              |   25 +-
 features/step_definitions/routability.rb           |   99 +-
 features/step_definitions/routing.rb               |  153 +-
 features/stress/launch.feature                     |  102 +-
 features/support/config.rb                         |   18 -
 features/support/cucumber.rb                       |    6 +-
 features/support/data.rb                           |  160 +-
 features/support/env.rb                            |   41 +-
 features/support/exceptions.rb                     |   17 +-
 features/support/file.rb                           |   42 +-
 features/support/fuzzy.rb                          |   20 +-
 features/support/hash.rb                           |   16 +-
 features/support/hooks.rb                          |   21 +-
 features/support/launch.rb                         |   44 +-
 features/support/{nearest.rb => locate.rb}         |    8 +-
 features/support/log.rb                            |   35 +-
 features/support/nearest.rb                        |    2 +-
 features/support/osm_parser.rb                     |   18 +-
 features/support/route.rb                          |  129 +-
 features/support/run.rb                            |   18 +
 features/testbot/bad.feature                       |  144 +-
 features/testbot/basic.feature                     |  519 ++++---
 features/testbot/bearing.feature                   |  348 +++--
 features/testbot/bearing_param.feature             |  170 +--
 features/testbot/bug.feature                       |   23 -
 features/testbot/bugs.feature                      |    5 +
 features/testbot/distance.feature                  |  452 +++---
 features/testbot/duration.feature                  |   66 +-
 features/testbot/example.feature                   |   59 +-
 features/testbot/fastest.feature                   |   62 +-
 features/testbot/ferry.feature                     |  332 ++---
 features/testbot/fixed.feature                     |   26 +
 features/testbot/geometry.feature                  |   30 +
 features/testbot/graph.feature                     |   37 +-
 features/testbot/impedance.feature                 |  161 +-
 features/testbot/loop.feature                      |   78 +
 features/testbot/maxspeed.feature                  |   65 +-
 features/testbot/mode.feature                      |   40 +-
 features/testbot/oneway.feature                    |   44 +
 features/testbot/opposite.feature                  |   32 +-
 features/testbot/origin.feature                    |  128 +-
 features/testbot/overlap.feature                   |   39 +
 features/testbot/penalty.feature                   |  332 ++---
 features/testbot/planetary.feature                 |  168 +--
 features/testbot/projection.feature                |   38 +
 features/testbot/protobuffer.feature               |  156 ++
 features/testbot/roundabout.feature                |   76 +
 features/testbot/routes.feature                    |   58 +-
 features/testbot/snap.feature                      |  306 ++--
 features/testbot/speed.feature                     |   31 +
 features/testbot/status.feature                    |   67 +
 features/testbot/time.feature                      |  448 +++---
 features/testbot/turns.feature                     |  220 +--
 features/testbot/utf.feature                       |   34 +-
 features/testbot/via.feature                       |  124 +-
 features/timestamp/timestamp.feature               |   19 +-
 prepare.cpp                                        |  523 +++++++
 profile.lua                                        |    1 +
 profiles/bicycle.lua                               |  575 ++++----
 profiles/car.lua                                   |  289 ++--
 profiles/examples/postgis.lua                      |   82 ++
 profiles/foot.lua                                  |  312 ++--
 profiles/testbot.lua                               |  181 +--
 routed.cpp                                         |  270 ++--
 server.ini                                         |   11 -
 test/contractor.ini                                |    1 -
 test/extractor.ini                                 |    1 -
 typedefs.h                                         |   82 +-
 win/createHierarchy.vcproj                         |  459 ------
 win/extractor.vcproj                               |  532 -------
 win/getopt.c                                       | 1260 ----------------
 win/getopt.h                                       |  189 ---
 win/osrm.sln                                       |   29 -
 win/osrm.vsprops                                   |   39 -
 win/routed.vcproj                                  |  459 ------
 win/unistd.h                                       |   30 -
 330 files changed, 31598 insertions(+), 21819 deletions(-)

diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..f5577f5
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,54 @@
+---
+Language:        Cpp
+# BasedOnStyle:  LLVM
+AccessModifierOffset: -2
+ConstructorInitializerIndentWidth: 4
+AlignEscapedNewlinesLeft: false
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: true
+AlwaysBreakTemplateDeclarations: false
+AlwaysBreakBeforeMultilineStrings: false
+BreakBeforeBinaryOperators: false
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BinPackParameters: false
+ColumnLimit:     100
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+DerivePointerBinding: false
+ExperimentalAutoDetectBinPacking: false
+IndentCaseLabels: false
+MaxEmptyLinesToKeep: 1
+KeepEmptyLinesAtTheStartOfBlocks: true
+NamespaceIndentation: None
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakString: 1000
+PenaltyBreakFirstLessLess: 120
+PenaltyExcessCharacter: 1000
+PenaltyReturnTypeOnItsOwnLine: 60
+PointerBindsToType: false
+SpacesBeforeTrailingComments: 1
+Cpp11BracedListStyle: true
+Standard:        Cpp11
+IndentWidth:     4
+TabWidth:        8
+UseTab:          Never
+BreakBeforeBraces: Allman
+IndentFunctionDeclarationAfterType: false
+SpacesInParentheses: false
+SpacesInAngles:  false
+SpaceInEmptyParentheses: false
+SpacesInCStyleCastParentheses: false
+SpacesInContainerLiterals: true
+SpaceBeforeAssignmentOperators: true
+ContinuationIndentWidth: 4
+CommentPragmas:  '^ IWYU pragma:'
+ForEachMacros:   [ foreach, Q_FOREACH, BOOST_FOREACH ]
+SpaceBeforeParens: ControlStatements
+...
+
diff --git a/.gitignore b/.gitignore
index 2e6107a..5642924 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,6 +36,8 @@ Thumbs.db
 # build related files #
 #######################
 /build/
+/Util/FingerPrint.cpp
+/Util/GitDescription.cpp
 
 # Eclipse related files #
 #########################
@@ -70,8 +72,13 @@ stxxl.errlog
 /win/bin/
 /win/bin-debug/
 /osrm-extract
+/osrm-io-benchmark
+/osrm-components
 /osrm-routed
+/osrm-datastore
 /osrm-prepare
+/osrm-unlock-all
+/osrm-cli
 /nohup.out
 
 # Sandbox folder #
@@ -79,4 +86,7 @@ stxxl.errlog
 /sandbox/
 
 /test/profile.lua
-/profile.lua
+
+# Deprecated config file #
+##########################
+/server.ini
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..8817e38
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,54 @@
+language: cpp
+compiler:
+  - gcc
+#  - clang
+# Make sure CMake is installed
+install:
+ - sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
+ - sudo add-apt-repository -y ppa:boost-latest/ppa
+ - sudo apt-get update >/dev/null
+ - sudo apt-get -q install libprotoc-dev libprotobuf7 libprotobuf-dev libosmpbf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev lua5.1 liblua5.1-0-dev rubygems libtbb-dev
+ - sudo apt-get -q install g++-4.7
+ - sudo apt-get install libboost1.54-all-dev
+ #luabind
+ - curl https://gist.githubusercontent.com/DennisOSRM/f2eb7b948e6fe1ae319e/raw/install-luabind.sh | sudo bash
+ #osmosis
+ - curl -s https://gist.githubusercontent.com/DennisOSRM/803a64a9178ec375069f/raw/ | sudo bash
+before_script:
+ - rvm use 1.9.3
+ - gem install bundler
+ - bundle install
+ - mkdir build
+ - cd build
+ - cmake .. $CMAKEOPTIONS
+script:
+ - make -j 2
+ - cd ..
+ - cucumber -p verify
+after_script:
+# - cd ..
+# - cucumber -p verify
+branches:
+  only:
+    - master
+    - develop
+cache:
+- bundler
+- apt
+env:
+ - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-4.7" OSRM_PORT=5000 OSRM_TIMEOUT=60
+ - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++-4.7" OSRM_PORT=5010 OSRM_TIMEOUT=60
+notifications:
+ irc:
+  channels:
+    - irc.oftc.net#osrm
+  on_success: change
+  on_failure: always
+  use_notice: true
+  skip_join: false
+
+  recipients:
+    - dennis at mapbox.com
+  email:
+    on_success: change
+    on_failure: always
diff --git a/AUTHORS.TXT b/AUTHORS.TXT
deleted file mode 100644
index 8268ebd..0000000
--- a/AUTHORS.TXT
+++ /dev/null
@@ -1,11 +0,0 @@
-The following people contributed code to the Open Source Routing Machine:
-
-Christian Vetter 
-Dennis Luxen
-Ruslan Krenzler
-Frederik Ramm
-Bharath Vissapragada
-Pascal Neis
-Sasa Ivetic
-Emil Tin
-Henning Moll
diff --git a/Algorithms/BFSComponentExplorer.h b/Algorithms/BFSComponentExplorer.h
new file mode 100644
index 0000000..7bc7ecb
--- /dev/null
+++ b/Algorithms/BFSComponentExplorer.h
@@ -0,0 +1,148 @@
+#ifndef __BFS_COMPONENT_EXPLORER_H__
+#define __BFS_COMPONENT_EXPLORER_H__
+
+#include "../typedefs.h"
+#include "../DataStructures/DynamicGraph.h"
+#include "../DataStructures/RestrictionMap.h"
+
+#include <queue>
+#include <unordered_set>
+
+// Explores the components of the given graph while respecting turn restrictions
+// and barriers.
+template <typename GraphT> class BFSComponentExplorer
+{
+  public:
+    BFSComponentExplorer(const GraphT &dynamicGraph,
+                         const RestrictionMap &restrictions,
+                         const std::unordered_set<NodeID> &barrier_nodes)
+        : m_graph(dynamicGraph), m_restriction_map(restrictions), m_barrier_nodes(barrier_nodes)
+    {
+        BOOST_ASSERT(m_graph.GetNumberOfNodes() > 0);
+    }
+
+    /*!
+     * Returns the size of the component that the node belongs to.
+     */
+    inline unsigned int GetComponentSize(NodeID node)
+    {
+        BOOST_ASSERT(node < m_component_index_list.size());
+
+        return m_component_index_size[m_component_index_list[node]];
+    }
+
+    inline unsigned int GetNumberOfComponents() { return m_component_index_size.size(); }
+
+    /*!
+     * Computes the component sizes.
+     */
+    void run()
+    {
+        std::queue<std::pair<NodeID, NodeID>> bfs_queue;
+        unsigned current_component = 0;
+
+        BOOST_ASSERT(m_component_index_list.empty());
+        BOOST_ASSERT(m_component_index_size.empty());
+
+        unsigned num_nodes = m_graph.GetNumberOfNodes();
+
+        m_component_index_list.resize(num_nodes, std::numeric_limits<unsigned>::max());
+
+        BOOST_ASSERT(num_nodes > 0);
+
+        // put unexplorered node with parent pointer into queue
+        for (NodeID node = 0; node < num_nodes; ++node)
+        {
+            if (std::numeric_limits<unsigned>::max() == m_component_index_list[node])
+            {
+                unsigned size = ExploreComponent(bfs_queue, node, current_component);
+
+                // push size into vector
+                m_component_index_size.emplace_back(size);
+                ++current_component;
+            }
+        }
+    }
+
+  private:
+    /*!
+     * Explores the current component that starts at node using BFS.
+     */
+    inline unsigned ExploreComponent(std::queue<std::pair<NodeID, NodeID>> &bfs_queue,
+                                     NodeID node,
+                                     unsigned current_component)
+    {
+        /*
+           Graphical representation of variables:
+
+           u           v           w
+           *---------->*---------->*
+                            e2
+        */
+
+        bfs_queue.emplace(node, node);
+        // mark node as read
+        m_component_index_list[node] = current_component;
+
+        unsigned current_component_size = 1;
+
+        while (!bfs_queue.empty())
+        {
+            // fetch element from BFS queue
+            std::pair<NodeID, NodeID> current_queue_item = bfs_queue.front();
+            bfs_queue.pop();
+
+            const NodeID v = current_queue_item.first; // current node
+            const NodeID u = current_queue_item.second; // parent
+            // increment size counter of current component
+            ++current_component_size;
+            const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
+            if (!is_barrier_node)
+            {
+                const NodeID to_node_of_only_restriction =
+                    m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
+
+                for (auto e2 : m_graph.GetAdjacentEdgeRange(v))
+                {
+                    const NodeID w = m_graph.GetTarget(e2);
+
+                    if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
+                        w != to_node_of_only_restriction)
+                    {
+                        // At an only_-restriction but not at the right turn
+                        continue;
+                    }
+
+                    if (u != w)
+                    {
+                        // only add an edge if turn is not a U-turn except
+                        // when it is at the end of a dead-end street.
+                        if (!m_restriction_map.CheckIfTurnIsRestricted(u, v, w))
+                        {
+                            // only add an edge if turn is not prohibited
+                            if (std::numeric_limits<unsigned>::max() == m_component_index_list[w])
+                            {
+                                // insert next (node, parent) only if w has
+                                // not yet been explored
+                                // mark node as read
+                                m_component_index_list[w] = current_component;
+                                bfs_queue.emplace(w, v);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return current_component_size;
+    }
+
+    std::vector<unsigned> m_component_index_list;
+    std::vector<NodeID> m_component_index_size;
+
+    const GraphT &m_graph;
+    const RestrictionMap &m_restriction_map;
+    const std::unordered_set<NodeID> &m_barrier_nodes;
+};
+
+#endif
diff --git a/Algorithms/Bresenham.h b/Algorithms/Bresenham.h
deleted file mode 100644
index a4f7e61..0000000
--- a/Algorithms/Bresenham.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef BRESENHAM_H_
-#define BRESENHAM_H_
-
-#include <cmath>
-#include <vector>
-typedef std::pair<unsigned, unsigned> BresenhamPixel;
-
-inline void Bresenham (int x0, int y0, int x1, int y1, std::vector<BresenhamPixel> &resultList) {
-    int dx = std::abs(x1-x0);
-    int dy = std::abs(y1-y0);
-    int sx = (x0 < x1 ? 1 : -1);
-    int sy = (y0 < y1 ? 1 : -1);
-    int err = dx - dy;
-    while(true) {
-        resultList.push_back(std::make_pair(x0,y0));
-        if(x0 == x1 && y0 == y1) break;
-        int e2 = 2* err;
-        if ( e2 > -dy) {
-            err -= dy;
-            x0 += sx;
-        }
-        if(e2 < dx) {
-            err+= dx;
-            y0 += sy;
-        }
-    }
-}
-
-#endif /* BRESENHAM_H_ */
diff --git a/Algorithms/CRC32.cpp b/Algorithms/CRC32.cpp
deleted file mode 100644
index d2f821c..0000000
--- a/Algorithms/CRC32.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
-
- 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.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#include "CRC32.h"
-
-CRC32::CRC32() : crc(0) {
-    crcFunction = detectBestCRC32C();
-}
-
-unsigned CRC32::SoftwareBasedCRC32(char *str, unsigned len, unsigned ) {
-    boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_Processor;
-    CRC32_Processor.process_bytes( str, len);
-    return CRC32_Processor.checksum();
-}
-
-unsigned CRC32::SSEBasedCRC32( char *str, unsigned len, unsigned crc) {
-    unsigned q=len/sizeof(unsigned),
-            r=len%sizeof(unsigned),
-            *p=(unsigned*)str/*, crc*/;
-
-    //crc=0;
-    while (q--) {
-        __asm__ __volatile__(
-                ".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
-                :"=S"(crc)
-                 :"0"(crc), "c"(*p)
-        );
-        ++p;
-    }
-
-    str=(char*)p;
-    while (r--) {
-        __asm__ __volatile__(
-                ".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
-                :"=S"(crc)
-                 :"0"(crc), "c"(*str)
-        );
-        ++str;
-    }
-    return crc;
-}
-
-CRC32::CRC32CFunctionPtr CRC32::detectBestCRC32C() {
-    static const int SSE42_BIT = 20;
-    unsigned ecx = cpuid(1);
-    bool hasSSE42 = ecx & (1 << SSE42_BIT);
-    if (hasSSE42) {
-        std::cout << "using hardware base sse computation" << std::endl;
-        return &CRC32::SSEBasedCRC32; //crc32 hardware accelarated;
-    } else {
-        std::cout << "using software base sse computation" << std::endl;
-        return &CRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
-    }
-}
-
-unsigned CRC32::cpuid(unsigned functionInput) {
-    unsigned eax;
-    unsigned ebx;
-    unsigned ecx;
-    unsigned edx;
-    asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (functionInput));
-    return ecx;
-}
-
-unsigned CRC32::operator()(char *str, unsigned len){
-    crc =((*this).*(crcFunction))(str, len, crc);
-    return crc;
-}
diff --git a/Algorithms/CRC32.h b/Algorithms/CRC32.h
deleted file mode 100644
index 6321030..0000000
--- a/Algorithms/CRC32.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
-
- 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.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef CRC32_H_
-#define CRC32_H_
-
-#include <boost/crc.hpp>  // for boost::crc_32_type
-#include <iostream>
-
-class CRC32 {
-private:
-    unsigned crc;
-
-    typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
-    typedef unsigned (CRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
-
-    unsigned SoftwareBasedCRC32(char *str, unsigned len, unsigned crc);
-    unsigned SSEBasedCRC32( char *str, unsigned len, unsigned crc);
-    unsigned cpuid(unsigned functionInput);
-    CRC32CFunctionPtr detectBestCRC32C();
-    CRC32CFunctionPtr crcFunction;
-public:
-    CRC32();
-    unsigned operator()(char *str, unsigned len);
-    virtual ~CRC32() {};
-};
-
-#endif /* CRC32_H_ */
diff --git a/Algorithms/DouglasPeucker.cpp b/Algorithms/DouglasPeucker.cpp
new file mode 100644
index 0000000..2e647fc
--- /dev/null
+++ b/Algorithms/DouglasPeucker.cpp
@@ -0,0 +1,183 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <osrm/Coordinate.h>
+
+#include "DouglasPeucker.h"
+#include "../DataStructures/SegmentInformation.h"
+#include "../Util/SimpleLogger.h"
+
+#include <boost/assert.hpp>
+
+#include <cmath>
+
+#include <algorithm>
+
+struct CoordinatePairCalculator
+{
+    CoordinatePairCalculator() = delete;
+    CoordinatePairCalculator(const FixedPointCoordinate &coordinate_a,
+                             const FixedPointCoordinate &coordinate_b)
+    {
+        // initialize distance calculator with two fixed coordinates a, b
+        const float RAD = 0.017453292519943295769236907684886f;
+        first_lat = (coordinate_a.lat / COORDINATE_PRECISION) * RAD;
+        first_lon = (coordinate_a.lon / COORDINATE_PRECISION) * RAD;
+        second_lat = (coordinate_b.lat / COORDINATE_PRECISION) * RAD;
+        second_lon = (coordinate_b.lon / COORDINATE_PRECISION) * RAD;
+    }
+
+    int operator()(FixedPointCoordinate &other) const
+    {
+        // set third coordinate c
+        const float RAD = 0.017453292519943295769236907684886f;
+        const float earth_radius = 6372797.560856f;
+        const float float_lat1 = (other.lat / COORDINATE_PRECISION) * RAD;
+        const float float_lon1 = (other.lon / COORDINATE_PRECISION) * RAD;
+
+        // compute distance (a,c)
+        const float x_value_1 = (first_lon - float_lon1) * cos((float_lat1 + first_lat) / 2.f);
+        const float y_value_1 = first_lat - float_lat1;
+        const float dist1 = sqrt(std::pow(x_value_1, 2) + std::pow(y_value_1, 2)) * earth_radius;
+
+        // compute distance (b,c)
+        const float x_value_2 = (second_lon - float_lon1) * cos((float_lat1 + second_lat) / 2.f);
+        const float y_value_2 = second_lat - float_lat1;
+        const float dist2 = sqrt(std::pow(x_value_2, 2) + std::pow(y_value_2, 2)) * earth_radius;
+
+        // return the minimum
+        return static_cast<int>(std::min(dist1, dist2));
+    }
+
+    float first_lat;
+    float first_lon;
+    float second_lat;
+    float second_lon;
+};
+
+DouglasPeucker::DouglasPeucker()
+    : douglas_peucker_thresholds({512440, // z0
+                                  256720, // z1
+                                  122560, // z2
+                                  56780,  // z3
+                                  28800,  // z4
+                                  14400,  // z5
+                                  7200,   // z6
+                                  3200,   // z7
+                                  2400,   // z8
+                                  1000,   // z9
+                                  600,    // z10
+                                  120,    // z11
+                                  60,     // z12
+                                  45,     // z13
+                                  36,     // z14
+                                  20,     // z15
+                                  8,      // z16
+                                  6,      // z17
+                                  4       // z18
+      })
+{
+}
+
+void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level)
+{
+    // check if input data is invalid
+    BOOST_ASSERT_MSG(!input_geometry.empty(), "geometry invalid");
+
+    if (input_geometry.size() < 2)
+    {
+        return;
+    }
+
+    input_geometry.front().necessary = true;
+    input_geometry.back().necessary = true;
+
+    {
+        BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level");
+        unsigned left_border = 0;
+        unsigned right_border = 1;
+        // Sweep over array and identify those ranges that need to be checked
+        do
+        {
+            // traverse list until new border element found
+            if (input_geometry[right_border].necessary)
+            {
+                // sanity checks
+                BOOST_ASSERT(input_geometry[left_border].necessary);
+                BOOST_ASSERT(input_geometry[right_border].necessary);
+                recursion_stack.emplace(left_border, right_border);
+                left_border = right_border;
+            }
+            ++right_border;
+        } while (right_border < input_geometry.size());
+    }
+
+    // mark locations as 'necessary' by divide-and-conquer
+    while (!recursion_stack.empty())
+    {
+        // pop next element
+        const GeometryRange pair = recursion_stack.top();
+        recursion_stack.pop();
+        // sanity checks
+        BOOST_ASSERT_MSG(input_geometry[pair.first].necessary, "left border mus be necessary");
+        BOOST_ASSERT_MSG(input_geometry[pair.second].necessary, "right border must be necessary");
+        BOOST_ASSERT_MSG(pair.second < input_geometry.size(), "right border outside of geometry");
+        BOOST_ASSERT_MSG(pair.first < pair.second, "left border on the wrong side");
+
+        int max_int_distance = 0;
+        unsigned farthest_entry_index = pair.second;
+        const CoordinatePairCalculator DistCalc(input_geometry[pair.first].location,
+                                                input_geometry[pair.second].location);
+
+        // sweep over range to find the maximum
+        for (unsigned i = pair.first + 1; i < pair.second; ++i)
+        {
+            const int distance = DistCalc(input_geometry[i].location);
+            // found new feasible maximum?
+            if (distance > max_int_distance && distance > douglas_peucker_thresholds[zoom_level])
+            {
+                farthest_entry_index = i;
+                max_int_distance = distance;
+            }
+        }
+
+        // check if maximum violates a zoom level dependent threshold
+        if (max_int_distance > douglas_peucker_thresholds[zoom_level])
+        {
+            //  mark idx as necessary
+            input_geometry[farthest_entry_index].necessary = true;
+            if (1 < (farthest_entry_index - pair.first))
+            {
+                recursion_stack.emplace(pair.first, farthest_entry_index);
+            }
+            if (1 < (pair.second - farthest_entry_index))
+            {
+                recursion_stack.emplace(farthest_entry_index, pair.second);
+            }
+        }
+    }
+}
diff --git a/Algorithms/DouglasPeucker.h b/Algorithms/DouglasPeucker.h
index 47b0ce9..d0f295c 100644
--- a/Algorithms/DouglasPeucker.h
+++ b/Algorithms/DouglasPeucker.h
@@ -1,129 +1,58 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef DOUGLASPEUCKER_H_
 #define DOUGLASPEUCKER_H_
 
-#include <cassert>
-#include <cmath>
-#include <cfloat>
 #include <stack>
+#include <utility>
+#include <vector>
 
-#include "../DataStructures/Coordinate.h"
-
-/*This class object computes the bitvector of indicating generalized input points
- * according to the (Ramer-)Douglas-Peucker algorithm.
+/* This class object computes the bitvector of indicating generalized input
+ * points according to the (Ramer-)Douglas-Peucker algorithm.
  *
- * Input is vector of pairs. Each pair consists of the point information and a bit
- * indicating if the points is present in the generalization.
+ * Input is vector of pairs. Each pair consists of the point information and a
+ * bit indicating if the points is present in the generalization.
  * Note: points may also be pre-selected*/
 
-//These thresholds are more or less heuristically chosen.
-//                                                  0          1         2         3         4          5         6         7       8       9       10     11       12     13    14   15  16  17   18
-static double DouglasPeuckerThresholds[19] = { 32000000., 16240000., 80240000., 40240000., 20000000., 10000000., 500000., 240000., 120000., 60000., 30000., 19000., 5000., 2000., 200, 16,  6, 3. , 3. };
-
-template<class PointT>
-class DouglasPeucker {
-private:
-    typedef std::pair<std::size_t, std::size_t> PairOfPoints;
-    //Stack to simulate the recursion
-    std::stack<PairOfPoints > recursionStack;
-
-    /**
-     * This distance computation does integer arithmetic only and is about twice as fast as
-     * the other distance function. It is an approximation only, but works more or less ok.
-     */
-    template<class CoordT>
-    inline int fastDistance(const CoordT& point, const CoordT& segA, const CoordT& segB) const {
-        const int p2x = (segB.lon - segA.lat);
-        const int p2y = (segB.lon - segA.lat);
-        const int something = p2x*p2x + p2y*p2y;
-        int u = (something < FLT_EPSILON ? 0 : ((point.lon - segA.lon) * p2x + (point.lat - segA.lat) * p2y) / something);
-
-        if (u > 1)
-            u = 1;
-        else if (u < 0)
-            u = 0;
-
-        const int x = segA.lon + u * p2x;
-        const int y = segA.lat + u * p2y;
-
-        const int dx = x - point.lon;
-        const int dy = y - point.lat;
-
-        const int dist = (dx*dx + dy*dy);
-
-        return dist;
-    }
-
+struct SegmentInformation;
 
-public:
-    void Run(std::vector<PointT> & inputVector, const unsigned zoomLevel) {
-        {
-            assert(zoomLevel < 19);
-            assert(1 < inputVector.size());
-            std::size_t leftBorderOfRange = 0;
-            std::size_t rightBorderOfRange = 1;
-            //Sweep linerarily over array and identify those ranges that need to be checked
-//            recursionStack.hint(inputVector.size());
-            do {
-                assert(inputVector[leftBorderOfRange].necessary);
-                assert(inputVector.back().necessary);
+class DouglasPeucker
+{
+  private:
+    std::vector<int> douglas_peucker_thresholds;
 
-                if(inputVector[rightBorderOfRange].necessary) {
-                    recursionStack.push(std::make_pair(leftBorderOfRange, rightBorderOfRange));
-                    leftBorderOfRange = rightBorderOfRange;
-                }
-                ++rightBorderOfRange;
-            } while( rightBorderOfRange < inputVector.size());
-        }
-        while(!recursionStack.empty()) {
-            //pop next element
-            const PairOfPoints pair = recursionStack.top();
-            recursionStack.pop();
-            assert(inputVector[pair.first].necessary);
-            assert(inputVector[pair.second].necessary);
-            assert(pair.second < inputVector.size());
-            assert(pair.first < pair.second);
-            int maxDistance = INT_MIN;
+    typedef std::pair<unsigned, unsigned> GeometryRange;
+    // Stack to simulate the recursion
+    std::stack<GeometryRange> recursion_stack;
 
-            std::size_t indexOfFarthestElement = pair.second;
-            //find index idx of element with maxDistance
-            for(std::size_t i = pair.first+1; i < pair.second; ++i){
-                const double distance = std::fabs(fastDistance(inputVector[i].location, inputVector[pair.first].location, inputVector[pair.second].location));
-                if(distance > DouglasPeuckerThresholds[zoomLevel] && distance > maxDistance) {
-                    indexOfFarthestElement = i;
-                    maxDistance = distance;
-                }
-            }
-            if (maxDistance > DouglasPeuckerThresholds[zoomLevel]) {
-                //  mark idx as necessary
-                inputVector[indexOfFarthestElement].necessary = true;
-                if (1 < indexOfFarthestElement - pair.first) {
-                    recursionStack.push(std::make_pair(pair.first, indexOfFarthestElement) );
-                }
-                if (1 < pair.second - indexOfFarthestElement)
-                    recursionStack.push(std::make_pair(indexOfFarthestElement, pair.second) );
-            }
-        }
-    }
+  public:
+    DouglasPeucker();
+    void Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level);
 };
 
 #endif /* DOUGLASPEUCKER_H_ */
diff --git a/Algorithms/ExtractRouteNames.h b/Algorithms/ExtractRouteNames.h
new file mode 100644
index 0000000..5c1b860
--- /dev/null
+++ b/Algorithms/ExtractRouteNames.h
@@ -0,0 +1,169 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef EXTRACT_ROUTE_NAMES_H
+#define EXTRACT_ROUTE_NAMES_H
+
+#include <boost/assert.hpp>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+struct RouteNames
+{
+    std::string shortest_path_name_1;
+    std::string shortest_path_name_2;
+    std::string alternative_path_name_1;
+    std::string alternative_path_name_2;
+};
+
+// construct routes names
+template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
+{
+  private:
+    SegmentT PickNextLongestSegment(const std::vector<SegmentT> &segment_list,
+                                    const unsigned blocked_name_id) const
+    {
+        SegmentT result_segment;
+        result_segment.length = 0;
+
+        for (const SegmentT &segment : segment_list)
+        {
+            if (segment.name_id != blocked_name_id && segment.length > result_segment.length)
+            {
+                result_segment = segment;
+            }
+        }
+        return result_segment;
+    }
+
+  public:
+    RouteNames operator()(std::vector<SegmentT> &shortest_path_segments,
+                          std::vector<SegmentT> &alternative_path_segments,
+                          const DataFacadeT *facade) const
+    {
+        RouteNames route_names;
+
+        SegmentT shortest_segment_1, shortest_segment_2;
+        SegmentT alternative_segment_1, alternative_segment_2;
+
+        auto length_comperator = [](const SegmentT &a, const SegmentT &b)
+        { return a.length > b.length; };
+        auto name_id_comperator = [](const SegmentT &a, const SegmentT &b)
+        { return a.name_id < b.name_id; };
+
+        if (shortest_path_segments.empty())
+        {
+            return route_names;
+        }
+
+        // pick the longest segment for the shortest path.
+        std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), length_comperator);
+        shortest_segment_1 = shortest_path_segments[0];
+        if (!alternative_path_segments.empty())
+        {
+            std::sort(alternative_path_segments.begin(),
+                      alternative_path_segments.end(),
+                      length_comperator);
+
+            // also pick the longest segment for the alternative path
+            alternative_segment_1 = alternative_path_segments[0];
+        }
+
+        // compute the set difference (for shortest path) depending on names between shortest and
+        // alternative
+        std::vector<SegmentT> shortest_path_set_difference(shortest_path_segments.size());
+        std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), name_id_comperator);
+        std::sort(alternative_path_segments.begin(), alternative_path_segments.end(), name_id_comperator);
+        std::set_difference(shortest_path_segments.begin(),
+                            shortest_path_segments.end(),
+                            alternative_path_segments.begin(),
+                            alternative_path_segments.end(),
+                            shortest_path_set_difference.begin(),
+                            name_id_comperator);
+
+        std::sort(shortest_path_set_difference.begin(),
+                  shortest_path_set_difference.end(),
+                  length_comperator);
+        shortest_segment_2 =
+            PickNextLongestSegment(shortest_path_set_difference, shortest_path_segments[0].name_id);
+
+        // compute the set difference (for alternative path) depending on names between shortest and
+        // alternative
+        // vectors are still sorted, no need to do again
+        BOOST_ASSERT(std::is_sorted(shortest_path_segments.begin(),
+                                    shortest_path_segments.end(),
+                                    name_id_comperator));
+        BOOST_ASSERT(std::is_sorted(alternative_path_segments.begin(),
+                                    alternative_path_segments.end(),
+                                    name_id_comperator));
+
+        std::vector<SegmentT> alternative_path_set_difference(alternative_path_segments.size());
+        std::set_difference(alternative_path_segments.begin(),
+                            alternative_path_segments.end(),
+                            shortest_path_segments.begin(),
+                            shortest_path_segments.end(),
+                            alternative_path_set_difference.begin(),
+                            name_id_comperator);
+
+        std::sort(alternative_path_set_difference.begin(),
+                  alternative_path_set_difference.end(),
+                  length_comperator);
+
+        if (!alternative_path_segments.empty())
+        {
+            alternative_segment_2 = PickNextLongestSegment(alternative_path_set_difference,
+                                                       alternative_path_segments[0].name_id);
+        }
+
+        // move the segments into the order in which they occur.
+        if (shortest_segment_1.position > shortest_segment_2.position)
+        {
+            std::swap(shortest_segment_1, shortest_segment_2);
+        }
+        if (alternative_segment_1.position > alternative_segment_2.position)
+        {
+            std::swap(alternative_segment_1, alternative_segment_2);
+        }
+
+        // fetching names for the selected segments
+        route_names.shortest_path_name_1 =
+            facade->GetEscapedNameForNameID(shortest_segment_1.name_id);
+        route_names.shortest_path_name_2 =
+            facade->GetEscapedNameForNameID(shortest_segment_2.name_id);
+
+        route_names.alternative_path_name_1 =
+            facade->GetEscapedNameForNameID(alternative_segment_1.name_id);
+        route_names.alternative_path_name_2 =
+            facade->GetEscapedNameForNameID(alternative_segment_2.name_id);
+
+        return route_names;
+    }
+};
+
+#endif // EXTRACT_ROUTE_NAMES_H
diff --git a/Algorithms/IteratorBasedCRC32.h b/Algorithms/IteratorBasedCRC32.h
index 5d4415c..84a404a 100644
--- a/Algorithms/IteratorBasedCRC32.h
+++ b/Algorithms/IteratorBasedCRC32.h
@@ -1,109 +1,144 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#ifndef ITERATORBASEDCRC32_H_
-#define ITERATORBASEDCRC32_H_
+*/
+
+#ifndef ITERATOR_BASED_CRC32_H
+#define ITERATOR_BASED_CRC32_H
+
+#include "../Util/SimpleLogger.h"
 
-#include <boost/crc.hpp>  // for boost::crc_32_type
 #include <iostream>
 
-template<class ContainerT>
-class IteratorbasedCRC32 {
-private:
-    typedef typename ContainerT::iterator ContainerT_iterator;
+#if defined(__x86_64__) && !defined(__MINGW64__)
+#include <cpuid.h>
+#else
+#include <boost/crc.hpp> // for boost::crc_32_type
+
+inline void __get_cpuid(int param, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx)
+{
+    *ecx = 0;
+}
+#endif
+
+template <class ContainerT> class IteratorbasedCRC32
+{
+  private:
+    typedef typename ContainerT::iterator IteratorType;
     unsigned crc;
 
-    typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
-    typedef unsigned (IteratorbasedCRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
-
-    unsigned SoftwareBasedCRC32(char *str, unsigned len, unsigned ){
-        boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_Processor;
-        CRC32_Processor.process_bytes( str, len);
-        return CRC32_Processor.checksum();
+    bool use_SSE42_CRC_function;
+
+#if !defined(__x86_64__)
+    boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_processor;
+#endif
+    unsigned SoftwareBasedCRC32(char *str, unsigned len)
+    {
+#if !defined(__x86_64__)
+        CRC32_processor.process_bytes(str, len);
+        return CRC32_processor.checksum();
+#else
+        return 0;
+#endif
     }
-    unsigned SSEBasedCRC32( char *str, unsigned len, unsigned crc){
-        unsigned q=len/sizeof(unsigned),
-                r=len%sizeof(unsigned),
-                *p=(unsigned*)str/*, crc*/;
-
-        //crc=0;
-        while (q--) {
-            __asm__ __volatile__(
-                    ".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
-                    :"=S"(crc)
-                     :"0"(crc), "c"(*p)
-            );
+
+    // adapted from http://byteworm.com/2010/10/13/crc32/
+    unsigned SSE42BasedCRC32(char *str, unsigned len)
+    {
+#if defined(__x86_64__)
+        unsigned q = len / sizeof(unsigned);
+        unsigned r = len % sizeof(unsigned);
+        unsigned *p = (unsigned *)str;
+
+        // crc=0;
+        while (q--)
+        {
+            __asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
+                                 : "=S"(crc)
+                                 : "0"(crc), "c"(*p));
             ++p;
         }
 
-        str=(char*)p;
-        while (r--) {
-            __asm__ __volatile__(
-                    ".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
-                    :"=S"(crc)
-                     :"0"(crc), "c"(*str)
-            );
+        str = (char *)p;
+        while (r--)
+        {
+            __asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
+                                 : "=S"(crc)
+                                 : "0"(crc), "c"(*str));
             ++str;
         }
+#endif
         return crc;
     }
 
-    unsigned cpuid(unsigned functionInput){
-        unsigned eax;
-        unsigned ebx;
-        unsigned ecx;
-        unsigned edx;
-        asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (functionInput));
+    inline unsigned cpuid() const
+    {
+        unsigned eax = 0, ebx = 0, ecx = 0, edx = 0;
+        // on X64 this calls hardware cpuid(.) instr. otherwise a dummy impl.
+        __get_cpuid(1, &eax, &ebx, &ecx, &edx);
         return ecx;
     }
 
-    CRC32CFunctionPtr detectBestCRC32C(){
-        static const int SSE42_BIT = 20;
-        unsigned ecx = cpuid(1);
-        bool hasSSE42 = ecx & (1 << SSE42_BIT);
-        if (hasSSE42) {
-            std::cout << "using hardware base sse computation" << std::endl;
-            return &IteratorbasedCRC32::SSEBasedCRC32; //crc32 hardware accelarated;
-        } else {
-            std::cout << "using software base sse computation" << std::endl;
-            return &IteratorbasedCRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
+    bool DetectNativeCRC32Support()
+    {
+        static const int SSE42_BIT = 0x00100000;
+        const unsigned ecx = cpuid();
+        const bool has_SSE42 = (ecx & SSE42_BIT) != 0;
+        if (has_SSE42)
+        {
+            SimpleLogger().Write() << "using hardware based CRC32 computation";
         }
-    }
-    CRC32CFunctionPtr crcFunction;
-public:
-    IteratorbasedCRC32(): crc(0) {
-        crcFunction = detectBestCRC32C();
+        else
+        {
+            SimpleLogger().Write() << "using software based CRC32 computation";
+        }
+        return has_SSE42;
     }
 
-    virtual ~IteratorbasedCRC32() {};
+  public:
+    IteratorbasedCRC32() : crc(0) { use_SSE42_CRC_function = DetectNativeCRC32Support(); }
 
-    unsigned operator()( ContainerT_iterator iter, const ContainerT_iterator end) {
+    unsigned operator()(IteratorType iter, const IteratorType end)
+    {
         unsigned crc = 0;
-        while(iter != end) {
-            char * data = reinterpret_cast<char*>(&(*iter) );
-            crc =((*this).*(crcFunction))(data, sizeof(typename ContainerT::value_type*), crc);
+        while (iter != end)
+        {
+            char *data = reinterpret_cast<char *>(&(*iter));
+
+            if (use_SSE42_CRC_function)
+            {
+                crc = SSE42BasedCRC32(data, sizeof(typename ContainerT::value_type));
+            }
+            else
+            {
+                crc = SoftwareBasedCRC32(data, sizeof(typename ContainerT::value_type));
+            }
             ++iter;
         }
         return crc;
     }
 };
 
-#endif /* ITERATORBASEDCRC32_H_ */
+#endif /* ITERATOR_BASED_CRC32_H */
diff --git a/Algorithms/ObjectToBase64.h b/Algorithms/ObjectToBase64.h
index 8d69c0a..2599283 100644
--- a/Algorithms/ObjectToBase64.h
+++ b/Algorithms/ObjectToBase64.h
@@ -1,67 +1,99 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef OBJECTTOBASE64_H_
 #define OBJECTTOBASE64_H_
 
+#include "../Util/StringUtil.h"
+
+#include <boost/assert.hpp>
 #include <boost/archive/iterators/base64_from_binary.hpp>
 #include <boost/archive/iterators/binary_from_base64.hpp>
 #include <boost/archive/iterators/transform_width.hpp>
-#include <boost/foreach.hpp>
 
 #include <algorithm>
 #include <string>
-
-#include "../Util/StringUtil.h"
+#include <vector>
 
 typedef
         boost::archive::iterators::base64_from_binary<
-        boost::archive::iterators::transform_width<std::string::const_iterator, 6, 8>
-> base64_t;
+            boost::archive::iterators::transform_width<const char *, 6, 8>
+        > base64_t;
 
 typedef
         boost::archive::iterators::transform_width<
-        boost::archive::iterators::binary_from_base64<std::string::const_iterator>, 8, 6
+            boost::archive::iterators::binary_from_base64<
+            std::string::const_iterator>, 8, 6
         > binary_t;
 
-template<class ToEncodeT>
-static void EncodeObjectToBase64(const ToEncodeT & object, std::string& encoded) {
-    encoded.clear();
-    char * pointerToOriginalObject = (char *)&object;
-    encoded = std::string(base64_t(pointerToOriginalObject), base64_t(pointerToOriginalObject+sizeof(ToEncodeT)));
-    //replace "+" with "-" and "/" with "_"
+template<class ObjectT>
+static void EncodeObjectToBase64(const ObjectT & object, std::string& encoded) {
+    const char * char_ptr_to_object = (const char *)&object;
+    std::vector<unsigned char> data(sizeof(object));
+    std::copy(
+        char_ptr_to_object,
+        char_ptr_to_object + sizeof(ObjectT),
+        data.begin()
+    );
+
+    unsigned char number_of_padded_chars = 0; // is in {0,1,2};
+    while(data.size() % 3 != 0)  {
+      ++number_of_padded_chars;
+      data.push_back(0x00);
+    }
+
+    BOOST_ASSERT_MSG(
+        0 == data.size() % 3,
+        "base64 input data size is not a multiple of 3!"
+    );
+    encoded.resize(sizeof(ObjectT));
+    encoded.assign(
+        base64_t( &data[0] ),
+        base64_t( &data[0] + (data.size() - number_of_padded_chars) )
+    );
     replaceAll(encoded, "+", "-");
     replaceAll(encoded, "/", "_");
 }
 
-template<class ToEncodeT>
-static void DecodeObjectFromBase64(ToEncodeT & object, const std::string& _encoded) {
+template<class ObjectT>
+static void DecodeObjectFromBase64(const std::string& input, ObjectT & object) {
     try {
-    	std::string encoded(_encoded);
+    	std::string encoded(input);
         //replace "-" with "+" and "_" with "/"
         replaceAll(encoded, "-", "+");
         replaceAll(encoded, "_", "/");
-        char * pointerToDecodedObject = (char *)&object;
-        std::string dec(binary_t(encoded.begin()), binary_t(encoded.begin() + encoded.length() - 1));
-        std::copy ( dec.begin(), dec.end(), pointerToDecodedObject );
-    } catch(...) {}
+
+        std::copy (
+            binary_t( encoded.begin() ),
+            binary_t( encoded.begin() + encoded.length() - 1),
+            (char *)&object
+        );
+
+    } catch(...) { }
 }
 
 #endif /* OBJECTTOBASE64_H_ */
diff --git a/Algorithms/PolylineCompressor.cpp b/Algorithms/PolylineCompressor.cpp
new file mode 100644
index 0000000..a34f8c7
--- /dev/null
+++ b/Algorithms/PolylineCompressor.cpp
@@ -0,0 +1,118 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "PolylineCompressor.h"
+#include "../DataStructures/SegmentInformation.h"
+
+#include <osrm/Coordinate.h>
+
+void PolylineCompressor::encodeVectorSignedNumber(std::vector<int> &numbers, std::string &output)
+    const
+{
+    const unsigned end = static_cast<unsigned>(numbers.size());
+    for (unsigned i = 0; i < end; ++i)
+    {
+        numbers[i] <<= 1;
+        if (numbers[i] < 0)
+        {
+            numbers[i] = ~(numbers[i]);
+        }
+    }
+    for (const int number : numbers)
+    {
+        encodeNumber(number, output);
+    }
+}
+
+void PolylineCompressor::encodeNumber(int number_to_encode, std::string &output) const
+{
+    while (number_to_encode >= 0x20)
+    {
+        const int next_value = (0x20 | (number_to_encode & 0x1f)) + 63;
+        output += static_cast<char>(next_value);
+        if (92 == next_value)
+        {
+            output += static_cast<char>(next_value);
+        }
+        number_to_encode >>= 5;
+    }
+
+    number_to_encode += 63;
+    output += static_cast<char>(number_to_encode);
+    if (92 == number_to_encode)
+    {
+        output += static_cast<char>(number_to_encode);
+    }
+}
+
+JSON::String PolylineCompressor::printEncodedString(const std::vector<SegmentInformation> &polyline)
+    const
+{
+    std::string output;
+    std::vector<int> delta_numbers;
+    if (!polyline.empty())
+    {
+        FixedPointCoordinate last_coordinate = polyline[0].location;
+        delta_numbers.emplace_back(last_coordinate.lat);
+        delta_numbers.emplace_back(last_coordinate.lon);
+        // iterate after skipping the first, already handled, segment
+        for (auto it = ++polyline.cbegin(); it != polyline.cend(); ++it)
+        {
+            const auto &segment = *it;
+            if (segment.necessary)
+            {
+                int lat_diff = segment.location.lat - last_coordinate.lat;
+                int lon_diff = segment.location.lon - last_coordinate.lon;
+                delta_numbers.emplace_back(lat_diff);
+                delta_numbers.emplace_back(lon_diff);
+                last_coordinate = segment.location;
+            }
+        }
+        encodeVectorSignedNumber(delta_numbers, output);
+    }
+    JSON::String return_value(output);
+    return return_value;
+}
+
+JSON::Array
+PolylineCompressor::printUnencodedString(const std::vector<SegmentInformation> &polyline) const
+{
+    JSON::Array json_geometry_array;
+    for (const auto &segment : polyline)
+    {
+        if (segment.necessary)
+        {
+            std::string tmp, output;
+            FixedPointCoordinate::convertInternalLatLonToString(segment.location.lat, tmp);
+            output += (tmp + ",");
+            FixedPointCoordinate::convertInternalLatLonToString(segment.location.lon, tmp);
+            output += tmp;
+            json_geometry_array.values.push_back(output);
+        }
+    }
+    return json_geometry_array;
+}
diff --git a/Algorithms/PolylineCompressor.h b/Algorithms/PolylineCompressor.h
index 7bb143b..5472bd8 100644
--- a/Algorithms/PolylineCompressor.h
+++ b/Algorithms/PolylineCompressor.h
@@ -1,134 +1,51 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef POLYLINECOMPRESSOR_H_
-#define POLYLINECOMPRESSOR_H_
-
-#include <string>
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-//#include "../DataStructures/ExtractorStructs.h"
-#include "../DataStructures/SegmentInformation.h"
-#include "../Util/StringUtil.h"
+*/
 
-class PolylineCompressor {
-private:
-	inline void encodeVectorSignedNumber(std::vector<int> & numbers, std::string & output) const {
-		for(unsigned i = 0; i < numbers.size(); ++i) {
-			numbers[i] <<= 1;
-			if (numbers[i] < 0) {
-				numbers[i] = ~(numbers[i]);
-			}
-		}
-		for(unsigned i = 0; i < numbers.size(); ++i) {
-			encodeNumber(numbers[i], output);
-		}
-	}
+#ifndef POLYLINECOMPRESSOR_H_
+#define POLYLINECOMPRESSOR_H_
 
-	inline void encodeNumber(int numberToEncode, std::string & output) const {
-		while (numberToEncode >= 0x20) {
-			int nextValue = (0x20 | (numberToEncode & 0x1f)) + 63;
-			output += (static_cast<char> (nextValue));
-			if(92 == nextValue)
-				output += (static_cast<char> (nextValue));
-			numberToEncode >>= 5;
-		}
+struct SegmentInformation;
 
-		numberToEncode += 63;
-		output += (static_cast<char> (numberToEncode));
-		if(92 == numberToEncode)
-			output += (static_cast<char> (numberToEncode));
-	}
+#include "../DataStructures/JSONContainer.h"
 
-public:
-    inline void printEncodedString(const std::vector<SegmentInformation>& polyline, std::string &output) const {
-    	std::vector<int> deltaNumbers;
-        output += "\"";
-        if(!polyline.empty()) {
-            _Coordinate lastCoordinate = polyline[0].location;
-            deltaNumbers.push_back( lastCoordinate.lat );
-            deltaNumbers.push_back( lastCoordinate.lon );
-            for(unsigned i = 1; i < polyline.size(); ++i) {
-                if(!polyline[i].necessary)
-                    continue;
-                deltaNumbers.push_back(polyline[i].location.lat - lastCoordinate.lat);
-                deltaNumbers.push_back(polyline[i].location.lon - lastCoordinate.lon);
-                lastCoordinate = polyline[i].location;
-            }
-            encodeVectorSignedNumber(deltaNumbers, output);
-        }
-        output += "\"";
+#include <string>
+#include <vector>
 
-    }
+class PolylineCompressor
+{
+  private:
+    void encodeVectorSignedNumber(std::vector<int> &numbers, std::string &output) const;
 
-	inline void printEncodedString(const std::vector<_Coordinate>& polyline, std::string &output) const {
-		std::vector<int> deltaNumbers(2*polyline.size());
-		output += "\"";
-		if(!polyline.empty()) {
-			deltaNumbers[0] = polyline[0].lat;
-			deltaNumbers[1] = polyline[0].lon;
-			for(unsigned i = 1; i < polyline.size(); ++i) {
-				deltaNumbers[(2*i)]   = (polyline[i].lat - polyline[i-1].lat);
-				deltaNumbers[(2*i)+1] = (polyline[i].lon - polyline[i-1].lon);
-			}
-			encodeVectorSignedNumber(deltaNumbers, output);
-		}
-		output += "\"";
-	}
+    void encodeNumber(int number_to_encode, std::string &output) const;
 
-    inline void printUnencodedString(std::vector<_Coordinate> & polyline, std::string & output) const {
-        output += "[";
-        std::string tmp;
-        for(unsigned i = 0; i < polyline.size(); i++) {
-            convertInternalLatLonToString(polyline[i].lat, tmp);
-            output += "[";
-            output += tmp;
-            convertInternalLatLonToString(polyline[i].lon, tmp);
-            output += ", ";
-            output += tmp;
-            output += "]";
-            if( i < polyline.size()-1 ) {
-                output += ",";
-            }
-        }
-        output += "]";
-    }
+  public:
+    JSON::String printEncodedString(const std::vector<SegmentInformation> &polyline) const;
 
-    inline void printUnencodedString(std::vector<SegmentInformation> & polyline, std::string & output) const {
-        output += "[";
-        std::string tmp;
-        for(unsigned i = 0; i < polyline.size(); i++) {
-            if(!polyline[i].necessary)
-                continue;
-            convertInternalLatLonToString(polyline[i].location.lat, tmp);
-            output += "[";
-            output += tmp;
-            convertInternalLatLonToString(polyline[i].location.lon, tmp);
-            output += ", ";
-            output += tmp;
-            output += "]";
-            if( i < polyline.size()-1 ) {
-                output += ",";
-            }
-        }
-        output += "]";
-    }
+    JSON::Array printUnencodedString(const std::vector<SegmentInformation> &polyline) const;
 };
 
 #endif /* POLYLINECOMPRESSOR_H_ */
diff --git a/Algorithms/StronglyConnectedComponents.h b/Algorithms/StronglyConnectedComponents.h
index a831100..e0c31f9 100644
--- a/Algorithms/StronglyConnectedComponents.h
+++ b/Algorithms/StronglyConnectedComponents.h
@@ -1,373 +1,447 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+*/
 
 #ifndef STRONGLYCONNECTEDCOMPONENTS_H_
 #define STRONGLYCONNECTEDCOMPONENTS_H_
 
-#include <cassert>
-
-#include <stack>
-#include <vector>
-
-#include <boost/foreach.hpp>
-#include <boost/make_shared.hpp>
-#include <boost/unordered_map.hpp>
-
-#include <gdal/gdal.h>
-#include <gdal/ogrsf_frmts.h>
-
+#include "../typedefs.h"
 #include "../DataStructures/DeallocatingVector.h"
 #include "../DataStructures/DynamicGraph.h"
 #include "../DataStructures/ImportEdge.h"
-#include "../DataStructures/NodeCoords.h"
+#include "../DataStructures/QueryNode.h"
 #include "../DataStructures/Percent.h"
 #include "../DataStructures/Restriction.h"
 #include "../DataStructures/TurnInstructions.h"
 
-// Strongly connected components using Tarjan's Algorithm
+#include "../Util/OSRMException.h"
+#include "../Util/SimpleLogger.h"
+#include "../Util/StdHashExtensions.h"
 
-class TarjanSCC {
-private:
-    struct _NodeBasedEdgeData {
-        int distance;
-        unsigned edgeBasedNodeID;
-        unsigned nameID:31;
-        bool shortcut:1;
-        short type;
-        bool isAccessRestricted:1;
-        bool forward:1;
-        bool backward:1;
-        bool roundabout:1;
-        bool ignoreInGrid:1;
-    };
+#include <osrm/Coordinate.h>
 
-    typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph;
-    typedef _NodeBasedDynamicGraph::InputEdge _NodeBasedEdge;
-    std::vector<NodeInfo>               inputNodeInfoList;
-    unsigned numberOfTurnRestrictions;
-    boost::shared_ptr<_NodeBasedDynamicGraph>   _nodeBasedGraph;
-    boost::unordered_map<NodeID, bool>          _barrierNodes;
-    boost::unordered_map<NodeID, bool>          _trafficLights;
+#include <boost/assert.hpp>
+#include <boost/filesystem.hpp>
 
-    typedef std::pair<NodeID, NodeID> RestrictionSource;
-    typedef std::pair<NodeID, bool>   RestrictionTarget;
-    typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
-    typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
-    std::vector<EmanatingRestrictionsVector> _restrictionBucketVector;
-    RestrictionMap _restrictionMap;
+#ifdef __APPLE__
+#include <gdal.h>
+#include <ogrsf_frmts.h>
+#else
+#include <gdal/gdal.h>
+#include <gdal/ogrsf_frmts.h>
+#endif
 
+#include <cstdint>
 
-public:
-    struct EdgeBasedNode {
-        bool operator<(const EdgeBasedNode & other) const {
-            return other.id < id;
-        }
-        bool operator==(const EdgeBasedNode & other) const {
-            return id == other.id;
-        }
-        NodeID id;
-        int lat1;
-        int lat2;
-        int lon1;
-        int lon2:31;
-        bool belongsToTinyComponent:1;
-        NodeID nameID;
-        unsigned weight:31;
-        bool ignoreInGrid:1;
-    };
-
-private:
-    DeallocatingVector<EdgeBasedNode>   edgeBasedNodes;
+#include <memory>
+#include <stack>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
 
-    struct TarjanNode {
-        TarjanNode() : index(UINT_MAX), lowlink(UINT_MAX), onStack(false) {}
+class TarjanSCC
+{
+  private:
+    struct TarjanNode
+    {
+        TarjanNode() : index(UINT_MAX), low_link(UINT_MAX), on_stack(false) {}
         unsigned index;
-        unsigned lowlink;
-        bool onStack;
+        unsigned low_link;
+        bool on_stack;
+    };
+
+    struct TarjanEdgeData
+    {
+        int distance;
+        unsigned name_id : 31;
+        bool shortcut : 1;
+        short type;
+        bool forward : 1;
+        bool backward : 1;
+        bool reversedEdge : 1;
     };
 
-    struct TarjanStackFrame {
-        explicit TarjanStackFrame(NodeID _v, NodeID p) : v(_v), parent(p) {}
+    struct TarjanStackFrame
+    {
+        explicit TarjanStackFrame(NodeID v, NodeID parent) : v(v), parent(parent) {}
         NodeID v;
         NodeID parent;
     };
-public:
-    TarjanSCC(int nodes, std::vector<NodeBasedEdge> & inputEdges, std::vector<NodeID> & bn, std::vector<NodeID> & tl, std::vector<_Restriction> & irs, std::vector<NodeInfo> & nI) : inputNodeInfoList(nI), numberOfTurnRestrictions(irs.size()) {
-        BOOST_FOREACH(_Restriction & restriction, irs) {
-            std::pair<NodeID, NodeID> restrictionSource = std::make_pair(restriction.fromNode, restriction.viaNode);
+
+    typedef DynamicGraph<TarjanEdgeData> TarjanDynamicGraph;
+    typedef TarjanDynamicGraph::InputEdge TarjanEdge;
+    typedef std::pair<NodeID, NodeID> RestrictionSource;
+    typedef std::pair<NodeID, bool> restriction_target;
+    typedef std::vector<restriction_target> EmanatingRestrictionsVector;
+    typedef std::unordered_map<RestrictionSource, unsigned> RestrictionMap;
+
+    std::vector<NodeInfo> m_coordinate_list;
+    std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
+    std::shared_ptr<TarjanDynamicGraph> m_node_based_graph;
+    std::unordered_set<NodeID> m_barrier_node_list;
+    std::unordered_set<NodeID> m_traffic_light_list;
+    unsigned m_restriction_counter;
+    RestrictionMap m_restriction_map;
+
+  public:
+    TarjanSCC(int number_of_nodes,
+              std::vector<NodeBasedEdge> &input_edges,
+              std::vector<NodeID> &bn,
+              std::vector<NodeID> &tl,
+              std::vector<TurnRestriction> &irs,
+              std::vector<NodeInfo> &nI)
+        : m_coordinate_list(nI), m_restriction_counter(irs.size())
+    {
+        for (const TurnRestriction &restriction : irs)
+        {
+            std::pair<NodeID, NodeID> restrictionSource = {restriction.fromNode,
+                                                           restriction.viaNode};
             unsigned index;
-            RestrictionMap::iterator restrIter = _restrictionMap.find(restrictionSource);
-            if(restrIter == _restrictionMap.end()) {
-                index = _restrictionBucketVector.size();
-                _restrictionBucketVector.resize(index+1);
-                _restrictionMap[restrictionSource] = index;
-            } else {
-                index = restrIter->second;
-                //Map already contains an is_only_*-restriction
-                if(_restrictionBucketVector.at(index).begin()->second)
+            RestrictionMap::iterator restriction_iterator =
+                m_restriction_map.find(restrictionSource);
+            if (restriction_iterator == m_restriction_map.end())
+            {
+                index = m_restriction_bucket_list.size();
+                m_restriction_bucket_list.resize(index + 1);
+                m_restriction_map.emplace(restrictionSource, index);
+            }
+            else
+            {
+                index = restriction_iterator->second;
+                // Map already contains an is_only_*-restriction
+                if (m_restriction_bucket_list.at(index).begin()->second)
+                {
                     continue;
-                else if(restriction.flags.isOnly){
-                    //We are going to insert an is_only_*-restriction. There can be only one.
-                    _restrictionBucketVector.at(index).clear();
+                }
+                else if (restriction.flags.isOnly)
+                {
+                    // We are going to insert an is_only_*-restriction. There can be only one.
+                    m_restriction_bucket_list.at(index).clear();
                 }
             }
 
-            _restrictionBucketVector.at(index).push_back(std::make_pair(restriction.toNode, restriction.flags.isOnly));
+            m_restriction_bucket_list.at(index)
+                .emplace_back(restriction.toNode, restriction.flags.isOnly);
         }
 
-        BOOST_FOREACH(NodeID id, bn) {
-            _barrierNodes[id] = true;
-        }
-        BOOST_FOREACH(NodeID id, tl) {
-            _trafficLights[id] = true;
-        }
+        m_barrier_node_list.insert(bn.begin(), bn.end());
+        m_traffic_light_list.insert(tl.begin(), tl.end());
 
-        DeallocatingVector< _NodeBasedEdge > edges;
-        for ( std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(); i != inputEdges.end(); ++i ) {
-
-            _NodeBasedEdge edge;
-            if(!i->isForward()) {
-                edge.source = i->target();
-                edge.target = i->source();
-                edge.data.backward = i->isForward();
-                edge.data.forward = i->isBackward();
-            } else {
-                edge.source = i->source();
-                edge.target = i->target();
-                edge.data.forward = i->isForward();
-                edge.data.backward = i->isBackward();
-            }
-            if(edge.source == edge.target)
+        DeallocatingVector<TarjanEdge> edge_list;
+        for (const NodeBasedEdge &input_edge : input_edges)
+        {
+            if (input_edge.source == input_edge.target)
+            {
                 continue;
+            }
+
+            TarjanEdge edge;
+            if (input_edge.forward)
+            {
+                edge.source = input_edge.source;
+                edge.target = input_edge.target;
+                edge.data.forward = input_edge.forward;
+                edge.data.backward = input_edge.backward;
+            }
+            else
+            {
+                edge.source = input_edge.target;
+                edge.target = input_edge.source;
+                edge.data.backward = input_edge.forward;
+                edge.data.forward = input_edge.backward;
+            }
 
-            edge.data.distance = (std::max)((int)i->weight(), 1 );
-            assert( edge.data.distance > 0 );
+            edge.data.distance = (std::max)((int)input_edge.weight, 1);
+            BOOST_ASSERT(edge.data.distance > 0);
             edge.data.shortcut = false;
-            edge.data.roundabout = i->isRoundabout();
-            edge.data.ignoreInGrid = i->ignoreInGrid();
-            edge.data.nameID = i->name();
-            edge.data.type = i->type();
-            edge.data.isAccessRestricted = i->isAccessRestricted();
-            edge.data.edgeBasedNodeID = edges.size();
-            edges.push_back( edge );
-            if( edge.data.backward ) {
-                std::swap( edge.source, edge.target );
-                edge.data.forward = i->isBackward();
-                edge.data.backward = i->isForward();
-                edge.data.edgeBasedNodeID = edges.size();
-                edges.push_back( edge );
+            edge.data.name_id = input_edge.name_id;
+            edge.data.type = input_edge.type;
+            edge.data.reversedEdge = false;
+            edge_list.push_back(edge);
+            if (edge.data.backward)
+            {
+                std::swap(edge.source, edge.target);
+                edge.data.forward = input_edge.backward;
+                edge.data.backward = input_edge.forward;
+                edge.data.reversedEdge = true;
+                edge_list.push_back(edge);
             }
         }
-        std::vector<NodeBasedEdge>().swap(inputEdges);
-        std::sort( edges.begin(), edges.end() );
-        _nodeBasedGraph = boost::make_shared<_NodeBasedDynamicGraph>( nodes, edges );
+        input_edges.shrink_to_fit();
+        BOOST_ASSERT_MSG(0 == input_edges.size() && 0 == input_edges.capacity(),
+                         "input edge vector not properly deallocated");
+
+        std::sort(edge_list.begin(), edge_list.end());
+        m_node_based_graph = std::make_shared<TarjanDynamicGraph>(number_of_nodes, edge_list);
     }
 
-    void Run() {
-        Percent p(_nodeBasedGraph->GetNumberOfNodes());
+    ~TarjanSCC() { m_node_based_graph.reset(); }
 
-        const char *pszDriverName = "ESRI Shapefile";
-        OGRSFDriver *poDriver;
+    void Run()
+    {
+        // remove files from previous run if exist
+        DeleteFileIfExists("component.dbf");
+        DeleteFileIfExists("component.shx");
+        DeleteFileIfExists("component.shp");
+
+        Percent p(m_node_based_graph->GetNumberOfNodes());
 
         OGRRegisterAll();
 
-        poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(
-                pszDriverName );
-        if( poDriver == NULL )
+        const char *pszDriverName = "ESRI Shapefile";
+        OGRSFDriver *poDriver =
+            OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(pszDriverName);
+        if (nullptr == poDriver)
         {
-            printf( "%s driver not available.\n", pszDriverName );
-            exit( 1 );
+            throw OSRMException("ESRI Shapefile driver not available");
         }
-        OGRDataSource *poDS;
+        OGRDataSource *poDS = poDriver->CreateDataSource("component.shp", nullptr);
 
-        poDS = poDriver->CreateDataSource( "component.shp", NULL );
-        if( poDS == NULL ) {
-            printf( "Creation of output file failed.\n" );
-            exit( 1 );
+        if (nullptr == poDS)
+        {
+            throw OSRMException("Creation of output file failed");
         }
 
-        OGRLayer *poLayer;
+        OGRLayer *poLayer = poDS->CreateLayer("component", nullptr, wkbLineString, nullptr);
 
-        poLayer = poDS->CreateLayer( "component", NULL, wkbLineString, NULL );
-        if( poLayer == NULL ) {
-            printf( "Layer creation failed.\n" );
-            exit( 1 );
+        if (nullptr == poLayer)
+        {
+            throw OSRMException("Layer creation failed.");
         }
 
-
-        //The following is a hack to distinguish between stuff that happens before the recursive call and stuff that happens after
-        std::stack<std::pair<bool, TarjanStackFrame> > recursionStack; //true = stuff before, false = stuff after call
-        std::stack<NodeID> tarjanStack;
-        std::vector<unsigned> componentsIndex(_nodeBasedGraph->GetNumberOfNodes(), UINT_MAX);
-        std::vector<NodeID> vectorOfComponentSizes;
-        std::vector<TarjanNode> tarjanNodes(_nodeBasedGraph->GetNumberOfNodes());
-        unsigned currentComponent = 0, sizeOfCurrentComponent = 0;
+        // The following is a hack to distinguish between stuff that happens
+        // before the recursive call and stuff that happens after
+        std::stack<std::pair<bool, TarjanStackFrame>> recursion_stack;
+        // true = stuff before, false = stuff after call
+        std::stack<NodeID> tarjan_stack;
+        std::vector<unsigned> components_index(m_node_based_graph->GetNumberOfNodes(), UINT_MAX);
+        std::vector<NodeID> component_size_vector;
+        std::vector<TarjanNode> tarjan_node_list(m_node_based_graph->GetNumberOfNodes());
+        unsigned component_index = 0, size_of_current_component = 0;
         int index = 0;
-        for(NodeID node = 0, endNodes = _nodeBasedGraph->GetNumberOfNodes(); node < endNodes; ++node) {
-            if(UINT_MAX == componentsIndex[node]) {
-                recursionStack.push(std::make_pair(true, TarjanStackFrame(node,node)) );
+        NodeID last_node = m_node_based_graph->GetNumberOfNodes();
+        for (NodeID node = 0; node < last_node; ++node)
+        {
+            if (UINT_MAX == components_index[node])
+            {
+                recursion_stack.emplace(true, TarjanStackFrame(node, node));
             }
 
-            while(!recursionStack.empty()) {
-                bool beforeRecursion = recursionStack.top().first;
-                TarjanStackFrame currentFrame = recursionStack.top().second;
+            while (!recursion_stack.empty())
+            {
+                const bool before_recursion = recursion_stack.top().first;
+                TarjanStackFrame currentFrame = recursion_stack.top().second;
                 NodeID v = currentFrame.v;
-//                INFO("popping node " << v << (beforeRecursion ? " before " : " after ") << "recursion");
-                recursionStack.pop();
-
-                if(beforeRecursion) {
-                    //Mark frame to handle tail of recursion
-                    recursionStack.push(std::make_pair(false, currentFrame));
-
-                    //Mark essential information for SCC
-                    tarjanNodes[v].index = index;
-                    tarjanNodes[v].lowlink = index;
-                    tarjanStack.push(v);
-                    tarjanNodes[v].onStack = true;
+                recursion_stack.pop();
+
+                if (before_recursion)
+                {
+                    // Mark frame to handle tail of recursion
+                    recursion_stack.emplace(false, currentFrame);
+
+                    // Mark essential information for SCC
+                    tarjan_node_list[v].index = index;
+                    tarjan_node_list[v].low_link = index;
+                    tarjan_stack.push(v);
+                    tarjan_node_list[v].on_stack = true;
                     ++index;
-//                    INFO("pushing " << v << " onto tarjan stack, idx[" << v << "]=" << tarjanNodes[v].index << ", lowlink["<< v << "]=" << tarjanNodes[v].lowlink);
-
-                    //Traverse outgoing edges
-                    for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
-                        _NodeBasedDynamicGraph::NodeIterator vprime = _nodeBasedGraph->GetTarget(e2);
-//                        INFO("traversing edge (" << v << "," << vprime << ")");
-                        if(UINT_MAX == tarjanNodes[vprime].index) {
-
-                            recursionStack.push(std::make_pair(true,TarjanStackFrame(vprime, v)));
-                        } else {
-//                            INFO("Node " << vprime << " is already explored");
-                            if(tarjanNodes[vprime].onStack) {
-                                unsigned newLowlink = std::min(tarjanNodes[v].lowlink, tarjanNodes[vprime].index);
-//                                INFO("Setting lowlink[" << v << "] from " << tarjanNodes[v].lowlink << " to " << newLowlink);
-                                tarjanNodes[v].lowlink = newLowlink;
-//                            } else {
-//                                INFO("But node " << vprime << " is not on stack");
+
+                    // Traverse outgoing edges
+                    for (auto e2 : m_node_based_graph->GetAdjacentEdgeRange(v))
+                    {
+                        const TarjanDynamicGraph::NodeIterator vprime =
+                            m_node_based_graph->GetTarget(e2);
+                        if (UINT_MAX == tarjan_node_list[vprime].index)
+                        {
+                            recursion_stack.emplace(true, TarjanStackFrame(vprime, v));
+                        }
+                        else
+                        {
+                            if (tarjan_node_list[vprime].on_stack &&
+                                tarjan_node_list[vprime].index < tarjan_node_list[v].low_link)
+                            {
+                                tarjan_node_list[v].low_link = tarjan_node_list[vprime].index;
                             }
                         }
                     }
-                } else {
-
-//                    INFO("we are at the end of recursion and checking node " << v);
-                    { // setting lowlink in its own scope so it does not pollute namespace
-                        //                        NodeID parent = (UINT_MAX == tarjanNodes[v].parent ? v : tarjanNodes[v].parent );
-//                        INFO("parent=" << currentFrame.parent);
-//                        INFO("tarjanNodes[" << v  << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << currentFrame.parent << "].lowlink=" << tarjanNodes[currentFrame.parent].lowlink);
-                        //Note the index shift by 1 compared to the recursive version
-                        tarjanNodes[currentFrame.parent].lowlink = std::min(tarjanNodes[currentFrame.parent].lowlink, tarjanNodes[v].lowlink);
-//                        INFO("Setting tarjanNodes[" << currentFrame.parent  <<"].lowlink=" << tarjanNodes[currentFrame.parent].lowlink);
-                    }
-//                    INFO("tarjanNodes[" << v  << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << v  << "].index=" << tarjanNodes[v].index);
-
-                    //after recursion, lets do cycle checking
-                    //Check if we found a cycle. This is the bottom part of the recursion
-                    if(tarjanNodes[v].lowlink == tarjanNodes[v].index) {
+                }
+                else
+                {
+                    tarjan_node_list[currentFrame.parent].low_link =
+                        std::min(tarjan_node_list[currentFrame.parent].low_link,
+                                 tarjan_node_list[v].low_link);
+                    // after recursion, lets do cycle checking
+                    // Check if we found a cycle. This is the bottom part of the recursion
+                    if (tarjan_node_list[v].low_link == tarjan_node_list[v].index)
+                    {
                         NodeID vprime;
-                        do {
-//                            INFO("identified component " << currentComponent << ": " << tarjanStack.top());
-                            vprime = tarjanStack.top(); tarjanStack.pop();
-                            tarjanNodes[vprime].onStack = false;
-                            componentsIndex[vprime] = currentComponent;
-                            ++sizeOfCurrentComponent;
-                        } while( v != vprime);
-                        vectorOfComponentSizes.push_back(sizeOfCurrentComponent);
-                        if(sizeOfCurrentComponent > 1000)
-                            INFO("large component [" << currentComponent << "]=" << sizeOfCurrentComponent);
-                        ++currentComponent;
-                        sizeOfCurrentComponent = 0;
+                        do
+                        {
+                            vprime = tarjan_stack.top();
+                            tarjan_stack.pop();
+                            tarjan_node_list[vprime].on_stack = false;
+                            components_index[vprime] = component_index;
+                            ++size_of_current_component;
+                        } while (v != vprime);
+
+                        component_size_vector.emplace_back(size_of_current_component);
+
+                        if (size_of_current_component > 1000)
+                        {
+                            SimpleLogger().Write() << "large component [" << component_index
+                                                   << "]=" << size_of_current_component;
+                        }
+
+                        ++component_index;
+                        size_of_current_component = 0;
                     }
                 }
             }
         }
 
-        INFO("identified: " << vectorOfComponentSizes.size() << " many components, marking small components");
+        SimpleLogger().Write() << "identified: " << component_size_vector.size()
+                               << " many components, marking small components";
 
-        int singleCounter = 0;
-        for(unsigned i = 0; i < vectorOfComponentSizes.size(); ++i){
-            if(1 == vectorOfComponentSizes[i])
-                ++singleCounter;
-        }
-        INFO("identified " << singleCounter << " SCCs of size 1");
+        unsigned size_one_counter = std::count_if(component_size_vector.begin(),
+                                                  component_size_vector.end(),
+                                                  [] (unsigned value) { return 1 == value;});
 
-        p.reinit(_nodeBasedGraph->GetNumberOfNodes());
-        for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
-            for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
-                _NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
+        SimpleLogger().Write() << "identified " << size_one_counter << " SCCs of size 1";
 
-                if(_nodeBasedGraph->GetEdgeData(e1).type != SHRT_MAX) {
-                    assert(e1 != UINT_MAX);
-                    assert(u != UINT_MAX);
-                    assert(v != UINT_MAX);
-                    //edges that end on bollard nodes may actually be in two distinct components
-                    if(std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 10) {
-
-                        //INFO("(" << inputNodeInfoList[u].lat/100000. << ";" << inputNodeInfoList[u].lon/100000. << ") -> (" << inputNodeInfoList[v].lat/100000. << ";" << inputNodeInfoList[v].lon/100000. << ")");
+        uint64_t total_network_distance = 0;
+        p.reinit(m_node_based_graph->GetNumberOfNodes());
+        NodeID last_u_node = m_node_based_graph->GetNumberOfNodes();
+        for (NodeID u = 0; u < last_u_node; ++u)
+        {
+            p.printIncrement();
+            for (auto e1 : m_node_based_graph->GetAdjacentEdgeRange(u))
+            {
+                if (!m_node_based_graph->GetEdgeData(e1).reversedEdge)
+                {
+                    continue;
+                }
+                const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1);
+
+                total_network_distance +=
+                    100 * FixedPointCoordinate::ApproximateDistance(m_coordinate_list[u].lat,
+                                                                    m_coordinate_list[u].lon,
+                                                                    m_coordinate_list[v].lat,
+                                                                    m_coordinate_list[v].lon);
+
+                if (SHRT_MAX != m_node_based_graph->GetEdgeData(e1).type)
+                {
+                    BOOST_ASSERT(e1 != UINT_MAX);
+                    BOOST_ASSERT(u != UINT_MAX);
+                    BOOST_ASSERT(v != UINT_MAX);
+
+                    const unsigned size_of_containing_component =
+                        std::min(component_size_vector[components_index[u]],
+                                 component_size_vector[components_index[v]]);
+
+                    // edges that end on bollard nodes may actually be in two distinct components
+                    if (size_of_containing_component < 10)
+                    {
                         OGRLineString lineString;
-                        lineString.addPoint(inputNodeInfoList[u].lon/100000., inputNodeInfoList[u].lat/100000.);
-                        lineString.addPoint(inputNodeInfoList[v].lon/100000., inputNodeInfoList[v].lat/100000.);
+                        lineString.addPoint(m_coordinate_list[u].lon / COORDINATE_PRECISION,
+                                            m_coordinate_list[u].lat / COORDINATE_PRECISION);
+                        lineString.addPoint(m_coordinate_list[v].lon / COORDINATE_PRECISION,
+                                            m_coordinate_list[v].lat / COORDINATE_PRECISION);
 
-                        OGRFeature *poFeature;
-                        poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() );
-                        poFeature->SetGeometry( &lineString );
-                        if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE )
+                        OGRFeature *poFeature = OGRFeature::CreateFeature(poLayer->GetLayerDefn());
+
+                        poFeature->SetGeometry(&lineString);
+                        if (OGRERR_NONE != poLayer->CreateFeature(poFeature))
                         {
-                            ERR( "Failed to create feature in shapefile.\n" );
+                            throw OSRMException("Failed to create feature in shapefile.");
                         }
-                        OGRFeature::DestroyFeature( poFeature );
+                        OGRFeature::DestroyFeature(poFeature);
                     }
                 }
             }
         }
-        OGRDataSource::DestroyDataSource( poDS );
-        std::vector<NodeID>().swap(vectorOfComponentSizes);
-        std::vector<NodeID>().swap(componentsIndex);
+        OGRDataSource::DestroyDataSource(poDS);
+        std::vector<NodeID>().swap(component_size_vector);
+        BOOST_ASSERT_MSG(0 == component_size_vector.size() && 0 == component_size_vector.capacity(),
+                         "component_size_vector not properly deallocated");
+
+        std::vector<NodeID>().swap(components_index);
+        BOOST_ASSERT_MSG(0 == components_index.size() && 0 == components_index.capacity(),
+                         "icomponents_index not properly deallocated");
 
+        SimpleLogger().Write() << "total network distance: " << (uint64_t)total_network_distance /
+                                                                    100 / 1000. << " km";
     }
-private:
-    unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
-        std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
-        RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
-        if (restrIter != _restrictionMap.end()) {
-            unsigned index = restrIter->second;
-            BOOST_FOREACH(RestrictionSource restrictionTarget, _restrictionBucketVector.at(index)) {
-                if(restrictionTarget.second) {
-                    return restrictionTarget.first;
+
+  private:
+    unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const
+    {
+        std::pair<NodeID, NodeID> restriction_source = {u, v};
+        RestrictionMap::const_iterator restriction_iterator =
+            m_restriction_map.find(restriction_source);
+        if (restriction_iterator != m_restriction_map.end())
+        {
+            const unsigned index = restriction_iterator->second;
+            for (const RestrictionSource &restriction_target : m_restriction_bucket_list.at(index))
+            {
+                if (restriction_target.second)
+                {
+                    return restriction_target.first;
                 }
             }
         }
         return UINT_MAX;
     }
-    bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const {
-        //only add an edge if turn is not a U-turn except it is the end of dead-end street.
-        std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
-        RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
-        if (restrIter != _restrictionMap.end()) {
-            unsigned index = restrIter->second;
-            BOOST_FOREACH(RestrictionTarget restrictionTarget, _restrictionBucketVector.at(index)) {
-                if(w == restrictionTarget.first)
+
+    bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const
+    {
+        // only add an edge if turn is not a U-turn except it is the end of dead-end street.
+        std::pair<NodeID, NodeID> restriction_source = {u, v};
+        RestrictionMap::const_iterator restriction_iterator =
+            m_restriction_map.find(restriction_source);
+        if (restriction_iterator != m_restriction_map.end())
+        {
+            const unsigned index = restriction_iterator->second;
+            for (const restriction_target &restriction_target : m_restriction_bucket_list.at(index))
+            {
+                if (w == restriction_target.first)
+                {
                     return true;
+                }
             }
         }
         return false;
     }
+
+    void DeleteFileIfExists(const std::string &file_name) const
+    {
+        if (boost::filesystem::exists(file_name))
+        {
+            boost::filesystem::remove(file_name);
+        }
+    }
 };
 
 #endif /* STRONGLYCONNECTEDCOMPONENTS_H_ */
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3de4c4f..dc202c8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,111 +1,307 @@
-cmake_minimum_required(VERSION 2.6)
+cmake_minimum_required(VERSION 2.8)
 project(OSRM)
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+include(CheckCXXCompilerFlag)
 include(FindPackageHandleStandardArgs)
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
-set(BOOST_COMPONENTS filesystem regex system thread)
 
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
+include(GetGitRevisionDescription)
+git_describe(GIT_DESCRIPTION)
+
+set(bitness 32)
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+  set(bitness 64)
+  message(STATUS "Building on a 64 bit system")
+else()
+  message(WARNING "Building on a 32 bit system is unsupported")
+endif()
+
+if (WIN32 AND MSVC_VERSION LESS 1800)
+  message(FATAL_ERROR "Building with Microsoft compiler needs Visual Studio 2013 or later (Express version works too)")
+endif()
+
+OPTION(WITH_TOOLS "Build ORSM tools" OFF)
+
+include_directories(${CMAKE_SOURCE_DIR}/Include/)
+
+add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp FingerPrint.cpp.alwaysbuild
+  COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
+    -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FingerPrint-Config.cmake
+  DEPENDS
+    ${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp.in
+  COMMENT "Configuring FingerPrint.cpp"
+  VERBATIM)
+
+add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp)
+
+set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread)
+
+configure_file(
+  ${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp.in
+  ${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp
+)
 file(GLOB ExtractorGlob Extractor/*.cpp)
+file(GLOB ImporterGlob DataStructures/Import*.cpp)
+add_library(IMPORT STATIC ${ImporterGlob})
 set(ExtractorSources extractor.cpp ${ExtractorGlob})
 add_executable(osrm-extract ${ExtractorSources})
 
-file(GLOB PrepareGlob Contractor/*.cpp)
-set(PrepareSources createHierarchy.cpp ${PrepareGlob})
+file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp DataStructures/RestrictionMap.cpp)
+set(PrepareSources prepare.cpp ${PrepareGlob})
 add_executable(osrm-prepare ${PrepareSources})
 
-file(GLOB RoutedGlob Server/DataStructures/*.cpp Descriptors/*.cpp DataStructures/SearchEngine*.cpp)
-set(RoutedSources routed.cpp ${RoutedGlob})
-add_executable(osrm-routed ${RoutedSources})
-set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
+file(GLOB ServerGlob Server/*.cpp)
+file(GLOB DescriptorGlob Descriptors/*.cpp)
+file(GLOB DatastructureGlob DataStructures/SearchEngineData.cpp DataStructures/RouteParameters.cpp)
+file(GLOB CoordinateGlob DataStructures/Coordinate.cpp)
+file(GLOB AlgorithmGlob Algorithms/*.cpp)
+file(GLOB HttpGlob Server/Http/*.cpp)
+file(GLOB LibOSRMGlob Library/*.cpp)
+
+set(
+  OSRMSources
+  ${LibOSRMGlob}
+  ${DescriptorGlob}
+  ${DatastructureGlob}
+  ${CoordinateGlob}
+  ${AlgorithmGlob}
+  ${HttpGlob}
+)
+add_library(COORDLIB STATIC ${CoordinateGlob})
+add_library(FINGERPRINT STATIC Util/FingerPrint.cpp)
+add_library(OSRM ${OSRMSources} Util/GitDescription.cpp Util/FingerPrint.cpp)
+add_library(GITDESCRIPTION STATIC Util/GitDescription.cpp)
+add_dependencies(FINGERPRINT FingerPrintConfigure)
+
+add_executable(osrm-routed routed.cpp ${ServerGlob})
+add_executable(osrm-datastore datastore.cpp)
 
 # Check the release mode
 if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
-	set(CMAKE_BUILD_TYPE Release)
-endif(NOT CMAKE_BUILD_TYPE MATCHES Debug) 
+  set(CMAKE_BUILD_TYPE Release)
+endif()
 if(CMAKE_BUILD_TYPE MATCHES Debug)
-    message(STATUS "Configuring OSRM in debug mode")
-endif(CMAKE_BUILD_TYPE MATCHES Debug) 
+  message(STATUS "Configuring OSRM in debug mode")
+  if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+    message(STATUS "adding profiling flags")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
+    set(CMAKE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
+  endif()
+endif()
 if(CMAKE_BUILD_TYPE MATCHES Release)
-    message(STATUS "Configuring OSRM in release mode")
-endif(CMAKE_BUILD_TYPE MATCHES Release) 
-
-#Configuring compilers
-if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
-	# using Clang
-	set(CMAKE_CXX_FLAGS "-Wall -Wno-unknown-pragmas -Wno-unneeded-internal-declaration")
-	message(STATUS "OpenMP parallelization not available using clang++")
-elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
-	# using GCC
-	set(CMAKE_CXX_FLAGS "-Wall -fopenmp -pedantic") 
-elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
-	# using Intel C++
-	set(CMAKE_CXX_FLAGS "-static-intel -wd10237 -Wall -openmp -ipo")
-elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
-	# using Visual Studio C++
+  message(STATUS "Configuring OSRM in release mode")
+  # Check if LTO is available
+  set(LTO_FLAGS "")
+  CHECK_CXX_COMPILER_FLAG("-flto" HAS_LTO_FLAG)
+  if (HAS_LTO_FLAG)
+    set(LTO_FLAGS "${LTO_FLAGS} -flto")
+
+    # Since gcc 4.9 the LTO format is non-standart ('slim'), so we need to use the build-in tools
+    if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND
+        NOT "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.9.0")
+      message(STATUS "Using gcc specific binutils for LTO.")
+      set(CMAKE_AR     "/usr/bin/gcc-ar")
+      set(CMAKE_RANLIB "/usr/bin/gcc-ranlib")
+    endif()
+  endif (HAS_LTO_FLAG)
 endif()
 
+# Configuring compilers
+if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+  # using Clang
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -pedantic -fPIC")
+elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
+  # using GCC
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -fPIC")
+  if (WIN32) # using mingw
+    add_definitions(-DM_PI=3.141592653589793238462643383) # define M_PI
+    add_definitions(-DWIN32)
+    SET(OPTIONAL_SOCKET_LIBS ws2_32 wsock32)
+    SET(OPTIONAL_OMP_LIB gomp)
+  endif()
+elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
+  # using Intel C++
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -ipo -fPIC")
+elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+  # using Visual Studio C++
+  set(BOOST_COMPONENTS ${BOOST_COMPONENTS} date_time chrono zlib)
+  add_definitions(-D_CRT_SECURE_NO_WARNINGS)
+  add_definitions(-DNOMINMAX) # avoid min and max macros that can break compilation
+  add_definitions(-D_USE_MATH_DEFINES) # define M_PI
+  add_definitions(-D_WIN32_WINNT=0x0501)
+endif()
+
+# disable partitioning of LTO process when possible (fixes Debian issues)
+set(LTO_PARTITION_FLAGS "")
+CHECK_CXX_COMPILER_FLAG("-flto-partition=none" HAS_LTO_PARTITION_FLAG)
+if    (HAS_LTO_PARTITION_FLAG)
+  set(LTO_PARTITION_FLAGS "${LTO_PARTITION_FLAGS} -flto-partition=none")
+endif (HAS_LTO_PARTITION_FLAG)
+
+# Add Link-Time-Optimization flags, if supported (GCC >= 4.7) and enabled
+set(CMAKE_CXX_FLAGS           "${CMAKE_CXX_FLAGS}           ${LTO_FLAGS}")
+set(CMAKE_EXE_LINKER_FLAGS    "${CMAKE_EXE_LINKER_FLAGS}    ${LTO_FLAGS} ${LTO_PARTITION_FLAGS}")
+set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LTO_FLAGS} ${LTO_PARTITION_FLAGS}")
+
+# Activate C++11
+if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+  ADD_DEFINITIONS(-std=c++11)
+endif()
+
+# Configuring other platform dependencies
 if(APPLE)
-	SET(CMAKE_OSX_ARCHITECTURES "x86_64")
-	message("Set Architecture to x64 on OS X")
+  set(CMAKE_OSX_ARCHITECTURES "x86_64")
+  message(STATUS "Set Architecture to x64 on OS X")
+  exec_program(uname ARGS -v  OUTPUT_VARIABLE DARWIN_VERSION)
+  string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
+  if(OSXLIBSTD)
+    message(STATUS "linking against ${OSXLIBSTD}")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${OSXLIBSTD}")
+  elseif(DARWIN_VERSION GREATER 12)
+    message(STATUS "linking against libc++")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
+  endif()
+endif()
+
+if(UNIX AND NOT APPLE)
+  target_link_libraries(osrm-prepare rt)
+  target_link_libraries(osrm-datastore rt)
+  target_link_libraries(OSRM rt)
 endif()
 
 #Check Boost
-set(BOOST_MIN_VERSION "1.44.0")
-find_package( Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED )
-if (NOT Boost_FOUND)
-      message(FATAL_ERROR "Fatal error: Boost (version >= 1.44.0) required.\n")
-endif (NOT Boost_FOUND)
+set(BOOST_MIN_VERSION "1.49.0")
+find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED)
+if(NOT Boost_FOUND)
+  message(FATAL_ERROR "Fatal error: Boost (version >= 1.49.0) required.\n")
+endif()
 include_directories(${Boost_INCLUDE_DIRS})
-target_link_libraries( osrm-extract ${Boost_LIBRARIES} )
-target_link_libraries( osrm-prepare ${Boost_LIBRARIES} )
-target_link_libraries( osrm-routed ${Boost_LIBRARIES} )
-
-find_package ( BZip2 REQUIRED )
-include_directories(${BZIP_INCLUDE_DIRS})
-target_link_libraries (osrm-extract ${BZIP2_LIBRARIES})
 
-find_package( ZLIB REQUIRED )
-target_link_libraries (osrm-extract ${ZLIB_LIBRARY})
-target_link_libraries (osrm-routed ${ZLIB_LIBRARY})
+target_link_libraries(OSRM ${Boost_LIBRARIES} COORDLIB)
+target_link_libraries(osrm-extract ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION COORDLIB IMPORT)
+target_link_libraries(osrm-prepare ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION COORDLIB IMPORT)
+target_link_libraries(osrm-routed ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM FINGERPRINT GITDESCRIPTION)
+target_link_libraries(osrm-datastore ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION COORDLIB)
 
-find_package( Threads REQUIRED )
-target_link_libraries (osrm-extract ${Threads_LIBRARY})
+find_package(Threads REQUIRED)
+target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT} ${OPTIONAL_OMP_LIB})
+target_link_libraries(osrm-datastore ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries(OSRM ${CMAKE_THREAD_LIBS_INIT})
 
-find_package( Lua51 REQUIRED ) 
-include_directories(${LUA_INCLUDE_DIR})
-target_link_libraries( osrm-extract ${LUA_LIBRARY} )
-target_link_libraries( osrm-prepare ${LUA_LIBRARY} )
+find_package(TBB REQUIRED)
+if(WIN32 AND CMAKE_BUILD_TYPE MATCHES Debug)
+  set(TBB_LIBRARIES ${TBB_DEBUG_LIBRARIES})
+endif()
+target_link_libraries(osrm-datastore ${TBB_LIBRARIES})
+target_link_libraries(osrm-extract ${TBB_LIBRARIES})
+target_link_libraries(osrm-prepare ${TBB_LIBRARIES})
+target_link_libraries(osrm-routed ${TBB_LIBRARIES})
+include_directories(${TBB_INCLUDE_DIR})
 
-find_package( LibXml2 REQUIRED )
-include_directories(${LIBXML2_INCLUDE_DIR})
-target_link_libraries (osrm-extract ${LIBXML2_LIBRARIES})
+find_package(Lua52)
+if(NOT LUA52_FOUND)
+  find_package(Lua51 REQUIRED)
+  if(NOT APPLE)
+    find_package(LuaJIT 5.1)
+  endif()
+else()
+  if(NOT APPLE)
+    find_package(LuaJIT 5.2)
+  endif()
+endif()
 
 find_package( Luabind REQUIRED )
 include_directories(${LUABIND_INCLUDE_DIR})
-target_link_libraries (osrm-extract ${LUABIND_LIBRARY})
-target_link_libraries (osrm-prepare ${LUABIND_LIBRARY})
+target_link_libraries(osrm-extract ${LUABIND_LIBRARY})
+target_link_libraries(osrm-prepare ${LUABIND_LIBRARY})
 
-find_package( Protobuf REQUIRED )
-include_directories(${PROTOBUF_INCLUDE_DIRS})
-target_link_libraries (osrm-extract ${PROTOBUF_LIBRARY})
-target_link_libraries (osrm-prepare ${PROTOBUF_LIBRARY})
+if( LUAJIT_FOUND )
+  target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES})
+  target_link_libraries(osrm-prepare ${LUAJIT_LIBRARIES})
+else()
+  target_link_libraries(osrm-extract ${LUA_LIBRARY})
+  target_link_libraries(osrm-prepare ${LUA_LIBRARY})
+endif()
+include_directories(${LUA_INCLUDE_DIR})
+
+find_package(LibXml2 REQUIRED)
+include_directories(${LIBXML2_INCLUDE_DIR})
+target_link_libraries(osrm-extract ${LIBXML2_LIBRARIES})
 
 find_package( STXXL REQUIRED )
 include_directories(${STXXL_INCLUDE_DIR})
-target_link_libraries (osrm-extract ${STXXL_LIBRARY})
-target_link_libraries (osrm-prepare ${STXXL_LIBRARY})
+target_link_libraries(OSRM ${STXXL_LIBRARY})
+target_link_libraries(osrm-extract ${STXXL_LIBRARY})
+target_link_libraries(osrm-prepare ${STXXL_LIBRARY})
 
 find_package( OSMPBF REQUIRED )
 include_directories(${OSMPBF_INCLUDE_DIR})
-target_link_libraries (osrm-extract ${OSMPBF_LIBRARY})
-target_link_libraries (osrm-prepare ${OSMPBF_LIBRARY})
+target_link_libraries(osrm-extract ${OSMPBF_LIBRARY})
+target_link_libraries(osrm-prepare ${OSMPBF_LIBRARY})
+
+find_package(Protobuf REQUIRED)
+include_directories(${PROTOBUF_INCLUDE_DIRS})
+target_link_libraries(osrm-extract ${PROTOBUF_LIBRARY})
+target_link_libraries(osrm-prepare ${PROTOBUF_LIBRARY})
+
+find_package(BZip2 REQUIRED)
+include_directories(${BZIP_INCLUDE_DIRS})
+target_link_libraries(osrm-extract ${BZIP2_LIBRARIES})
+
+find_package(ZLIB REQUIRED)
+include_directories(${ZLIB_INCLUDE_DIRS})
+target_link_libraries(osrm-extract ${ZLIB_LIBRARY})
+target_link_libraries(osrm-routed ${ZLIB_LIBRARY})
 
 if(WITH_TOOLS)
-	message("-- Activating OSRM internal tools")
-	find_package( GDAL )
-	if(GDAL_FOUND)
-		add_executable(osrm-components Tools/componentAnalysis.cpp)
-		include_directories(${GDAL_INCLUDE_DIR})
-		target_link_libraries( osrm-components ${GDAL_LIBRARIES} )
-		target_link_libraries( osrm-components ${Boost_LIBRARIES} )
-	endif(GDAL_FOUND)
-endif(WITH_TOOLS)
+  message(STATUS "Activating OSRM internal tools")
+  find_package(GDAL)
+  if(GDAL_FOUND)
+    add_executable(osrm-components Tools/components.cpp)
+    target_link_libraries(osrm-components ${TBB_LIBRARIES} IMPORT)
+    include_directories(${GDAL_INCLUDE_DIR})
+    target_link_libraries(
+      osrm-components
+      ${GDAL_LIBRARIES} ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION COORDLIB)
+  else()
+    message(FATAL_ERROR "libgdal and/or development headers not found")
+  endif()
+  add_executable(osrm-cli Tools/simpleclient.cpp)
+  target_link_libraries(osrm-cli ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM FINGERPRINT GITDESCRIPTION)
+  target_link_libraries(osrm-cli ${TBB_LIBRARIES})
+  add_executable(osrm-io-benchmark Tools/io-benchmark.cpp)
+  target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION)
+  add_executable(osrm-unlock-all Tools/unlock_all_mutexes.cpp)
+  target_link_libraries(osrm-unlock-all ${Boost_LIBRARIES} GITDESCRIPTION)
+  if(UNIX AND NOT APPLE)
+    target_link_libraries(osrm-unlock-all rt)
+  endif()
+endif()
+
+file(GLOB InstallGlob Include/osrm/*.h Library/OSRM.h)
+
+# Add RPATH info to executables so that when they are run after being installed
+# (i.e., from /usr/local/bin/) the linker can find library dependencies. For
+# more info see http://www.cmake.org/Wiki/CMake_RPATH_handling
+set_property(TARGET osrm-extract PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
+set_property(TARGET osrm-prepare PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
+set_property(TARGET osrm-datastore PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
+set_property(TARGET osrm-routed PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
+
+install(FILES ${InstallGlob} DESTINATION include/osrm)
+install(TARGETS osrm-extract DESTINATION bin)
+install(TARGETS osrm-prepare DESTINATION bin)
+install(TARGETS osrm-datastore DESTINATION bin)
+install(TARGETS osrm-routed DESTINATION bin)
+install(TARGETS OSRM DESTINATION lib)
+list(GET Boost_LIBRARIES 1 BOOST_LIBRARY_FIRST)
+get_filename_component(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_FIRST}" PATH)
+set(BOOST_LIBRARY_LISTING "-L${BOOST_LIBRARY_LISTING}")
+foreach (lib ${Boost_LIBRARIES})
+  get_filename_component(BOOST_LIBRARY_NAME "${lib}" NAME_WE)
+  string(REPLACE "lib" "" BOOST_LIBRARY_NAME ${BOOST_LIBRARY_NAME})
+  set(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_LISTING} -l${BOOST_LIBRARY_NAME}")
+endforeach ()
+
+configure_file(${CMAKE_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
+install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION lib/pkgconfig)
diff --git a/Contractor/ContractionCleanup.h b/Contractor/ContractionCleanup.h
deleted file mode 100644
index e42dad3..0000000
--- a/Contractor/ContractionCleanup.h
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef CONTRACTIONCLEANUP_H_INCLUDED
-#define CONTRACTIONCLEANUP_H_INCLUDED
-
-#include <algorithm>
-#ifndef _WIN32
-#include <sys/time.h>
-#endif
-#include "Contractor.h"
-
-class ContractionCleanup {
-private:
-
-    struct _CleanupHeapData {
-        NodeID parent;
-        _CleanupHeapData( NodeID p ) {
-            parent = p;
-        }
-    };
-    typedef BinaryHeap< NodeID, NodeID, int, _CleanupHeapData > _Heap;
-
-    struct _ThreadData {
-        _Heap* _heapForward;
-        _Heap* _heapBackward;
-        _ThreadData( NodeID nodes ) {
-            _heapBackward = new _Heap(nodes);
-            _heapForward = new _Heap(nodes);
-        }
-        ~_ThreadData() {
-            delete _heapBackward;
-            delete _heapForward;
-        }
-    };
-
-public:
-
-    struct Edge {
-        NodeID source;
-        NodeID target;
-        struct EdgeData {
-        	NodeID via;
-        	unsigned nameID;
-        	int distance;
-        	TurnInstruction turnInstruction;
-        	bool shortcut:1;
-        	bool forward:1;
-        	bool backward:1;
-        } data;
-        bool operator<( const Edge& right ) const {
-            if ( source != right.source )
-                return source < right.source;
-            return target < right.target;
-        }
-
-        //sorts by source and other attributes
-        static bool CompareBySource( const Edge& left, const Edge& right ) {
-            if ( left.source != right.source )
-                return left.source < right.source;
-            int l = ( left.data.forward ? -1 : 0 ) + ( left.data.backward ? -1 : 0 );
-            int r = ( right.data.forward ? -1 : 0 ) + ( right.data.backward ? -1 : 0 );
-            if ( l != r )
-                return l < r;
-            if ( left.target != right.target )
-                return left.target < right.target;
-            return left.data.distance < right.data.distance;
-        }
-
-        bool operator== ( const Edge& right ) const {
-            return ( source == right.source && target == right.target && data.distance == right.data.distance &&
-                    data.shortcut == right.data.shortcut && data.forward == right.data.forward && data.backward == right.data.backward
-                    && data.via == right.data.via && data.nameID == right.data.nameID
-                    );
-        }
-    };
-
-    ContractionCleanup( int numNodes, const std::vector< Edge >& edges ) {
-        _graph = edges;
-        _numNodes = numNodes;
-    }
-
-    ~ContractionCleanup() {
-
-    }
-
-    void Run() {
-        RemoveUselessShortcuts();
-    }
-
-    template< class EdgeT >
-    void GetData( std::vector< EdgeT >& edges ) {
-        for ( int edge = 0, endEdges = ( int ) _graph.size(); edge != endEdges; ++edge ) {
-            if(_graph[edge].data.forward || _graph[edge].data.backward) {
-                EdgeT newEdge;
-                newEdge.source = _graph[edge].source;
-                newEdge.target = _graph[edge].target;
-                newEdge.data = _graph[edge].data;
-                edges.push_back( newEdge );
-            }
-        }
-        sort( edges.begin(), edges.end() );
-    }
-
-private:
-
-    double _Timestamp() {
-        struct timeval tp;
-        gettimeofday(&tp, NULL);
-        return double(tp.tv_sec) + tp.tv_usec / 1000000.;
-    }
-
-    void BuildOutgoingGraph() {
-        //sort edges by source
-        sort( _graph.begin(), _graph.end(), Edge::CompareBySource );
-        try {
-            _firstEdge.resize( _numNodes + 1 );
-        } catch(...) {
-            ERR("Not enough RAM on machine");
-            return;
-        }
-        _firstEdge[0] = 0;
-        for ( NodeID i = 0, node = 0; i < ( NodeID ) _graph.size(); i++ ) {
-            while ( _graph[i].source != node )
-                _firstEdge[++node] = i;
-            if ( i == ( NodeID ) _graph.size() - 1 )
-                while ( node < _numNodes )
-                    _firstEdge[++node] = ( int ) _graph.size();
-        }
-    }
-
-    void RemoveUselessShortcuts() {
-        int maxThreads = omp_get_max_threads();
-        std::vector < _ThreadData* > threadData;
-        for ( int threadNum = 0; threadNum < maxThreads; ++threadNum ) {
-            threadData.push_back( new _ThreadData( _numNodes ) );
-        }
-
-        INFO("Scanning for useless shortcuts");
-        BuildOutgoingGraph();
-/*
-        #pragma omp parallel for
-        for ( int i = 0; i < ( int ) _graph.size(); i++ ) {
-            //only remove shortcuts
-            if ( !_graph[i].data.shortcut )
-                continue;
-
-            if ( _graph[i].data.forward ) {
-                int result = _ComputeDistance( _graph[i].source, _graph[i].target, threadData[omp_get_thread_num()] );
-                if ( result < _graph[i].data.distance ) {
-                    _graph[i].data.forward = false;
-                }
-            }
-            if ( _graph[i].data.backward ) {
-                int result = _ComputeDistance( _graph[i].target, _graph[i].source, threadData[omp_get_thread_num()] );
-                if ( result < _graph[i].data.distance ) {
-                    _graph[i].data.backward = false;
-                }
-            }
-        }
-*/
-        INFO("Removing edges");
-        int useful = 0;
-        for ( int i = 0; i < ( int ) _graph.size(); i++ ) {
-            if ( !_graph[i].data.forward && !_graph[i].data.backward && _graph[i].data.shortcut ) {
-                continue;
-            }
-            _graph[useful] = _graph[i];
-            useful++;
-        }
-        INFO("Removed " << _graph.size() - useful << " useless shortcuts");
-        _graph.resize( useful );
-
-        for ( int threadNum = 0; threadNum < maxThreads; ++threadNum ) {
-            delete threadData[threadNum];
-        }
-    }
-
-    void _ComputeStep( _Heap* heapForward, _Heap* heapBackward, bool forwardDirection, NodeID* middle, int* targetDistance ) {
-
-        const NodeID node = heapForward->DeleteMin();
-        const int distance = heapForward->GetKey( node );
-
-        if ( distance > *targetDistance ) {
-            heapForward->DeleteAll();
-            return;
-        }
-
-        if ( heapBackward->WasInserted( node ) ) {
-            const int newDistance = heapBackward->GetKey( node ) + distance;
-            if ( newDistance < *targetDistance ) {
-                *middle = node;
-                *targetDistance = newDistance;
-            }
-        }
-
-       for ( int edge = _firstEdge[node], endEdges = _firstEdge[node + 1]; edge != endEdges; ++edge ) {
-            const NodeID to = _graph[edge].target;
-            const int edgeWeight = _graph[edge].data.distance;
-            assert( edgeWeight > 0 );
-            const int toDistance = distance + edgeWeight;
-
-            if ( (forwardDirection ? _graph[edge].data.forward : _graph[edge].data.backward ) ) {
-                //New Node discovered -> Add to Heap + Node Info Storage
-                if ( !heapForward->WasInserted( to ) )
-                    heapForward->Insert( to, toDistance, node );
-
-                //Found a shorter Path -> Update distance
-                else if ( toDistance < heapForward->GetKey( to ) ) {
-                    heapForward->DecreaseKey( to, toDistance );
-                    //new parent
-                    heapForward->GetData( to ) = node;
-                }
-            }
-        }
-    }
-
-    int _ComputeDistance( NodeID source, NodeID target, _ThreadData * data ) {
-        data->_heapForward->Clear();
-        data->_heapBackward->Clear();
-        //insert source into heap
-        data->_heapForward->Insert( source, 0, source );
-        data->_heapBackward->Insert( target, 0, target );
-
-        int targetDistance = std::numeric_limits< int >::max();
-        NodeID middle = std::numeric_limits<NodeID>::max();
-
-        while ( data->_heapForward->Size() + data->_heapBackward->Size() > 0 ) {
-            if ( data->_heapForward->Size() > 0 ) {
-                _ComputeStep( data->_heapForward, data->_heapBackward, true, &middle, &targetDistance );
-            }
-
-            if ( data->_heapBackward->Size() > 0 ) {
-                _ComputeStep( data->_heapBackward, data->_heapForward, false, &middle, &targetDistance );
-            }
-        }
-        return targetDistance;
-    }
-    NodeID _numNodes;
-    std::vector< Edge > _graph;
-    std::vector< unsigned > _firstEdge;
-};
-
-#endif // CONTRACTIONCLEANUP_H_INCLUDED
diff --git a/Contractor/Contractor.h b/Contractor/Contractor.h
index 35d2aa2..a879607 100644
--- a/Contractor/Contractor.h
+++ b/Contractor/Contractor.h
@@ -1,25 +1,32 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef CONTRACTOR_H_INCLUDED
-#define CONTRACTOR_H_INCLUDED
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef CONTRACTOR_H
+#define CONTRACTOR_H
 
 #include "TemporaryStorage.h"
 #include "../DataStructures/BinaryHeap.h"
@@ -28,396 +35,510 @@ or see http://www.gnu.org/licenses/agpl.txt.
 #include "../DataStructures/Percent.h"
 #include "../DataStructures/XORFastHash.h"
 #include "../DataStructures/XORFastHashStorage.h"
-#include "../Util/OpenMPWrapper.h"
+#include "../Util/SimpleLogger.h"
 #include "../Util/StringUtil.h"
+#include "../Util/TimingUtil.h"
 
 #include <boost/assert.hpp>
-#include <boost/foreach.hpp>
-#include <boost/lambda/lambda.hpp>
-#include <boost/make_shared.hpp>
-#include <boost/shared_ptr.hpp>
 
-#include <cfloat>
-#include <ctime>
+#include <tbb/enumerable_thread_specific.h>
+#include <tbb/parallel_for.h>
+#include <tbb/parallel_sort.h>
 
 #include <algorithm>
 #include <limits>
 #include <vector>
 
-class Contractor {
+class Contractor
+{
 
-private:
-    struct _ContractorEdgeData {
-        _ContractorEdgeData() :
-            distance(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0), originalViaNodeID(false) {}
-        _ContractorEdgeData( unsigned _distance, unsigned _originalEdges, unsigned _id, bool _shortcut, bool _forward, bool _backward) :
-            distance(_distance), id(_id), originalEdges(std::min((unsigned)1<<28, _originalEdges) ), shortcut(_shortcut), forward(_forward), backward(_backward), originalViaNodeID(false) {}
+  private:
+    struct ContractorEdgeData
+    {
+        ContractorEdgeData()
+            : distance(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0),
+              is_original_via_node_ID(false)
+        {
+        }
+        ContractorEdgeData(unsigned _distance,
+                           unsigned _originalEdges,
+                           unsigned _id,
+                           bool _shortcut,
+                           bool _forward,
+                           bool _backward)
+            : distance(_distance), id(_id),
+              originalEdges(std::min((unsigned)1 << 28, _originalEdges)), shortcut(_shortcut),
+              forward(_forward), backward(_backward), is_original_via_node_ID(false)
+        {
+        }
         unsigned distance;
         unsigned id;
-        unsigned originalEdges:28;
-        bool shortcut:1;
-        bool forward:1;
-        bool backward:1;
-        bool originalViaNodeID:1;
+        unsigned originalEdges : 28;
+        bool shortcut : 1;
+        bool forward : 1;
+        bool backward : 1;
+        bool is_original_via_node_ID : 1;
     } data;
 
-    struct _HeapData {
+    struct ContractorHeapData
+    {
         short hop;
         bool target;
-        _HeapData() : hop(0), target(false) {}
-        _HeapData( short h, bool t ) : hop(h), target(t) {}
+        ContractorHeapData() : hop(0), target(false) {}
+        ContractorHeapData(short h, bool t) : hop(h), target(t) {}
     };
 
-    typedef DynamicGraph< _ContractorEdgeData > _DynamicGraph;
-    //    typedef BinaryHeap< NodeID, NodeID, int, _HeapData, ArrayStorage<NodeID, NodeID> > _Heap;
-    typedef BinaryHeap< NodeID, NodeID, int, _HeapData, XORFastHashStorage<NodeID, NodeID> > _Heap;
-    typedef _DynamicGraph::InputEdge _ContractorEdge;
-
-    struct _ThreadData {
-        _Heap heap;
-        std::vector< _ContractorEdge > insertedEdges;
-        std::vector< NodeID > neighbours;
-        _ThreadData( NodeID nodes ): heap( nodes ) { }
+    typedef DynamicGraph<ContractorEdgeData> ContractorGraph;
+    //    typedef BinaryHeap< NodeID, NodeID, int, ContractorHeapData, ArrayStorage<NodeID, NodeID>
+    //    > ContractorHeap;
+    typedef BinaryHeap<NodeID, NodeID, int, ContractorHeapData, XORFastHashStorage<NodeID, NodeID>>
+    ContractorHeap;
+    typedef ContractorGraph::InputEdge ContractorEdge;
+
+    struct ContractorThreadData
+    {
+        ContractorHeap heap;
+        std::vector<ContractorEdge> inserted_edges;
+        std::vector<NodeID> neighbours;
+        ContractorThreadData(NodeID nodes) : heap(nodes) {}
     };
 
-    struct _PriorityData {
+    struct NodePriorityData
+    {
         int depth;
-        _PriorityData() : depth(0) { }
+        NodePriorityData() : depth(0) {}
     };
 
-    struct _ContractionInformation {
-        int edgesDeleted;
-        int edgesAdded;
-        int originalEdgesDeleted;
-        int originalEdgesAdded;
-        _ContractionInformation() : edgesDeleted(0), edgesAdded(0), originalEdgesDeleted(0), originalEdgesAdded(0) {}
+    struct ContractionStats
+    {
+        int edges_deleted_count;
+        int edges_added_count;
+        int original_edges_deleted_count;
+        int original_edges_added_count;
+        ContractionStats()
+            : edges_deleted_count(0), edges_added_count(0), original_edges_deleted_count(0),
+              original_edges_added_count(0)
+        {
+        }
     };
 
-    struct _RemainingNodeData {
-        _RemainingNodeData() : id (0), isIndependent(false) {}
-        NodeID id:31;
-        bool isIndependent:1;
+    struct RemainingNodeData
+    {
+        RemainingNodeData() : id(0), is_independent(false) {}
+        NodeID id : 31;
+        bool is_independent : 1;
     };
 
-    struct _NodePartitionor {
-        inline bool operator()(_RemainingNodeData & nodeData ) const {
-            return !nodeData.isIndependent;
-        }
-    };
 
-public:
+    struct ThreadDataContainer
+    {
+        ThreadDataContainer(int number_of_nodes) : number_of_nodes(number_of_nodes)  {}
+
+        inline ContractorThreadData* getThreadData()
+        {
+            bool exists = false;
+            auto& ref = data.local(exists);
+            if (!exists)
+            {
+                ref = std::make_shared<ContractorThreadData>(number_of_nodes);
+            }
+
+            return ref.get();
+        }
 
-    template<class ContainerT >
-    Contractor( int nodes, ContainerT& inputEdges) {
-        std::vector< _ContractorEdge > edges;
-        edges.reserve(inputEdges.size()*2);
+        int number_of_nodes;
+        typedef tbb::enumerable_thread_specific<std::shared_ptr<ContractorThreadData>> EnumerableThreadData;
+        EnumerableThreadData data;
+    };
 
-        typename ContainerT::deallocation_iterator diter = inputEdges.dbegin();
-        typename ContainerT::deallocation_iterator dend  = inputEdges.dend();
+  public:
+    template <class ContainerT> Contractor(int nodes, ContainerT &input_edge_list)
+    {
+        std::vector<ContractorEdge> edges;
+        edges.reserve(input_edge_list.size() * 2);
+        temp_edge_counter = 0;
 
-        _ContractorEdge newEdge;
-        while(diter!=dend) {
-            newEdge.source = diter->source();
-            newEdge.target = diter->target();
-            newEdge.data = _ContractorEdgeData( (std::max)((int)diter->weight(), 1 ),  1,  diter->id(),  false,  diter->isForward(),  diter->isBackward());
+        auto diter = input_edge_list.dbegin();
+        auto dend = input_edge_list.dend();
 
-            BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" );
+        ContractorEdge new_edge;
+        while (diter != dend)
+        {
+            new_edge.source = diter->source;
+            new_edge.target = diter->target;
+            new_edge.data = { static_cast<unsigned int>(std::max(diter->weight, 1)),
+                              1,
+                              diter->edge_id,
+                              false,
+                              diter->forward,
+                              diter->backward};
+
+            BOOST_ASSERT_MSG(new_edge.data.distance > 0, "edge distance < 1");
 #ifndef NDEBUG
-            if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
-                WARN("Edge weight large -> " << newEdge.data.distance);
+            if (new_edge.data.distance > 24 * 60 * 60 * 10)
+            {
+                SimpleLogger().Write(logWARNING) << "Edge weight large -> "
+                                                 << new_edge.data.distance;
             }
 #endif
-            edges.push_back( newEdge );
-            std::swap( newEdge.source, newEdge.target );
-            newEdge.data.forward = diter->isBackward();
-            newEdge.data.backward = diter->isForward();
-            edges.push_back( newEdge );
+            edges.push_back(new_edge);
+            std::swap(new_edge.source, new_edge.target);
+            new_edge.data.forward = diter->backward;
+            new_edge.data.backward = diter->forward;
+            edges.push_back(new_edge);
             ++diter;
         }
-        //clear input vector and trim the current set of edges with the well-known swap trick
-        inputEdges.clear();
-        sort( edges.begin(), edges.end() );
+        // clear input vector
+        edges.shrink_to_fit();
+        input_edge_list.clear();
+        tbb::parallel_sort(edges.begin(), edges.end());
         NodeID edge = 0;
-        for ( NodeID i = 0; i < edges.size(); ) {
+        for (NodeID i = 0; i < edges.size();)
+        {
             const NodeID source = edges[i].source;
             const NodeID target = edges[i].target;
             const NodeID id = edges[i].data.id;
-            //remove eigenloops
-            if ( source == target ) {
+            // remove eigenloops
+            if (source == target)
+            {
                 i++;
                 continue;
             }
-            _ContractorEdge forwardEdge;
-            _ContractorEdge backwardEdge;
-            forwardEdge.source = backwardEdge.source = source;
-            forwardEdge.target = backwardEdge.target = target;
-            forwardEdge.data.forward = backwardEdge.data.backward = true;
-            forwardEdge.data.backward = backwardEdge.data.forward = false;
-            forwardEdge.data.shortcut = backwardEdge.data.shortcut = false;
-            forwardEdge.data.id = backwardEdge.data.id = id;
-            forwardEdge.data.originalEdges = backwardEdge.data.originalEdges = 1;
-            forwardEdge.data.distance = backwardEdge.data.distance = std::numeric_limits< int >::max();
-            //remove parallel edges
-            while ( i < edges.size() && edges[i].source == source && edges[i].target == target ) {
-            	if ( edges[i].data.forward) {
-                    forwardEdge.data.distance = std::min( edges[i].data.distance, forwardEdge.data.distance );
+            ContractorEdge forward_edge;
+            ContractorEdge reverse_edge;
+            forward_edge.source = reverse_edge.source = source;
+            forward_edge.target = reverse_edge.target = target;
+            forward_edge.data.forward = reverse_edge.data.backward = true;
+            forward_edge.data.backward = reverse_edge.data.forward = false;
+            forward_edge.data.shortcut = reverse_edge.data.shortcut = false;
+            forward_edge.data.id = reverse_edge.data.id = id;
+            forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1;
+            forward_edge.data.distance = reverse_edge.data.distance =
+                std::numeric_limits<int>::max();
+            // remove parallel edges
+            while (i < edges.size() && edges[i].source == source && edges[i].target == target)
+            {
+                if (edges[i].data.forward)
+                {
+                    forward_edge.data.distance =
+                        std::min(edges[i].data.distance, forward_edge.data.distance);
                 }
-                if ( edges[i].data.backward) {
-                    backwardEdge.data.distance = std::min( edges[i].data.distance, backwardEdge.data.distance );
+                if (edges[i].data.backward)
+                {
+                    reverse_edge.data.distance =
+                        std::min(edges[i].data.distance, reverse_edge.data.distance);
                 }
                 ++i;
             }
-            //merge edges (s,t) and (t,s) into bidirectional edge
-            if ( forwardEdge.data.distance == backwardEdge.data.distance ) {
-                if ( (int)forwardEdge.data.distance != std::numeric_limits< int >::max() ) {
-                    forwardEdge.data.backward = true;
-                    edges[edge++] = forwardEdge;
+            // merge edges (s,t) and (t,s) into bidirectional edge
+            if (forward_edge.data.distance == reverse_edge.data.distance)
+            {
+                if ((int)forward_edge.data.distance != std::numeric_limits<int>::max())
+                {
+                    forward_edge.data.backward = true;
+                    edges[edge++] = forward_edge;
                 }
-            } else { //insert seperate edges
-                if ( ((int)forwardEdge.data.distance) != std::numeric_limits< int >::max() ) {
-                    edges[edge++] = forwardEdge;
+            }
+            else
+            { // insert seperate edges
+                if (((int)forward_edge.data.distance) != std::numeric_limits<int>::max())
+                {
+                    edges[edge++] = forward_edge;
                 }
-                if ( (int)backwardEdge.data.distance != std::numeric_limits< int >::max() ) {
-                    edges[edge++] = backwardEdge;
+                if ((int)reverse_edge.data.distance != std::numeric_limits<int>::max())
+                {
+                    edges[edge++] = reverse_edge;
                 }
             }
         }
-        std::cout << "merged " << edges.size() - edge << " edges out of " << edges.size() << std::endl;
-        edges.resize( edge );
-        _graph = boost::make_shared<_DynamicGraph>( nodes, edges );
+        std::cout << "merged " << edges.size() - edge << " edges out of " << edges.size()
+                  << std::endl;
+        edges.resize(edge);
+        contractor_graph = std::make_shared<ContractorGraph>(nodes, edges);
         edges.clear();
-        std::vector<_ContractorEdge>().swap(edges);
+        edges.shrink_to_fit();
+
+        BOOST_ASSERT(0 == edges.capacity());
         //        unsigned maxdegree = 0;
         //        NodeID highestNode = 0;
         //
-        //        for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
-        //            unsigned degree = _graph->EndEdges(i) - _graph->BeginEdges(i);
+        //        for(unsigned i = 0; i < contractor_graph->GetNumberOfNodes(); ++i) {
+        //            unsigned degree = contractor_graph->EndEdges(i) -
+        //            contractor_graph->BeginEdges(i);
         //            if(degree > maxdegree) {
         //                maxdegree = degree;
         //                highestNode = i;
         //            }
         //        }
         //
-        //        INFO("edges at node with id " << highestNode << " has degree " << maxdegree);
-        //        for(unsigned i = _graph->BeginEdges(highestNode); i < _graph->EndEdges(highestNode); ++i) {
-        //            INFO(" ->(" << highestNode << "," << _graph->GetTarget(i) << "); via: " << _graph->GetEdgeData(i).via);
+        //        SimpleLogger().Write() << "edges at node with id " << highestNode << " has degree
+        //        " << maxdegree;
+        //        for(unsigned i = contractor_graph->BeginEdges(highestNode); i <
+        //        contractor_graph->EndEdges(highestNode); ++i) {
+        //            SimpleLogger().Write() << " ->(" << highestNode << "," <<
+        //            contractor_graph->GetTarget(i)
+        //            << "); via: " << contractor_graph->GetEdgeData(i).via;
         //        }
 
-        //Create temporary file
+        // Create temporary file
 
-        //        GetTemporaryFileName(temporaryEdgeStorageFilename);
-        temporaryStorageSlotID = TemporaryStorage::GetInstance().allocateSlot();
+        edge_storage_slot = TemporaryStorage::GetInstance().AllocateSlot();
         std::cout << "contractor finished initalization" << std::endl;
     }
 
-    ~Contractor() {
-        //Delete temporary file
-        //        remove(temporaryEdgeStorageFilename.c_str());
-        TemporaryStorage::GetInstance().deallocateSlot(temporaryStorageSlotID);
-    }
+    ~Contractor() { TemporaryStorage::GetInstance().DeallocateSlot(edge_storage_slot); }
 
-    void Run() {
-        const NodeID numberOfNodes = _graph->GetNumberOfNodes();
-        Percent p (numberOfNodes);
+    void Run()
+    {
+        // for the preperation we can use a big grain size, which is much faster (probably cache)
+        constexpr size_t InitGrainSize        = 100000;
+        constexpr size_t PQGrainSize          = 100000;
+        // auto_partitioner will automatically increase the blocksize if we have
+        // a lot of data. It is *important* for the last loop iterations
+        // (which have a very small dataset) that it is devisible.
+        constexpr size_t IndependentGrainSize = 1;
+        constexpr size_t ContractGrainSize    = 1;
+        constexpr size_t NeighboursGrainSize  = 1;
+        constexpr size_t DeleteGrainSize      = 1;
 
-        const unsigned maxThreads = omp_get_max_threads();
-        std::vector < _ThreadData* > threadData;
-        for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
-            threadData.push_back( new _ThreadData( numberOfNodes ) );
-        }
-        std::cout << "Contractor is using " << maxThreads << " threads" << std::endl;
+        const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
+        Percent p(number_of_nodes);
 
-        NodeID numberOfContractedNodes = 0;
-        std::vector< _RemainingNodeData > remainingNodes( numberOfNodes );
-        std::vector< float > nodePriority( numberOfNodes );
-        std::vector< _PriorityData > nodeData( numberOfNodes );
+        ThreadDataContainer thread_data_list(number_of_nodes);
+
+        NodeID number_of_contracted_nodes = 0;
+        std::vector<RemainingNodeData> remaining_nodes(number_of_nodes);
+        std::vector<float> node_priorities(number_of_nodes);
+        std::vector<NodePriorityData> node_data(number_of_nodes);
+
+
+        // initialize priorities in parallel
+        tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, InitGrainSize),
+            [&remaining_nodes](const tbb::blocked_range<int>& range)
+            {
+                for (int x = range.begin(); x != range.end(); ++x)
+                {
+                    remaining_nodes[x].id = x;
+                }
+            }
+        );
 
-        //initialize the variables
-#pragma omp parallel for schedule ( guided )
-        for ( int x = 0; x < ( int ) numberOfNodes; ++x ) {
-            remainingNodes[x].id = x;
-        }
 
         std::cout << "initializing elimination PQ ..." << std::flush;
-#pragma omp parallel
-        {
-            _ThreadData* data = threadData[omp_get_thread_num()];
-#pragma omp parallel for schedule ( guided )
-            for ( int x = 0; x < ( int ) numberOfNodes; ++x ) {
-                nodePriority[x] = _Evaluate( data, &nodeData[x], x );
+        tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, PQGrainSize),
+            [this, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range<int>& range)
+            {
+                ContractorThreadData *data = thread_data_list.getThreadData();
+                for (int x = range.begin(); x != range.end(); ++x)
+                {
+                    node_priorities[x] = this->EvaluateNodePriority(data, &node_data[x], x);
+                }
             }
-        }
-        std::cout << "ok" << std::endl << "preprocessing " << numberOfNodes << " nodes ..." << std::flush;
-
-        bool flushedContractor = false;
-        while ( numberOfNodes > 2 && numberOfContractedNodes < numberOfNodes ) {
-            if(!flushedContractor && (numberOfContractedNodes > (numberOfNodes*0.65) ) ){
-                DeallocatingVector<_ContractorEdge> newSetOfEdges; //this one is not explicitely cleared since it goes out of scope anywa
-                std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush;
-
-                //Delete old heap data to free memory that we need for the coming operations
-                BOOST_FOREACH(_ThreadData * data, threadData)
-                	delete data;
-                threadData.clear();
-
-
-                //Create new priority array
-                std::vector<float> newNodePriority(remainingNodes.size());
-                //this map gives the old IDs from the new ones, necessary to get a consistent graph at the end of contraction
-                oldNodeIDFromNewNodeIDMap.resize(remainingNodes.size());
-                //this map gives the new IDs from the old ones, necessary to remap targets from the remaining graph
-                std::vector<NodeID> newNodeIDFromOldNodeIDMap(numberOfNodes, UINT_MAX);
-
-                //build forward and backward renumbering map and remap ids in remainingNodes and Priorities.
-                for(unsigned newNodeID = 0; newNodeID < remainingNodes.size(); ++newNodeID) {
-                    //create renumbering maps in both directions
-                    oldNodeIDFromNewNodeIDMap[newNodeID] = remainingNodes[newNodeID].id;
-                    newNodeIDFromOldNodeIDMap[remainingNodes[newNodeID].id] = newNodeID;
-                    newNodePriority[newNodeID] = nodePriority[remainingNodes[newNodeID].id];
-                    remainingNodes[newNodeID].id = newNodeID;
+        );
+        std::cout << "ok" << std::endl << "preprocessing " << number_of_nodes << " nodes ..."
+                  << std::flush;
+
+        bool flushed_contractor = false;
+        while (number_of_nodes > 2 && number_of_contracted_nodes < number_of_nodes)
+        {
+            if (!flushed_contractor && (number_of_contracted_nodes > (number_of_nodes * 0.65)))
+            {
+                DeallocatingVector<ContractorEdge> new_edge_set; // this one is not explicitely
+                                                                 // cleared since it goes out of
+                                                                 // scope anywa
+                std::cout << " [flush " << number_of_contracted_nodes << " nodes] " << std::flush;
+
+                // Delete old heap data to free memory that we need for the coming operations
+                thread_data_list.data.clear();
+
+                // Create new priority array
+                std::vector<float> new_node_priority(remaining_nodes.size());
+                // this map gives the old IDs from the new ones, necessary to get a consistent graph
+                // at the end of contraction
+                orig_node_id_to_new_id_map.resize(remaining_nodes.size());
+                // this map gives the new IDs from the old ones, necessary to remap targets from the
+                // remaining graph
+                std::vector<NodeID> new_node_id_from_orig_id_map(number_of_nodes, UINT_MAX);
+
+                // build forward and backward renumbering map and remap ids in remaining_nodes and
+                // Priorities.
+                for (unsigned new_node_id = 0; new_node_id < remaining_nodes.size(); ++new_node_id)
+                {
+                    // create renumbering maps in both directions
+                    orig_node_id_to_new_id_map[new_node_id] = remaining_nodes[new_node_id].id;
+                    new_node_id_from_orig_id_map[remaining_nodes[new_node_id].id] = new_node_id;
+                    new_node_priority[new_node_id] =
+                        node_priorities[remaining_nodes[new_node_id].id];
+                    remaining_nodes[new_node_id].id = new_node_id;
                 }
-                TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
-                //Write dummy number of edges to temporary file
-                //        		std::ofstream temporaryEdgeStorage(temporaryEdgeStorageFilename.c_str(), std::ios::binary);
-                uint64_t initialFilePosition = tempStorage.tell(temporaryStorageSlotID);
-                unsigned numberOfTemporaryEdges = 0;
-                tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
-
-                //walk over all nodes
-                for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
-                    const NodeID start = i;
-                    for(_DynamicGraph::EdgeIterator currentEdge = _graph->BeginEdges(start); currentEdge < _graph->EndEdges(start); ++currentEdge) {
-                        _DynamicGraph::EdgeData & data = _graph->GetEdgeData(currentEdge);
-                        const NodeID target = _graph->GetTarget(currentEdge);
-                        if(UINT_MAX == newNodeIDFromOldNodeIDMap[i] ){
-                            //Save edges of this node w/o renumbering.
-                            tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&start,  sizeof(NodeID));
-                            tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&target, sizeof(NodeID));
-                            tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&data,   sizeof(_DynamicGraph::EdgeData));
-                            ++numberOfTemporaryEdges;
-                        }else {
-                            //node is not yet contracted.
-                            //add (renumbered) outgoing edges to new DynamicGraph.
-                            _ContractorEdge newEdge;
-                            newEdge.source = newNodeIDFromOldNodeIDMap[start];
-                            newEdge.target = newNodeIDFromOldNodeIDMap[target];
-                            newEdge.data = data;
-                            newEdge.data.originalViaNodeID = true;
-                            BOOST_ASSERT_MSG(
-                                UINT_MAX != newNodeIDFromOldNodeIDMap[start],
-                                "new start id not resolveable"
-                            );
-                            BOOST_ASSERT_MSG(
-                                UINT_MAX != newNodeIDFromOldNodeIDMap[target],
-                                "new target id not resolveable"
-                            );
-                            newSetOfEdges.push_back(newEdge);
+                TemporaryStorage &temporary_storage = TemporaryStorage::GetInstance();
+                // walk over all nodes
+                for (unsigned i = 0; i < contractor_graph->GetNumberOfNodes(); ++i)
+                {
+                    const NodeID source = i;
+                    for (auto current_edge : contractor_graph->GetAdjacentEdgeRange(source))
+                    {
+                        ContractorGraph::EdgeData &data =
+                            contractor_graph->GetEdgeData(current_edge);
+                        const NodeID target = contractor_graph->GetTarget(current_edge);
+                        if (UINT_MAX == new_node_id_from_orig_id_map[i])
+                        {
+                            // Save edges of this node w/o renumbering.
+                            temporary_storage.WriteToSlot(
+                                edge_storage_slot, (char *)&source, sizeof(NodeID));
+                            temporary_storage.WriteToSlot(
+                                edge_storage_slot, (char *)&target, sizeof(NodeID));
+                            temporary_storage.WriteToSlot(edge_storage_slot,
+                                                          (char *)&data,
+                                                          sizeof(ContractorGraph::EdgeData));
+                            ++temp_edge_counter;
+                        }
+                        else
+                        {
+                            // node is not yet contracted.
+                            // add (renumbered) outgoing edges to new DynamicGraph.
+                            ContractorEdge new_edge;
+                            new_edge.source = new_node_id_from_orig_id_map[source];
+                            new_edge.target = new_node_id_from_orig_id_map[target];
+                            new_edge.data = data;
+                            new_edge.data.is_original_via_node_ID = true;
+                            BOOST_ASSERT_MSG(UINT_MAX != new_node_id_from_orig_id_map[source],
+                                             "new source id not resolveable");
+                            BOOST_ASSERT_MSG(UINT_MAX != new_node_id_from_orig_id_map[target],
+                                             "new target id not resolveable");
+                            new_edge_set.push_back(new_edge);
                         }
                     }
                 }
-                //Note the number of temporarily stored edges
-                tempStorage.seek(temporaryStorageSlotID, initialFilePosition);
-                tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
-
-                //Delete map from old NodeIDs to new ones.
-                std::vector<NodeID>().swap(newNodeIDFromOldNodeIDMap);
-
-                //Replace old priorities array by new one
-                nodePriority.swap(newNodePriority);
-                //Delete old nodePriority vector
-                std::vector<float>().swap(newNodePriority);
-                //old Graph is removed
-                _graph.reset();
-
-                //create new graph
-                std::sort(newSetOfEdges.begin(), newSetOfEdges.end());
-                _graph = boost::make_shared<_DynamicGraph>(remainingNodes.size(), newSetOfEdges);
-
-                newSetOfEdges.clear();
-                flushedContractor = true;
-
-                //INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH!
-                //reinitialize heaps and ThreadData objects with appropriate size
-                for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
-                    threadData.push_back( new _ThreadData( _graph->GetNumberOfNodes() ) );
-                }
+
+                // Delete map from old NodeIDs to new ones.
+                new_node_id_from_orig_id_map.clear();
+                new_node_id_from_orig_id_map.shrink_to_fit();
+
+                // Replace old priorities array by new one
+                node_priorities.swap(new_node_priority);
+                // Delete old node_priorities vector
+                new_node_priority.clear();
+                new_node_priority.shrink_to_fit();
+                // old Graph is removed
+                contractor_graph.reset();
+
+                // create new graph
+                std::sort(new_edge_set.begin(), new_edge_set.end());
+                contractor_graph =
+                    std::make_shared<ContractorGraph>(remaining_nodes.size(), new_edge_set);
+
+                new_edge_set.clear();
+                flushed_contractor = true;
+
+                // INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH!
+                // reinitialize heaps and ThreadData objects with appropriate size
+                thread_data_list.number_of_nodes = contractor_graph->GetNumberOfNodes();
             }
 
-            const int last = ( int ) remainingNodes.size();
-#pragma omp parallel
-            {
-                //determine independent node set
-                _ThreadData* const data = threadData[omp_get_thread_num()];
-#pragma omp for schedule ( guided )
-                for ( int i = 0; i < last; ++i ) {
-                    const NodeID node = remainingNodes[i].id;
-                    remainingNodes[i].isIndependent = _IsIndependent( nodePriority/*, nodeData*/, data, node );
+            const int last = (int)remaining_nodes.size();
+            tbb::parallel_for(tbb::blocked_range<int>(0, last, IndependentGrainSize),
+                [this, &node_priorities, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range)
+                {
+                    ContractorThreadData *data = thread_data_list.getThreadData();
+                    // determine independent node set
+                    for (int i = range.begin(); i != range.end(); ++i)
+                    {
+                        const NodeID node = remaining_nodes[i].id;
+                        remaining_nodes[i].is_independent =
+                            this->IsNodeIndependent(node_priorities, data, node);
+                    }
                 }
-            }
-            _NodePartitionor functor;
-            const std::vector < _RemainingNodeData >::const_iterator first = stable_partition( remainingNodes.begin(), remainingNodes.end(), functor );
-            const int firstIndependent = first - remainingNodes.begin();
-            //contract independent nodes
-#pragma omp parallel
-            {
-                _ThreadData* data = threadData[omp_get_thread_num()];
-#pragma omp for schedule ( guided ) nowait
-                for ( int position = firstIndependent ; position < last; ++position ) {
-                    NodeID x = remainingNodes[position].id;
-                    _Contract< false > ( data, x );
-                    //nodePriority[x] = -1;
+            );
+
+            const auto first = stable_partition(remaining_nodes.begin(),
+                                                remaining_nodes.end(),
+                                                [](RemainingNodeData node_data)
+                                                { return !node_data.is_independent; });
+            const int first_independent_node = static_cast<int>(first - remaining_nodes.begin());
+
+            // contract independent nodes
+            tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, ContractGrainSize),
+                [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range)
+                {
+                    ContractorThreadData *data = thread_data_list.getThreadData();
+                    for (int position = range.begin(); position != range.end(); ++position)
+                    {
+                        const NodeID x = remaining_nodes[position].id;
+                        this->ContractNode<false>(data, x);
+                    }
+                }
+            );
+            // make sure we really sort each block
+            tbb::parallel_for(thread_data_list.data.range(),
+                [&](const ThreadDataContainer::EnumerableThreadData::range_type& range)
+                {
+                    for (auto& data : range)
+                        std::sort(data->inserted_edges.begin(),
+                                  data->inserted_edges.end());
+                }
+            );
+            tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, DeleteGrainSize),
+                [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range)
+                {
+                    ContractorThreadData *data = thread_data_list.getThreadData();
+                    for (int position = range.begin(); position != range.end(); ++position)
+                    {
+                        const NodeID x = remaining_nodes[position].id;
+                        this->DeleteIncomingEdges(data, x);
+                    }
                 }
+            );
 
-                std::sort( data->insertedEdges.begin(), data->insertedEdges.end() );
-            }
-#pragma omp parallel
+            // insert new edges
+            for (auto& data : thread_data_list.data)
             {
-                _ThreadData* data = threadData[omp_get_thread_num()];
-#pragma omp for schedule ( guided ) nowait
-                for ( int position = firstIndependent ; position < last; ++position ) {
-                    NodeID x = remainingNodes[position].id;
-                    _DeleteIncomingEdges( data, x );
-                }
-            }
-            //insert new edges
-            for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
-                _ThreadData& data = *threadData[threadNum];
-                BOOST_FOREACH(const _ContractorEdge& edge, data.insertedEdges) {
-                    _DynamicGraph::EdgeIterator currentEdgeID = _graph->FindEdge(edge.source, edge.target);
-                    if(currentEdgeID < _graph->EndEdges(edge.source) ) {
-                        _DynamicGraph::EdgeData & currentEdgeData = _graph->GetEdgeData(currentEdgeID);
-                        if( currentEdgeData.shortcut
-                                && edge.data.forward == currentEdgeData.forward
-                                && edge.data.backward == currentEdgeData.backward ) {
-                            currentEdgeData.distance = std::min(currentEdgeData.distance, edge.data.distance);
+                for (const ContractorEdge &edge : data->inserted_edges)
+                {
+                    const EdgeID current_edge_ID = contractor_graph->FindEdge(edge.source, edge.target);
+                    if (current_edge_ID < contractor_graph->EndEdges(edge.source))
+                    {
+                        ContractorGraph::EdgeData &current_data =
+                            contractor_graph->GetEdgeData(current_edge_ID);
+                        if (current_data.shortcut && edge.data.forward == current_data.forward &&
+                            edge.data.backward == current_data.backward &&
+                            edge.data.distance < current_data.distance)
+                        {
+                            // found a duplicate edge with smaller weight, update it.
+                            current_data = edge.data;
                             continue;
                         }
                     }
-                    _graph->InsertEdge( edge.source, edge.target, edge.data );
+                    contractor_graph->InsertEdge(edge.source, edge.target, edge.data);
                 }
-                data.insertedEdges.clear();
+                data->inserted_edges.clear();
             }
-            //update priorities
-#pragma omp parallel
-            {
-                _ThreadData* data = threadData[omp_get_thread_num()];
-#pragma omp for schedule ( guided ) nowait
-                for ( int position = firstIndependent ; position < last; ++position ) {
-                    NodeID x = remainingNodes[position].id;
-                    _UpdateNeighbours( nodePriority, nodeData, data, x );
+
+            tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, NeighboursGrainSize),
+                [this, &remaining_nodes, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range<int>& range)
+                {
+                    ContractorThreadData *data = thread_data_list.getThreadData();
+                    for (int position = range.begin(); position != range.end(); ++position)
+                    {
+                        NodeID x = remaining_nodes[position].id;
+                        this->UpdateNodeNeighbours(node_priorities, node_data, data, x);
+                    }
                 }
-            }
-            //remove contracted nodes from the pool
-            numberOfContractedNodes += last - firstIndependent;
-            remainingNodes.resize( firstIndependent );
-            std::vector< _RemainingNodeData>( remainingNodes ).swap( remainingNodes );
+            );
+
+            // remove contracted nodes from the pool
+            number_of_contracted_nodes += last - first_independent_node;
+            remaining_nodes.resize(first_independent_node);
+            remaining_nodes.shrink_to_fit();
             //            unsigned maxdegree = 0;
             //            unsigned avgdegree = 0;
             //            unsigned mindegree = UINT_MAX;
             //            unsigned quaddegree = 0;
             //
-            //            for(unsigned i = 0; i < remainingNodes.size(); ++i) {
-            //                unsigned degree = _graph->EndEdges(remainingNodes[i].first) - _graph->BeginEdges(remainingNodes[i].first);
+            //            for(unsigned i = 0; i < remaining_nodes.size(); ++i) {
+            //                unsigned degree = contractor_graph->EndEdges(remaining_nodes[i].first)
+            //                -
+            //                contractor_graph->BeginEdges(remaining_nodes[i].first);
             //                if(degree > maxdegree)
             //                    maxdegree = degree;
             //                if(degree < mindegree)
@@ -427,331 +548,431 @@ public:
             //                quaddegree += (degree*degree);
             //            }
             //
-            //            avgdegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
-            //            quaddegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
+            //            avgdegree /= std::max((unsigned)1,(unsigned)remaining_nodes.size() );
+            //            quaddegree /= std::max((unsigned)1,(unsigned)remaining_nodes.size() );
             //
-            //            INFO("rest: " << remainingNodes.size() << ", max: " << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ", quad: " << quaddegree);
+            //            SimpleLogger().Write() << "rest: " << remaining_nodes.size() << ", max: "
+            //            << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ",
+            //            quad: " << quaddegree;
 
-            p.printStatus(numberOfContractedNodes);
+            p.printStatus(number_of_contracted_nodes);
         }
-        BOOST_FOREACH(_ThreadData * data, threadData)
-        	delete data;
-        threadData.clear();
+
+        thread_data_list.data.clear();
     }
 
-    template< class Edge >
-    inline void GetEdges( DeallocatingVector< Edge >& edges ) {
-        Percent p (_graph->GetNumberOfNodes());
-        INFO("Getting edges of minimized graph");
-        NodeID numberOfNodes = _graph->GetNumberOfNodes();
-        if(_graph->GetNumberOfNodes()) {
-            for ( NodeID node = 0; node < numberOfNodes; ++node ) {
+    template <class Edge> inline void GetEdges(DeallocatingVector<Edge> &edges)
+    {
+        Percent p(contractor_graph->GetNumberOfNodes());
+        SimpleLogger().Write() << "Getting edges of minimized graph";
+        const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
+        if (contractor_graph->GetNumberOfNodes())
+        {
+            Edge new_edge;
+            for (NodeID node = 0; node < number_of_nodes; ++node)
+            {
                 p.printStatus(node);
-                for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; ++edge ) {
-                    const NodeID target = _graph->GetTarget( edge );
-                    const _DynamicGraph::EdgeData& data = _graph->GetEdgeData( edge );
-                    Edge newEdge;
-                    if(0 != oldNodeIDFromNewNodeIDMap.size()) {
-                        newEdge.source = oldNodeIDFromNewNodeIDMap[node];
-                        newEdge.target = oldNodeIDFromNewNodeIDMap[target];
-                    } else {
-                        newEdge.source = node;
-                        newEdge.target = target;
+                for (auto edge : contractor_graph->GetAdjacentEdgeRange(node))
+                {
+                    const NodeID target = contractor_graph->GetTarget(edge);
+                    const ContractorGraph::EdgeData &data = contractor_graph->GetEdgeData(edge);
+                    if (!orig_node_id_to_new_id_map.empty())
+                    {
+                        new_edge.source = orig_node_id_to_new_id_map[node];
+                        new_edge.target = orig_node_id_to_new_id_map[target];
+                    }
+                    else
+                    {
+                        new_edge.source = node;
+                        new_edge.target = target;
                     }
-                    BOOST_ASSERT_MSG(
-                        UINT_MAX != newEdge.source,
-                        "Source id invalid"
-                    );
-                    BOOST_ASSERT_MSG(
-                        UINT_MAX != newEdge.target,
-                        "Target id invalid"
-                    );
-                    newEdge.data.distance = data.distance;
-                    newEdge.data.shortcut = data.shortcut;
-                   if(!data.originalViaNodeID && oldNodeIDFromNewNodeIDMap.size()) {
-                        newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id];
-                    } else {
-                        newEdge.data.id = data.id;
+                    BOOST_ASSERT_MSG(UINT_MAX != new_edge.source, "Source id invalid");
+                    BOOST_ASSERT_MSG(UINT_MAX != new_edge.target, "Target id invalid");
+                    new_edge.data.distance = data.distance;
+                    new_edge.data.shortcut = data.shortcut;
+                    if (!data.is_original_via_node_ID && !orig_node_id_to_new_id_map.empty())
+                    {
+                        new_edge.data.id = orig_node_id_to_new_id_map[data.id];
                     }
-                    BOOST_ASSERT_MSG(
-                        newEdge.data.id <= INT_MAX, //2^31
-                        "edge id invalid"
-                    );
-                    newEdge.data.forward = data.forward;
-                    newEdge.data.backward = data.backward;
-                    edges.push_back( newEdge );
+                    else
+                    {
+                        new_edge.data.id = data.id;
+                    }
+                    BOOST_ASSERT_MSG(new_edge.data.id != INT_MAX, // 2^31
+                                     "edge id invalid");
+                    new_edge.data.forward = data.forward;
+                    new_edge.data.backward = data.backward;
+                    edges.push_back(new_edge);
                 }
             }
         }
-        _graph.reset();
-        std::vector<NodeID>().swap(oldNodeIDFromNewNodeIDMap);
-
-        TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
-        //Also get the edges from temporary storage
-        unsigned numberOfTemporaryEdges = 0;
-        tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
-        //loads edges of graph before renumbering, no need for further numbering action.
-        NodeID start;
+        contractor_graph.reset();
+        orig_node_id_to_new_id_map.clear();
+        orig_node_id_to_new_id_map.shrink_to_fit();
+
+        BOOST_ASSERT(0 == orig_node_id_to_new_id_map.capacity());
+        TemporaryStorage &temporary_storage = TemporaryStorage::GetInstance();
+        // loads edges of graph before renumbering, no need for further numbering action.
+        NodeID source;
         NodeID target;
-        //edges.reserve(edges.size()+numberOfTemporaryEdges);
-        _DynamicGraph::EdgeData data;
-        for(unsigned i = 0; i < numberOfTemporaryEdges; ++i) {
-            tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&start,  sizeof(NodeID));
-            tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&target, sizeof(NodeID));
-            tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&data,   sizeof(_DynamicGraph::EdgeData));
-            Edge newEdge;
-            newEdge.source =  start;
-            newEdge.target = target;
-            newEdge.data.distance = data.distance;
-            newEdge.data.shortcut = data.shortcut;
-            newEdge.data.id = data.id;
-            newEdge.data.forward = data.forward;
-            newEdge.data.backward = data.backward;
-            edges.push_back( newEdge );
+        ContractorGraph::EdgeData data;
+
+        Edge restored_edge;
+        for (unsigned i = 0; i < temp_edge_counter; ++i)
+        {
+            temporary_storage.ReadFromSlot(edge_storage_slot, (char *)&source, sizeof(NodeID));
+            temporary_storage.ReadFromSlot(edge_storage_slot, (char *)&target, sizeof(NodeID));
+            temporary_storage.ReadFromSlot(
+                edge_storage_slot, (char *)&data, sizeof(ContractorGraph::EdgeData));
+            restored_edge.source = source;
+            restored_edge.target = target;
+            restored_edge.data.distance = data.distance;
+            restored_edge.data.shortcut = data.shortcut;
+            restored_edge.data.id = data.id;
+            restored_edge.data.forward = data.forward;
+            restored_edge.data.backward = data.backward;
+            edges.push_back(restored_edge);
         }
-        tempStorage.deallocateSlot(temporaryStorageSlotID);
+        temporary_storage.DeallocateSlot(edge_storage_slot);
     }
 
-private:
-    inline void _Dijkstra( const int maxDistance, const unsigned numTargets, const int maxNodes, _ThreadData* const data, const NodeID middleNode ){
+  private:
+    inline void Dijkstra(const int max_distance,
+                         const unsigned number_of_targets,
+                         const int maxNodes,
+                         ContractorThreadData *const data,
+                         const NodeID middleNode)
+    {
 
-        _Heap& heap = data->heap;
+        ContractorHeap &heap = data->heap;
 
         int nodes = 0;
-        unsigned targetsFound = 0;
-        while ( heap.Size() > 0 ) {
+        unsigned number_of_targets_found = 0;
+        while (heap.Size() > 0)
+        {
             const NodeID node = heap.DeleteMin();
-            const int distance = heap.GetKey( node );
-            const short currentHop = heap.GetData( node ).hop+1;
+            const int distance = heap.GetKey(node);
+            const short current_hop = heap.GetData(node).hop + 1;
 
-            if ( ++nodes > maxNodes )
+            if (++nodes > maxNodes)
+            {
                 return;
-            //Destination settled?
-            if ( distance > maxDistance )
+            }
+            // Destination settled?
+            if (distance > max_distance)
+            {
                 return;
+            }
 
-            if ( heap.GetData( node ).target ) {
-                ++targetsFound;
-                if ( targetsFound >= numTargets ) {
+            if (heap.GetData(node).target)
+            {
+                ++number_of_targets_found;
+                if (number_of_targets_found >= number_of_targets)
+                {
                     return;
                 }
             }
 
-            //iterate over all edges of node
-            for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) {
-                const _ContractorEdgeData& data = _graph->GetEdgeData( edge );
-                if ( !data.forward ){
+            // iterate over all edges of node
+            for (auto edge : contractor_graph->GetAdjacentEdgeRange(node))
+            {
+                const ContractorEdgeData &data = contractor_graph->GetEdgeData(edge);
+                if (!data.forward)
+                {
                     continue;
                 }
-                const NodeID to = _graph->GetTarget( edge );
-                if(middleNode == to) {
+                const NodeID to = contractor_graph->GetTarget(edge);
+                if (middleNode == to)
+                {
                     continue;
                 }
-                const int toDistance = distance + data.distance;
+                const int to_distance = distance + data.distance;
 
-                //New Node discovered -> Add to Heap + Node Info Storage
-                if ( !heap.WasInserted( to ) ) {
-                    heap.Insert( to, toDistance, _HeapData(currentHop, false) );
+                // New Node discovered -> Add to Heap + Node Info Storage
+                if (!heap.WasInserted(to))
+                {
+                    heap.Insert(to, to_distance, ContractorHeapData(current_hop, false));
                 }
-                //Found a shorter Path -> Update distance
-                else if ( toDistance < heap.GetKey( to ) ) {
-                    heap.DecreaseKey( to, toDistance );
-                    heap.GetData( to ).hop = currentHop;
+                // Found a shorter Path -> Update distance
+                else if (to_distance < heap.GetKey(to))
+                {
+                    heap.DecreaseKey(to, to_distance);
+                    heap.GetData(to).hop = current_hop;
                 }
             }
         }
     }
 
-    inline float _Evaluate( _ThreadData* const data, _PriorityData* const nodeData, const NodeID node){
-        _ContractionInformation stats;
+    inline float EvaluateNodePriority(ContractorThreadData *const data,
+                                      NodePriorityData *const node_data,
+                                      const NodeID node)
+    {
+        ContractionStats stats;
 
-        //perform simulated contraction
-        _Contract< true> ( data, node, &stats );
+        // perform simulated contraction
+        ContractNode<true>(data, node, &stats);
 
         // Result will contain the priority
         float result;
-        if ( 0 == (stats.edgesDeleted*stats.originalEdgesDeleted) )
-            result = 1 * nodeData->depth;
+        if (0 == (stats.edges_deleted_count * stats.original_edges_deleted_count))
+        {
+            result = 1.f * node_data->depth;
+        }
         else
-            result =  2 * ((( float ) stats.edgesAdded ) / stats.edgesDeleted ) + 4 * ((( float ) stats.originalEdgesAdded ) / stats.originalEdgesDeleted ) + 1 * nodeData->depth;
-        assert( result >= 0 );
+        {
+            result = 2.f * (((float)stats.edges_added_count) / stats.edges_deleted_count) +
+                     4.f * (((float)stats.original_edges_added_count) /
+                            stats.original_edges_deleted_count) +
+                     1.f * node_data->depth;
+        }
+        BOOST_ASSERT(result >= 0);
         return result;
     }
 
-    template< bool Simulate >
-    inline bool _Contract( _ThreadData* data, NodeID node, _ContractionInformation* stats = NULL ) {
-        _Heap& heap = data->heap;
-        int insertedEdgesSize = data->insertedEdges.size();
-        std::vector< _ContractorEdge >& insertedEdges = data->insertedEdges;
-
-        for ( _DynamicGraph::EdgeIterator inEdge = _graph->BeginEdges( node ), endInEdges = _graph->EndEdges( node ); inEdge != endInEdges; ++inEdge ) {
-            const _ContractorEdgeData& inData = _graph->GetEdgeData( inEdge );
-            const NodeID source = _graph->GetTarget( inEdge );
-            if ( Simulate ) {
-                assert( stats != NULL );
-                ++stats->edgesDeleted;
-                stats->originalEdgesDeleted += inData.originalEdges;
+    template <bool RUNSIMULATION>
+    inline bool
+    ContractNode(ContractorThreadData *data, NodeID node, ContractionStats *stats = nullptr)
+    {
+        ContractorHeap &heap = data->heap;
+        int inserted_edges_size = data->inserted_edges.size();
+        std::vector<ContractorEdge> &inserted_edges = data->inserted_edges;
+
+        for (auto in_edge : contractor_graph->GetAdjacentEdgeRange(node))
+        {
+            const ContractorEdgeData &in_data = contractor_graph->GetEdgeData(in_edge);
+            const NodeID source = contractor_graph->GetTarget(in_edge);
+            if (RUNSIMULATION)
+            {
+                BOOST_ASSERT(stats != nullptr);
+                ++stats->edges_deleted_count;
+                stats->original_edges_deleted_count += in_data.originalEdges;
             }
-            if ( !inData.backward )
+            if (!in_data.backward)
+            {
                 continue;
+            }
 
             heap.Clear();
-            heap.Insert( source, 0, _HeapData() );
-            int maxDistance = 0;
-            unsigned numTargets = 0;
+            heap.Insert(source, 0, ContractorHeapData());
+            int max_distance = 0;
+            unsigned number_of_targets = 0;
 
-            for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
-                const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
-                if ( !outData.forward ) {
+            for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node))
+            {
+                const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge);
+                if (!out_data.forward)
+                {
                     continue;
                 }
-                const NodeID target = _graph->GetTarget( outEdge );
-                const int pathDistance = inData.distance + outData.distance;
-                maxDistance = std::max( maxDistance, pathDistance );
-                if ( !heap.WasInserted( target ) ) {
-                    heap.Insert( target, INT_MAX, _HeapData( 0, true ) );
-                    ++numTargets;
+                const NodeID target = contractor_graph->GetTarget(out_edge);
+                const int path_distance = in_data.distance + out_data.distance;
+                max_distance = std::max(max_distance, path_distance);
+                if (!heap.WasInserted(target))
+                {
+                    heap.Insert(target, INT_MAX, ContractorHeapData(0, true));
+                    ++number_of_targets;
                 }
             }
 
-            if( Simulate ) {
-                _Dijkstra( maxDistance, numTargets, 1000, data, node );
-            } else {
-                _Dijkstra( maxDistance, numTargets, 2000, data, node );
+            if (RUNSIMULATION)
+            {
+                Dijkstra(max_distance, number_of_targets, 1000, data, node);
             }
-            for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
-                const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
-                if ( !outData.forward ) {
+            else
+            {
+                Dijkstra(max_distance, number_of_targets, 2000, data, node);
+            }
+            for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node))
+            {
+                const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge);
+                if (!out_data.forward)
+                {
                     continue;
                 }
-                const NodeID target = _graph->GetTarget( outEdge );
-                const int pathDistance = inData.distance + outData.distance;
-                const int distance = heap.GetKey( target );
-                if ( pathDistance < distance ) {
-                    if ( Simulate ) {
-                        assert( stats != NULL );
-                        stats->edgesAdded+=2;
-                        stats->originalEdgesAdded += 2* ( outData.originalEdges + inData.originalEdges );
-                    } else {
-                        _ContractorEdge newEdge;
-                        newEdge.source = source;
-                        newEdge.target = target;
-                        newEdge.data = _ContractorEdgeData( pathDistance, outData.originalEdges + inData.originalEdges, node/*, 0, inData.turnInstruction*/, true, true, false);;
-                        insertedEdges.push_back( newEdge );
-                        std::swap( newEdge.source, newEdge.target );
-                        newEdge.data.forward = false;
-                        newEdge.data.backward = true;
-                        insertedEdges.push_back( newEdge );
+                const NodeID target = contractor_graph->GetTarget(out_edge);
+                const int path_distance = in_data.distance + out_data.distance;
+                const int distance = heap.GetKey(target);
+                if (path_distance < distance)
+                {
+                    if (RUNSIMULATION)
+                    {
+                        BOOST_ASSERT(stats != nullptr);
+                        stats->edges_added_count += 2;
+                        stats->original_edges_added_count +=
+                            2 * (out_data.originalEdges + in_data.originalEdges);
+                    }
+                    else
+                    {
+                        ContractorEdge new_edge;
+                        new_edge.source = source;
+                        new_edge.target = target;
+                        new_edge.data =
+                            ContractorEdgeData(path_distance,
+                                               out_data.originalEdges + in_data.originalEdges,
+                                               node /*, 0, in_data.turnInstruction*/,
+                                               true,
+                                               true,
+                                               false);
+                        inserted_edges.push_back(new_edge);
+                        std::swap(new_edge.source, new_edge.target);
+                        new_edge.data.forward = false;
+                        new_edge.data.backward = true;
+                        inserted_edges.push_back(new_edge);
                     }
                 }
             }
         }
-        if ( !Simulate ) {
-            for ( int i = insertedEdgesSize, iend = insertedEdges.size(); i < iend; ++i ) {
+        if (!RUNSIMULATION)
+        {
+            int iend = inserted_edges.size();
+            for (int i = inserted_edges_size; i < iend; ++i)
+            {
                 bool found = false;
-                for ( int other = i + 1 ; other < iend ; ++other ) {
-                    if ( insertedEdges[other].source != insertedEdges[i].source )
+                for (int other = i + 1; other < iend; ++other)
+                {
+                    if (inserted_edges[other].source != inserted_edges[i].source)
+                    {
                         continue;
-                    if ( insertedEdges[other].target != insertedEdges[i].target )
+                    }
+                    if (inserted_edges[other].target != inserted_edges[i].target)
+                    {
                         continue;
-                    if ( insertedEdges[other].data.distance != insertedEdges[i].data.distance )
+                    }
+                    if (inserted_edges[other].data.distance != inserted_edges[i].data.distance)
+                    {
                         continue;
-                    if ( insertedEdges[other].data.shortcut != insertedEdges[i].data.shortcut )
+                    }
+                    if (inserted_edges[other].data.shortcut != inserted_edges[i].data.shortcut)
+                    {
                         continue;
-                    insertedEdges[other].data.forward |= insertedEdges[i].data.forward;
-                    insertedEdges[other].data.backward |= insertedEdges[i].data.backward;
+                    }
+                    inserted_edges[other].data.forward |= inserted_edges[i].data.forward;
+                    inserted_edges[other].data.backward |= inserted_edges[i].data.backward;
                     found = true;
                     break;
                 }
-                if ( !found ) {
-                    insertedEdges[insertedEdgesSize++] = insertedEdges[i];
+                if (!found)
+                {
+                    inserted_edges[inserted_edges_size++] = inserted_edges[i];
                 }
             }
-            insertedEdges.resize( insertedEdgesSize );
+            inserted_edges.resize(inserted_edges_size);
         }
         return true;
     }
 
-    inline void _DeleteIncomingEdges( _ThreadData* data, const NodeID node ) {
-        std::vector< NodeID >& neighbours = data->neighbours;
+    inline void DeleteIncomingEdges(ContractorThreadData *data, const NodeID node)
+    {
+        std::vector<NodeID> &neighbours = data->neighbours;
         neighbours.clear();
 
-        //find all neighbours
-        for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ) ; e < _graph->EndEdges( node ) ; ++e ) {
-            const NodeID u = _graph->GetTarget( e );
-            if ( u != node )
-                neighbours.push_back( u );
+        // find all neighbours
+        for (auto e : contractor_graph->GetAdjacentEdgeRange(node))
+        {
+            const NodeID u = contractor_graph->GetTarget(e);
+            if (u != node)
+            {
+                neighbours.push_back(u);
+            }
         }
-        //eliminate duplicate entries ( forward + backward edges )
-        std::sort( neighbours.begin(), neighbours.end() );
-        neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() );
+        // eliminate duplicate entries ( forward + backward edges )
+        std::sort(neighbours.begin(), neighbours.end());
+        neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin());
 
-        for ( int i = 0, e = ( int ) neighbours.size(); i < e; ++i ) {
-            _graph->DeleteEdgesTo( neighbours[i], node );
+        for (int i = 0, e = (int)neighbours.size(); i < e; ++i)
+        {
+            contractor_graph->DeleteEdgesTo(neighbours[i], node);
         }
     }
 
-    inline bool _UpdateNeighbours( std::vector< float > & priorities, std::vector< _PriorityData > & nodeData, _ThreadData* const data, const NodeID node) {
-        std::vector< NodeID >& neighbours = data->neighbours;
+    inline bool UpdateNodeNeighbours(std::vector<float> &priorities,
+                                     std::vector<NodePriorityData> &node_data,
+                                     ContractorThreadData *const data,
+                                     const NodeID node)
+    {
+        std::vector<NodeID> &neighbours = data->neighbours;
         neighbours.clear();
 
-        //find all neighbours
-        for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ) ; e < endEdges ; ++e ) {
-            const NodeID u = _graph->GetTarget( e );
-            if ( u == node )
+        // find all neighbours
+        for (auto e : contractor_graph->GetAdjacentEdgeRange(node))
+        {
+            const NodeID u = contractor_graph->GetTarget(e);
+            if (u == node)
+            {
                 continue;
-            neighbours.push_back( u );
-            nodeData[u].depth = (std::max)(nodeData[node].depth + 1, nodeData[u].depth );
+            }
+            neighbours.push_back(u);
+            node_data[u].depth = (std::max)(node_data[node].depth + 1, node_data[u].depth);
         }
-        //eliminate duplicate entries ( forward + backward edges )
-        std::sort( neighbours.begin(), neighbours.end() );
-        neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() );
+        // eliminate duplicate entries ( forward + backward edges )
+        std::sort(neighbours.begin(), neighbours.end());
+        neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin());
 
-        BOOST_FOREACH(const NodeID u, neighbours) {
-            priorities[u] = _Evaluate( data, &( nodeData )[u], u );
+        // re-evaluate priorities of neighboring nodes
+        for (const NodeID u : neighbours)
+        {
+            priorities[u] = EvaluateNodePriority(data, &(node_data)[u], u);
         }
         return true;
     }
 
-    inline bool _IsIndependent( const std::vector< float >& priorities/*, const std::vector< _PriorityData >& nodeData*/, _ThreadData* const data, NodeID node ) const {
-        const double priority = priorities[node];
+    inline bool IsNodeIndependent(
+        const std::vector<float> &priorities /*, const std::vector< NodePriorityData >& node_data*/,
+        ContractorThreadData *const data,
+        NodeID node) const
+    {
+        const float priority = priorities[node];
 
-        std::vector< NodeID >& neighbours = data->neighbours;
+        std::vector<NodeID> &neighbours = data->neighbours;
         neighbours.clear();
 
-        for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ) ; e < _graph->EndEdges( node ) ; ++e ) {
-            const NodeID target = _graph->GetTarget( e );
-            if(node==target)
+        for (auto e : contractor_graph->GetAdjacentEdgeRange(node))
+        {
+            const NodeID target = contractor_graph->GetTarget(e);
+            if (node == target)
+            {
                 continue;
-            const double targetPriority = priorities[target];
-            assert( targetPriority >= 0 );
-            //found a neighbour with lower priority?
-            if ( priority > targetPriority )
+            }
+            const float target_priority = priorities[target];
+            BOOST_ASSERT(target_priority >= 0);
+            // found a neighbour with lower priority?
+            if (priority > target_priority)
+            {
                 return false;
-            //tie breaking
-            if ( fabs(priority - targetPriority) < FLT_EPSILON && bias(node, target) ) {
+            }
+            // tie breaking
+            if (std::abs(priority - target_priority) < std::numeric_limits<float>::epsilon() &&
+                bias(node, target))
+            {
                 return false;
             }
-            neighbours.push_back( target );
+            neighbours.push_back(target);
         }
 
-        std::sort( neighbours.begin(), neighbours.end() );
-        neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() );
+        std::sort(neighbours.begin(), neighbours.end());
+        neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin());
 
-        //examine all neighbours that are at most 2 hops away
-        BOOST_FOREACH(const NodeID u, neighbours) {
-            for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( u ) ; e < _graph->EndEdges( u ) ; ++e ) {
-                const NodeID target = _graph->GetTarget( e );
-                if(node==target)
+        // examine all neighbours that are at most 2 hops away
+        for (const NodeID u : neighbours)
+        {
+            for (auto e : contractor_graph->GetAdjacentEdgeRange(u))
+            {
+                const NodeID target = contractor_graph->GetTarget(e);
+                if (node == target)
+                {
                     continue;
-
-                const double targetPriority = priorities[target];
-                assert( targetPriority >= 0 );
-                //found a neighbour with lower priority?
-                if ( priority > targetPriority)
+                }
+                const float target_priority = priorities[target];
+                assert(target_priority >= 0);
+                // found a neighbour with lower priority?
+                if (priority > target_priority)
+                {
                     return false;
-                //tie breaking
-                if ( fabs(priority - targetPriority) < FLT_EPSILON && bias(node, target) ) {
+                }
+                // tie breaking
+                if (std::abs(priority - target_priority) < std::numeric_limits<float>::epsilon() &&
+                    bias(node, target))
+                {
                     return false;
                 }
             }
@@ -759,25 +980,27 @@ private:
         return true;
     }
 
+    // This bias function takes up 22 assembly instructions in total on X86
+    inline bool bias(const NodeID a, const NodeID b) const
+    {
+        unsigned short hasha = fast_hash(a);
+        unsigned short hashb = fast_hash(b);
 
-    /**
-     * This bias function takes up 22 assembly instructions in total on X86
-     */
-    inline bool bias(const NodeID a, const NodeID b) const {
-        unsigned short hasha = fastHash(a);
-        unsigned short hashb = fastHash(b);
-
-        //The compiler optimizes that to conditional register flags but without branching statements!
-        if(hasha != hashb)
+        // The compiler optimizes that to conditional register flags but without branching
+        // statements!
+        if (hasha != hashb)
+        {
             return hasha < hashb;
+        }
         return a < b;
     }
 
-    boost::shared_ptr<_DynamicGraph> _graph;
-    std::vector<_DynamicGraph::InputEdge> contractedEdges;
-    unsigned temporaryStorageSlotID;
-    std::vector<NodeID> oldNodeIDFromNewNodeIDMap;
-    XORFastHash fastHash;
+    std::shared_ptr<ContractorGraph> contractor_graph;
+    std::vector<ContractorGraph::InputEdge> contracted_edge_list;
+    unsigned edge_storage_slot;
+    uint64_t temp_edge_counter;
+    std::vector<NodeID> orig_node_id_to_new_id_map;
+    XORFastHash fast_hash;
 };
 
-#endif // CONTRACTOR_H_INCLUDED
+#endif // CONTRACTOR_H
diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp
index 13f49ec..1e4e381 100644
--- a/Contractor/EdgeBasedGraphFactory.cpp
+++ b/Contractor/EdgeBasedGraphFactory.cpp
@@ -1,412 +1,779 @@
 /*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
-
- 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.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #include "EdgeBasedGraphFactory.h"
+#include "../Algorithms/BFSComponentExplorer.h"
+#include "../DataStructures/Percent.h"
+#include "../Util/ComputeAngle.h"
+#include "../Util/LuaUtil.h"
+#include "../Util/SimpleLogger.h"
+#include "../Util/TimingUtil.h"
+
+#include <boost/assert.hpp>
+
+#include <fstream>
+#include <limits>
+
+EdgeBasedGraphFactory::EdgeBasedGraphFactory(
+    const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph,
+    std::unique_ptr<RestrictionMap> restriction_map,
+    std::vector<NodeID> &barrier_node_list,
+    std::vector<NodeID> &traffic_light_node_list,
+    std::vector<NodeInfo> &m_node_info_list,
+    SpeedProfileProperties &speed_profile)
+    : speed_profile(speed_profile),
+      m_number_of_edge_based_nodes(std::numeric_limits<unsigned>::max()),
+      m_node_info_list(m_node_info_list), m_node_based_graph(node_based_graph),
+      m_restriction_map(std::move(restriction_map)), max_id(0)
+{
+
+    // insert into unordered sets for fast lookup
+    m_barrier_nodes.insert(barrier_node_list.begin(), barrier_node_list.end());
+    m_traffic_lights.insert(traffic_light_node_list.begin(), traffic_light_node_list.end());
+}
 
-template<>
-EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector<NodeBasedEdge> & inputEdges, std::vector<NodeID> & bn, std::vector<NodeID> & tl, std::vector<_Restriction> & irs, std::vector<NodeInfo> & nI, SpeedProfileProperties sp) : speedProfile(sp), inputNodeInfoList(nI), numberOfTurnRestrictions(irs.size()) {
-	BOOST_FOREACH(const _Restriction & restriction, irs) {
-        std::pair<NodeID, NodeID> restrictionSource = std::make_pair(restriction.fromNode, restriction.viaNode);
-        unsigned index;
-        RestrictionMap::iterator restrIter = _restrictionMap.find(restrictionSource);
-        if(restrIter == _restrictionMap.end()) {
-            index = _restrictionBucketVector.size();
-            _restrictionBucketVector.resize(index+1);
-            _restrictionMap[restrictionSource] = index;
-        } else {
-            index = restrIter->second;
-            //Map already contains an is_only_*-restriction
-            if(_restrictionBucketVector.at(index).begin()->second)
-                continue;
-            else if(restriction.flags.isOnly){
-                //We are going to insert an is_only_*-restriction. There can be only one.
-                _restrictionBucketVector.at(index).clear();
-            }
+void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &output_edge_list)
+{
+    BOOST_ASSERT_MSG(0 == output_edge_list.size(), "Vector is not empty");
+    m_edge_based_edge_list.swap(output_edge_list);
+}
+
+void EdgeBasedGraphFactory::GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes)
+{
+#ifndef NDEBUG
+    for (const EdgeBasedNode &node : m_edge_based_node_list)
+    {
+        BOOST_ASSERT(m_node_info_list.at(node.u).lat != INT_MAX);
+        BOOST_ASSERT(m_node_info_list.at(node.u).lon != INT_MAX);
+        BOOST_ASSERT(m_node_info_list.at(node.v).lon != INT_MAX);
+        BOOST_ASSERT(m_node_info_list.at(node.v).lat != INT_MAX);
+    }
+#endif
+    nodes.swap(m_edge_based_node_list);
+}
+
+void
+EdgeBasedGraphFactory::InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool belongs_to_tiny_cc)
+{
+    // merge edges together into one EdgeBasedNode
+    BOOST_ASSERT(u != SPECIAL_NODEID);
+    BOOST_ASSERT(v != SPECIAL_NODEID);
+    BOOST_ASSERT(e1 != SPECIAL_EDGEID);
+
+#ifndef NDEBUG
+    // find forward edge id and
+    const EdgeID e1b = m_node_based_graph->FindEdge(u, v);
+    BOOST_ASSERT(e1 == e1b);
+#endif
+
+    BOOST_ASSERT(e1 != SPECIAL_EDGEID);
+    const EdgeData &forward_data = m_node_based_graph->GetEdgeData(e1);
+
+    // find reverse edge id and
+    const EdgeID e2 = m_node_based_graph->FindEdge(v, u);
+
+#ifndef NDEBUG
+    if (e2 == m_node_based_graph->EndEdges(v))
+    {
+        SimpleLogger().Write(logWARNING) << "Did not find edge (" << v << "," << u << ")";
+    }
+#endif
+    BOOST_ASSERT(e2 != SPECIAL_EDGEID);
+    BOOST_ASSERT(e2 < m_node_based_graph->EndEdges(v));
+    const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(e2);
+
+    if (forward_data.edgeBasedNodeID == SPECIAL_NODEID &&
+        reverse_data.edgeBasedNodeID == SPECIAL_NODEID)
+    {
+        return;
+    }
+
+    BOOST_ASSERT(m_geometry_compressor.HasEntryForID(e1) ==
+                 m_geometry_compressor.HasEntryForID(e2));
+    if (m_geometry_compressor.HasEntryForID(e1))
+    {
+        BOOST_ASSERT(m_geometry_compressor.HasEntryForID(e2));
+
+        // reconstruct geometry and put in each individual edge with its offset
+        const std::vector<GeometryCompressor::CompressedNode> &forward_geometry =
+            m_geometry_compressor.GetBucketReference(e1);
+        const std::vector<GeometryCompressor::CompressedNode> &reverse_geometry =
+            m_geometry_compressor.GetBucketReference(e2);
+        BOOST_ASSERT(forward_geometry.size() == reverse_geometry.size());
+        BOOST_ASSERT(0 != forward_geometry.size());
+
+        // reconstruct bidirectional edge with individual weights and put each into the NN index
+
+        std::vector<int> forward_dist_prefix_sum(forward_geometry.size(), 0);
+        std::vector<int> reverse_dist_prefix_sum(reverse_geometry.size(), 0);
+
+        // quick'n'dirty prefix sum as std::partial_sum needs addtional casts
+        // TODO: move to lambda function with C++11
+        int temp_sum = 0;
+
+        for (unsigned i = 0; i < forward_geometry.size(); ++i)
+        {
+            forward_dist_prefix_sum[i] = temp_sum;
+            temp_sum += forward_geometry[i].second;
+
+            BOOST_ASSERT(forward_data.distance >= temp_sum);
+        }
+
+        temp_sum = 0;
+        for (unsigned i = 0; i < reverse_geometry.size(); ++i)
+        {
+            temp_sum += reverse_geometry[reverse_geometry.size() - 1 - i].second;
+            reverse_dist_prefix_sum[i] = reverse_data.distance - temp_sum;
+            BOOST_ASSERT(reverse_data.distance >= temp_sum);
+        }
+
+        BOOST_ASSERT(forward_geometry.size() == reverse_geometry.size());
+
+        const unsigned geometry_size = forward_geometry.size();
+        BOOST_ASSERT(geometry_size > 1);
+        NodeID current_edge_source_coordinate_id = u;
+
+        if (forward_data.edgeBasedNodeID != SPECIAL_NODEID)
+        {
+            max_id = std::max(forward_data.edgeBasedNodeID, max_id);
+        }
+        if (SPECIAL_NODEID != reverse_data.edgeBasedNodeID)
+        {
+            max_id = std::max(reverse_data.edgeBasedNodeID, max_id);
         }
 
-        _restrictionBucketVector.at(index).push_back(std::make_pair(restriction.toNode, restriction.flags.isOnly));
+        // traverse arrays from start and end respectively
+        for (unsigned i = 0; i < geometry_size; ++i)
+        {
+            BOOST_ASSERT(current_edge_source_coordinate_id ==
+                         reverse_geometry[geometry_size - 1 - i].first);
+            const NodeID current_edge_target_coordinate_id = forward_geometry[i].first;
+            BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id);
+
+            // build edges
+            m_edge_based_node_list.emplace_back(forward_data.edgeBasedNodeID,
+                                                reverse_data.edgeBasedNodeID,
+                                                current_edge_source_coordinate_id,
+                                                current_edge_target_coordinate_id,
+                                                forward_data.nameID,
+                                                forward_geometry[i].second,
+                                                reverse_geometry[i].second,
+                                                forward_dist_prefix_sum[i],
+                                                reverse_dist_prefix_sum[i],
+                                                m_geometry_compressor.GetPositionForID(e1),
+                                                i,
+                                                belongs_to_tiny_cc);
+            current_edge_source_coordinate_id = current_edge_target_coordinate_id;
+
+            BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
+
+            BOOST_ASSERT(u != m_edge_based_node_list.back().u ||
+                         v != m_edge_based_node_list.back().v);
+
+            BOOST_ASSERT(u != m_edge_based_node_list.back().v ||
+                         v != m_edge_based_node_list.back().u);
+        }
+
+        BOOST_ASSERT(current_edge_source_coordinate_id == v);
+        BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
     }
+    else
+    {
+        BOOST_ASSERT(!m_geometry_compressor.HasEntryForID(e2));
 
-	_barrierNodes.insert(bn.begin(), bn.end());
-	_trafficLights.insert(tl.begin(), tl.end());
-
-    DeallocatingVector< _NodeBasedEdge > edges;
-    _NodeBasedEdge edge;
-    for ( std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(); i != inputEdges.end(); ++i ) {
-        if(!i->isForward()) {
-            edge.source = i->target();
-            edge.target = i->source();
-            edge.data.backward = i->isForward();
-            edge.data.forward = i->isBackward();
-        } else {
-            edge.source = i->source();
-            edge.target = i->target();
-            edge.data.forward = i->isForward();
-            edge.data.backward = i->isBackward();
+        if (forward_data.edgeBasedNodeID != SPECIAL_NODEID)
+        {
+            BOOST_ASSERT(forward_data.forward);
         }
-        if(edge.source == edge.target) {
-        	continue;
+        if (reverse_data.edgeBasedNodeID != SPECIAL_NODEID)
+        {
+            BOOST_ASSERT(reverse_data.forward);
         }
-        edge.data.distance = (std::max)((int)i->weight(), 1 );
-        assert( edge.data.distance > 0 );
-        edge.data.shortcut = false;
-        edge.data.roundabout = i->isRoundabout();
-        edge.data.ignoreInGrid = i->ignoreInGrid();
-        edge.data.nameID = i->name();
-        edge.data.type = i->type();
-        edge.data.isAccessRestricted = i->isAccessRestricted();
-        edge.data.edgeBasedNodeID = edges.size();
-        edge.data.contraFlow = i->isContraFlow();
-        edges.push_back( edge );
-        if( edge.data.backward ) {
-            std::swap( edge.source, edge.target );
-            edge.data.forward = i->isBackward();
-            edge.data.backward = i->isForward();
-            edge.data.edgeBasedNodeID = edges.size();
-            edges.push_back( edge );
+        if (forward_data.edgeBasedNodeID == SPECIAL_NODEID)
+        {
+            BOOST_ASSERT(!forward_data.forward);
         }
+        if (reverse_data.edgeBasedNodeID == SPECIAL_NODEID)
+        {
+            BOOST_ASSERT(!reverse_data.forward);
+        }
+
+        BOOST_ASSERT(forward_data.edgeBasedNodeID != SPECIAL_NODEID ||
+                     reverse_data.edgeBasedNodeID != SPECIAL_NODEID);
+
+        m_edge_based_node_list.emplace_back(EdgeBasedNode(forward_data.edgeBasedNodeID,
+                                                          reverse_data.edgeBasedNodeID,
+                                                          u,
+                                                          v,
+                                                          forward_data.nameID,
+                                                          forward_data.distance,
+                                                          reverse_data.distance,
+                                                          0,
+                                                          0,
+                                                          SPECIAL_EDGEID,
+                                                          0,
+                                                          belongs_to_tiny_cc));
+        BOOST_ASSERT(!m_edge_based_node_list.back().IsCompressed());
     }
-    std::vector<NodeBasedEdge>().swap(inputEdges);
-    std::sort( edges.begin(), edges.end() );
-    _nodeBasedGraph = boost::make_shared<_NodeBasedDynamicGraph>( nodes, edges );
 }
 
-void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector< EdgeBasedEdge >& outputEdgeList ) {
-    BOOST_ASSERT_MSG(
-        0 == outputEdgeList.size(),
-        "Vector is not empty"
-    );
-    edgeBasedEdges.swap(outputEdgeList);
+void EdgeBasedGraphFactory::FlushVectorToStream(
+    std::ofstream &edge_data_file, std::vector<OriginalEdgeData> &original_edge_data_vector) const
+{
+    if (original_edge_data_vector.empty()) {
+        return;
+    }
+    edge_data_file.write((char *)&(original_edge_data_vector[0]),
+                         original_edge_data_vector.size() * sizeof(OriginalEdgeData));
+    original_edge_data_vector.clear();
 }
 
-void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector<EdgeBasedNode> & nodes) {
-#ifndef NDEBUG
-    BOOST_FOREACH(EdgeBasedNode & node, edgeBasedNodes){
-        assert(node.lat1 != INT_MAX); assert(node.lon1 != INT_MAX);
-        assert(node.lat2 != INT_MAX); assert(node.lon2 != INT_MAX);
-    }
-#endif
-    nodes.swap(edgeBasedNodes);
+void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
+                                const std::string &geometry_filename,
+                                lua_State *lua_state)
+{
+
+    TIMER_START(geometry);
+    CompressGeometry();
+    TIMER_STOP(geometry);
+
+    TIMER_START(renumber);
+    RenumberEdges();
+    TIMER_STOP(renumber);
+
+    TIMER_START(generate_nodes);
+    GenerateEdgeExpandedNodes();
+    TIMER_STOP(generate_nodes);
+
+    TIMER_START(generate_edges);
+    GenerateEdgeExpandedEdges(original_edge_data_filename, lua_state);
+    TIMER_STOP(generate_edges);
+
+    m_geometry_compressor.SerializeInternalVector(geometry_filename);
+
+    SimpleLogger().Write() << "Timing statistics for edge-expanded graph:";
+    SimpleLogger().Write() << "Geometry compression: " << TIMER_SEC(geometry) << "s";
+    SimpleLogger().Write() << "Renumbering edges: " << TIMER_SEC(renumber) << "s";
+    SimpleLogger().Write() << "Generating nodes: " << TIMER_SEC(generate_nodes) << "s";
+    SimpleLogger().Write() << "Generating edges: " << TIMER_SEC(generate_edges) << "s";
 }
 
-NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
-    std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
-    RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
-    if (restrIter != _restrictionMap.end()) {
-        unsigned index = restrIter->second;
-        BOOST_FOREACH(const RestrictionSource & restrictionTarget, _restrictionBucketVector.at(index)) {
-            if(restrictionTarget.second) {
-                return restrictionTarget.first;
+void EdgeBasedGraphFactory::CompressGeometry()
+{
+    SimpleLogger().Write() << "Removing graph geometry while preserving topology";
+
+    const unsigned original_number_of_nodes = m_node_based_graph->GetNumberOfNodes();
+    const unsigned original_number_of_edges = m_node_based_graph->GetNumberOfEdges();
+
+    Percent p(original_number_of_nodes);
+    unsigned removed_node_count = 0;
+
+    for (NodeID v = 0; v < original_number_of_nodes; ++v)
+    {
+        p.printStatus(v);
+
+        // only contract degree 2 vertices
+        if (2 != m_node_based_graph->GetOutDegree(v))
+        {
+            continue;
+        }
+
+        // don't contract barrier node
+        if (m_barrier_nodes.end() != m_barrier_nodes.find(v))
+        {
+            continue;
+        }
+
+        // check if v is a via node for a turn restriction, i.e. a 'directed' barrier node
+        if (m_restriction_map->IsViaNode(v))
+        {
+            continue;
+        }
+
+        const bool reverse_edge_order =
+            !(m_node_based_graph->GetEdgeData(m_node_based_graph->BeginEdges(v)).forward);
+        const EdgeID forward_e2 = m_node_based_graph->BeginEdges(v) + reverse_edge_order;
+        BOOST_ASSERT(SPECIAL_EDGEID != forward_e2);
+        const EdgeID reverse_e2 = m_node_based_graph->BeginEdges(v) + 1 - reverse_edge_order;
+        BOOST_ASSERT(SPECIAL_EDGEID != reverse_e2);
+
+        const EdgeData &fwd_edge_data2 = m_node_based_graph->GetEdgeData(forward_e2);
+        const EdgeData &rev_edge_data2 = m_node_based_graph->GetEdgeData(reverse_e2);
+
+        const NodeID w = m_node_based_graph->GetTarget(forward_e2);
+        BOOST_ASSERT(SPECIAL_NODEID != w);
+        BOOST_ASSERT(v != w);
+        const NodeID u = m_node_based_graph->GetTarget(reverse_e2);
+        BOOST_ASSERT(SPECIAL_NODEID != u);
+        BOOST_ASSERT(u != v);
+
+        const EdgeID forward_e1 = m_node_based_graph->FindEdge(u, v);
+        BOOST_ASSERT(m_node_based_graph->EndEdges(u) != forward_e1);
+        BOOST_ASSERT(SPECIAL_EDGEID != forward_e1);
+        BOOST_ASSERT(v == m_node_based_graph->GetTarget(forward_e1));
+        const EdgeID reverse_e1 = m_node_based_graph->FindEdge(w, v);
+        BOOST_ASSERT(SPECIAL_EDGEID != reverse_e1);
+        BOOST_ASSERT(v == m_node_based_graph->GetTarget(reverse_e1));
+
+        const EdgeData &fwd_edge_data1 = m_node_based_graph->GetEdgeData(forward_e1);
+        const EdgeData &rev_edge_data1 = m_node_based_graph->GetEdgeData(reverse_e1);
+
+        if ((m_node_based_graph->FindEdge(u, w) != m_node_based_graph->EndEdges(u)) ||
+            (m_node_based_graph->FindEdge(w, u) != m_node_based_graph->EndEdges(w)))
+        {
+            continue;
+        }
+
+        if ( // TODO: rename to IsCompatibleTo
+                fwd_edge_data1.IsEqualTo(fwd_edge_data2) &&
+                rev_edge_data1.IsEqualTo(rev_edge_data2))
+        {
+            // Get distances before graph is modified
+            const int forward_weight1 = m_node_based_graph->GetEdgeData(forward_e1).distance;
+            const int forward_weight2 = m_node_based_graph->GetEdgeData(forward_e2).distance;
+
+            BOOST_ASSERT(0 != forward_weight1);
+            BOOST_ASSERT(0 != forward_weight2);
+
+            const int reverse_weight1 = m_node_based_graph->GetEdgeData(reverse_e1).distance;
+            const int reverse_weight2 = m_node_based_graph->GetEdgeData(reverse_e2).distance;
+
+            BOOST_ASSERT(0 != reverse_weight1);
+            BOOST_ASSERT(0 != forward_weight2);
+
+            const bool add_traffic_signal_penalty =
+                (m_traffic_lights.find(v) != m_traffic_lights.end());
+
+            // add weight of e2's to e1
+            m_node_based_graph->GetEdgeData(forward_e1).distance += fwd_edge_data2.distance;
+            m_node_based_graph->GetEdgeData(reverse_e1).distance += rev_edge_data2.distance;
+            if (add_traffic_signal_penalty)
+            {
+                m_node_based_graph->GetEdgeData(forward_e1).distance +=
+                    speed_profile.trafficSignalPenalty;
+                m_node_based_graph->GetEdgeData(reverse_e1).distance +=
+                    speed_profile.trafficSignalPenalty;
             }
+
+            // extend e1's to targets of e2's
+            m_node_based_graph->SetTarget(forward_e1, w);
+            m_node_based_graph->SetTarget(reverse_e1, u);
+
+            // remove e2's (if bidir, otherwise only one)
+            m_node_based_graph->DeleteEdge(v, forward_e2);
+            m_node_based_graph->DeleteEdge(v, reverse_e2);
+
+            // update any involved turn restrictions
+            m_restriction_map->FixupStartingTurnRestriction(u, v, w);
+            m_restriction_map->FixupArrivingTurnRestriction(u, v, w);
+
+            m_restriction_map->FixupStartingTurnRestriction(w, v, u);
+            m_restriction_map->FixupArrivingTurnRestriction(w, v, u);
+
+            // store compressed geometry in container
+            m_geometry_compressor.CompressEdge(
+                forward_e1,
+                forward_e2,
+                v,
+                w,
+                forward_weight1 +
+                    (add_traffic_signal_penalty ? speed_profile.trafficSignalPenalty : 0),
+                forward_weight2);
+            m_geometry_compressor.CompressEdge(
+                reverse_e1,
+                reverse_e2,
+                v,
+                u,
+                reverse_weight1,
+                reverse_weight2 +
+                    (add_traffic_signal_penalty ? speed_profile.trafficSignalPenalty : 0));
+            ++removed_node_count;
+
+            BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID ==
+                         m_node_based_graph->GetEdgeData(reverse_e1).nameID);
         }
     }
-    return UINT_MAX;
+    SimpleLogger().Write() << "removed " << removed_node_count << " nodes";
+    m_geometry_compressor.PrintStatistics();
+
+    unsigned new_node_count = 0;
+    unsigned new_edge_count = 0;
+    for (unsigned i = 0; i < m_node_based_graph->GetNumberOfNodes(); ++i)
+    {
+        if (m_node_based_graph->GetOutDegree(i) > 0)
+        {
+            ++new_node_count;
+            new_edge_count += (m_node_based_graph->EndEdges(i) - m_node_based_graph->BeginEdges(i));
+        }
+    }
+    SimpleLogger().Write() << "new nodes: " << new_node_count << ", edges " << new_edge_count;
+    SimpleLogger().Write() << "Node compression ratio: " << new_node_count /
+                                                                (double)original_number_of_nodes;
+    SimpleLogger().Write() << "Edge compression ratio: " << new_edge_count /
+                                                                (double)original_number_of_edges;
 }
 
-bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const {
-    //only add an edge if turn is not a U-turn except it is the end of dead-end street.
-    std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
-    RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
-    if (restrIter != _restrictionMap.end()) {
-        unsigned index = restrIter->second;
-        BOOST_FOREACH(RestrictionTarget restrictionTarget, _restrictionBucketVector.at(index)) {
-            if(w == restrictionTarget.first)
-                return true;
+/**
+ * Writes the id of the edge in the edge expanded graph (into the egde in the node based graph)
+ */
+void EdgeBasedGraphFactory::RenumberEdges()
+{
+    // renumber edge based node IDs
+    unsigned numbered_edges_count = 0;
+    for (NodeID current_node = 0; current_node < m_node_based_graph->GetNumberOfNodes();
+         ++current_node)
+    {
+        for (EdgeID current_edge : m_node_based_graph->GetAdjacentEdgeRange(current_node))
+        {
+            EdgeData &edge_data = m_node_based_graph->GetEdgeData(current_edge);
+            if (!edge_data.forward)
+            {
+                continue;
+            }
+
+            BOOST_ASSERT(numbered_edges_count < m_node_based_graph->GetNumberOfEdges());
+            edge_data.edgeBasedNodeID = numbered_edges_count;
+            ++numbered_edges_count;
+
+            BOOST_ASSERT(SPECIAL_NODEID != edge_data.edgeBasedNodeID);
         }
     }
-    return false;
+    m_number_of_edge_based_nodes = numbered_edges_count;
 }
 
-void EdgeBasedGraphFactory::InsertEdgeBasedNode(
-        _NodeBasedDynamicGraph::EdgeIterator e1,
-        _NodeBasedDynamicGraph::NodeIterator u,
-        _NodeBasedDynamicGraph::NodeIterator v,
-        bool belongsToTinyComponent) {
-    _NodeBasedDynamicGraph::EdgeData & data = _nodeBasedGraph->GetEdgeData(e1);
-    EdgeBasedNode currentNode;
-    currentNode.nameID = data.nameID;
-    currentNode.lat1 = inputNodeInfoList[u].lat;
-    currentNode.lon1 = inputNodeInfoList[u].lon;
-    currentNode.lat2 = inputNodeInfoList[v].lat;
-    currentNode.lon2 = inputNodeInfoList[v].lon;
-    currentNode.belongsToTinyComponent = belongsToTinyComponent;
-    currentNode.id = data.edgeBasedNodeID;
-    currentNode.ignoreInGrid = data.ignoreInGrid;
-    currentNode.weight = data.distance;
-    edgeBasedNodes.push_back(currentNode);
-}
+/**
+ * Creates the nodes in the edge expanded graph from edges in the node-based graph.
+ */
+void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
+{
+    SimpleLogger().Write() << "Identifying components of the road network";
 
-void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename, lua_State *myLuaState) {
-    Percent p(_nodeBasedGraph->GetNumberOfNodes());
-    int numberOfSkippedTurns(0);
-    int nodeBasedEdgeCounter(0);
-    unsigned numberOfOriginalEdges(0);
-    std::ofstream originalEdgeDataOutFile(originalEdgeDataFilename, std::ios::binary);
-    originalEdgeDataOutFile.write((char*)&numberOfOriginalEdges, sizeof(unsigned));
-
-
-    INFO("Identifying small components");
-    //Run a BFS on the undirected graph and identify small components
-    std::queue<std::pair<NodeID, NodeID> > bfsQueue;
-    std::vector<unsigned> componentsIndex(_nodeBasedGraph->GetNumberOfNodes(), UINT_MAX);
-    std::vector<NodeID> vectorOfComponentSizes;
-    unsigned currentComponent = 0, sizeOfCurrentComponent = 0;
-    //put unexplorered node with parent pointer into queue
-    for(NodeID node = 0, endNodes = _nodeBasedGraph->GetNumberOfNodes(); node < endNodes; ++node) {
-        if(UINT_MAX == componentsIndex[node]) {
-            bfsQueue.push(std::make_pair(node, node));
-            //mark node as read
-            componentsIndex[node] = currentComponent;
-            p.printIncrement();
-            while(!bfsQueue.empty()) {
-                //fetch element from BFS queue
-                std::pair<NodeID, NodeID> currentQueueItem = bfsQueue.front();
-                bfsQueue.pop();
-                //                INFO("sizeof queue: " << bfsQueue.size() <<  ", sizeOfCurrentComponents: " <<  sizeOfCurrentComponent << ", settled nodes: " << settledNodes++ << ", max: " << endNodes);
-                const NodeID v = currentQueueItem.first;  //current node
-                const NodeID u = currentQueueItem.second; //parent
-                //increment size counter of current component
-                ++sizeOfCurrentComponent;
-                const bool isBollardNode = (_barrierNodes.find(v) != _barrierNodes.end());
-                if(!isBollardNode) {
-                    const NodeID onlyToNode = CheckForEmanatingIsOnlyTurn(u, v);
-
-                    //relaxieren edge outgoing edge like below where edge-expanded graph
-                    for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
-                        _NodeBasedDynamicGraph::NodeIterator w = _nodeBasedGraph->GetTarget(e2);
-
-                        if(onlyToNode != UINT_MAX && w != onlyToNode) { //We are at an only_-restriction but not at the right turn.
-                            continue;
-                        }
-                        if( u != w ) { //only add an edge if turn is not a U-turn except it is the end of dead-end street.
-                            if (!CheckIfTurnIsRestricted(u, v, w) ) { //only add an edge if turn is not prohibited
-                                //insert next (node, parent) only if w has not yet been explored
-                                if(UINT_MAX == componentsIndex[w]) {
-                                    //mark node as read
-                                    componentsIndex[w] = currentComponent;
-                                    bfsQueue.push(std::make_pair(w,v));
-                                    p.printIncrement();
-                                }
-                            }
-                        }
-                    }
-                }
+    // Run a BFS on the undirected graph and identify small components
+    BFSComponentExplorer<NodeBasedDynamicGraph> component_explorer(
+        *m_node_based_graph, *m_restriction_map, m_barrier_nodes);
+
+    component_explorer.run();
+
+    SimpleLogger().Write() << "identified: " << component_explorer.GetNumberOfComponents()
+                           << " many components";
+    SimpleLogger().Write() << "generating edge-expanded nodes";
+
+    Percent p(m_node_based_graph->GetNumberOfNodes());
+
+    // loop over all edges and generate new set of nodes
+    for (NodeID u = 0, end = m_node_based_graph->GetNumberOfNodes(); u < end; ++u)
+    {
+        BOOST_ASSERT(u != SPECIAL_NODEID);
+        BOOST_ASSERT(u < m_node_based_graph->GetNumberOfNodes());
+        p.printIncrement();
+        for (EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(u))
+        {
+            const EdgeData &edge_data = m_node_based_graph->GetEdgeData(e1);
+            if (edge_data.edgeBasedNodeID == SPECIAL_NODEID)
+            {
+                // continue;
             }
-            //push size into vector
-            vectorOfComponentSizes.push_back(sizeOfCurrentComponent);
-            //reset counters;
-            sizeOfCurrentComponent = 0;
-            ++currentComponent;
-        }
-    }
-    INFO("identified: " << vectorOfComponentSizes.size() << " many components");
-
-    p.reinit(_nodeBasedGraph->GetNumberOfNodes());
-    //loop over all edges and generate new set of nodes.
-    for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
-        for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
-            _NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
-
-            if(_nodeBasedGraph->GetEdgeData(e1).type != SHRT_MAX) {
-                assert(e1 != UINT_MAX);
-                assert(u != UINT_MAX);
-                assert(v != UINT_MAX);
-                //edges that end on bollard nodes may actually be in two distinct components
-                InsertEdgeBasedNode(e1, u, v, (std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 1000) );
+            BOOST_ASSERT(e1 != SPECIAL_EDGEID);
+            const NodeID v = m_node_based_graph->GetTarget(e1);
+
+            BOOST_ASSERT(SPECIAL_NODEID != v);
+            // pick only every other edge
+            if (u > v)
+            {
+                continue;
             }
+
+            BOOST_ASSERT(u < v);
+            BOOST_ASSERT(edge_data.type != SHRT_MAX);
+
+            // Note: edges that end on barrier nodes or on a turn restriction
+            // may actually be in two distinct components. We choose the smallest
+            const unsigned size_of_component = std::min(component_explorer.GetComponentSize(u),
+                                                        component_explorer.GetComponentSize(v));
+
+            const bool component_is_tiny = (size_of_component < 1000);
+            InsertEdgeBasedNode(u, v, e1, component_is_tiny);
         }
     }
 
-    std::vector<NodeID>().swap(vectorOfComponentSizes);
-    std::vector<NodeID>().swap(componentsIndex);
+    SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size()
+                           << " nodes in edge-expanded graph";
+}
+
+/**
+ * Actually it also generates OriginalEdgeData and serializes them...
+ */
+void
+EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
+                                                 lua_State *lua_state)
+{
+    SimpleLogger().Write() << "generating edge-expanded edges";
+
+    unsigned node_based_edge_counter = 0;
+    unsigned original_edges_counter = 0;
+
+    std::ofstream edge_data_file(original_edge_data_filename.c_str(), std::ios::binary);
+
+    // writes a dummy value that is updated later
+    edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned));
 
     std::vector<OriginalEdgeData> original_edge_data_vector;
-    original_edge_data_vector.reserve(10000);
-
-    //Loop over all turns and generate new set of edges.
-    //Three nested loop look super-linear, but we are dealing with a linear number of turns only.
-    for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
-        for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
-            ++nodeBasedEdgeCounter;
-            _NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
-            bool isBollardNode = (_barrierNodes.find(v) != _barrierNodes.end());
-            //EdgeWeight heightPenalty = ComputeHeightPenalty(u, v);
-            NodeID onlyToNode = CheckForEmanatingIsOnlyTurn(u, v);
-            for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
-                const _NodeBasedDynamicGraph::NodeIterator w = _nodeBasedGraph->GetTarget(e2);
-
-                if(onlyToNode != UINT_MAX && w != onlyToNode) { //We are at an only_-restriction but not at the right turn.
-                    ++numberOfSkippedTurns;
+    original_edge_data_vector.reserve(1024 * 1024);
+
+    // Loop over all turns and generate new set of edges.
+    // Three nested loop look super-linear, but we are dealing with a (kind of)
+    // linear number of turns only.
+    unsigned restricted_turns_counter = 0;
+    unsigned skipped_uturns_counter = 0;
+    unsigned skipped_barrier_turns_counter = 0;
+    unsigned compressed = 0;
+
+    Percent p(m_node_based_graph->GetNumberOfNodes());
+
+    for (NodeID u = 0, end = m_node_based_graph->GetNumberOfNodes(); u < end; ++u)
+    {
+        for (EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(u))
+        {
+            if (!m_node_based_graph->GetEdgeData(e1).forward)
+            {
+                continue;
+            }
+
+            ++node_based_edge_counter;
+            const NodeID v = m_node_based_graph->GetTarget(e1);
+            const NodeID to_node_of_only_restriction =
+                m_restriction_map->CheckForEmanatingIsOnlyTurn(u, v);
+            const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
+
+            for (EdgeID e2 : m_node_based_graph->GetAdjacentEdgeRange(v))
+            {
+                if (!m_node_based_graph->GetEdgeData(e2).forward)
+                {
                     continue;
                 }
+                const NodeID w = m_node_based_graph->GetTarget(e2);
 
-                if(u == w && 1 != _nodeBasedGraph->GetOutDegree(v) ) {
+                if ((to_node_of_only_restriction != SPECIAL_NODEID) &&
+                    (w != to_node_of_only_restriction))
+                {
+                    // We are at an only_-restriction but not at the right turn.
+                    ++restricted_turns_counter;
                     continue;
                 }
 
-                if( !isBollardNode ) { //only add an edge if turn is not a U-turn except it is the end of dead-end street.
-                    if (!CheckIfTurnIsRestricted(u, v, w) || (onlyToNode != UINT_MAX && w == onlyToNode)) { //only add an edge if turn is not prohibited
-                        const _NodeBasedDynamicGraph::EdgeData edgeData1 = _nodeBasedGraph->GetEdgeData(e1);
-                        const _NodeBasedDynamicGraph::EdgeData edgeData2 = _nodeBasedGraph->GetEdgeData(e2);
-                        assert(edgeData1.edgeBasedNodeID < _nodeBasedGraph->GetNumberOfEdges());
-                        assert(edgeData2.edgeBasedNodeID < _nodeBasedGraph->GetNumberOfEdges());
-
-                        if(!edgeData1.forward || !edgeData2.forward) {
-                            continue;
-                        }
-
-                        unsigned distance = edgeData1.distance;
-                        if(_trafficLights.find(v) != _trafficLights.end()) {
-                            distance += speedProfile.trafficSignalPenalty;
-                        }
-                        unsigned penalty = 0;
-                        TurnInstruction turnInstruction = AnalyzeTurn(u, v, w, penalty, myLuaState);
-                        if(turnInstruction == TurnInstructions.UTurn)
-                            distance += speedProfile.uTurnPenalty;
-//                        if(!edgeData1.isAccessRestricted && edgeData2.isAccessRestricted) {
-//                            distance += TurnInstructions.AccessRestrictionPenalty;
-//                            turnInstruction |= TurnInstructions.AccessRestrictionFlag;
-//                        }
-                        distance += penalty;
-
-
-                        //distance += heightPenalty;
-                        //distance += ComputeTurnPenalty(u, v, w);
-                        assert(edgeData1.edgeBasedNodeID != edgeData2.edgeBasedNodeID);
-                        OriginalEdgeData oed(v,edgeData2.nameID, turnInstruction);
-                        original_edge_data_vector.push_back(oed);
-                        ++numberOfOriginalEdges;
-
-                        if(original_edge_data_vector.size() > 100000) {
-                            originalEdgeDataOutFile.write((char*)&(original_edge_data_vector[0]), original_edge_data_vector.size()*sizeof(OriginalEdgeData));
-                            original_edge_data_vector.clear();
-                        }
-
-                        EdgeBasedEdge newEdge(edgeData1.edgeBasedNodeID, edgeData2.edgeBasedNodeID, edgeBasedEdges.size(), distance, true, false );
-                        edgeBasedEdges.push_back(newEdge);
-                    } else {
-                        ++numberOfSkippedTurns;
+                if (is_barrier_node)
+                {
+                    if (u != w)
+                    {
+                        ++skipped_barrier_turns_counter;
+                        continue;
+                    }
+                }
+                else
+                {
+                    if ((u == w) && (m_node_based_graph->GetOutDegree(v) > 1))
+                    {
+                        ++skipped_uturns_counter;
+                        continue;
                     }
                 }
+
+                // only add an edge if turn is not a U-turn except when it is
+                // at the end of a dead-end street
+                if (m_restriction_map->CheckIfTurnIsRestricted(u, v, w) &&
+                    (to_node_of_only_restriction == SPECIAL_NODEID) &&
+                    (w != to_node_of_only_restriction))
+                {
+                    // We are at an only_-restriction but not at the right turn.
+                    ++restricted_turns_counter;
+                    continue;
+                }
+
+                // only add an edge if turn is not prohibited
+                const EdgeData &edge_data1 = m_node_based_graph->GetEdgeData(e1);
+                const EdgeData &edge_data2 = m_node_based_graph->GetEdgeData(e2);
+
+                BOOST_ASSERT(edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID);
+                BOOST_ASSERT(edge_data1.forward);
+                BOOST_ASSERT(edge_data2.forward);
+
+                // the following is the core of the loop.
+                unsigned distance = edge_data1.distance;
+                if (m_traffic_lights.find(v) != m_traffic_lights.end())
+                {
+                    distance += speed_profile.trafficSignalPenalty;
+                }
+                const double angle = GetAngleBetweenThreeFixedPointCoordinates(
+                m_node_info_list[u], m_node_info_list[v], m_node_info_list[w]);
+                const int turn_penalty = GetTurnPenalty(angle, lua_state);
+                TurnInstruction turn_instruction = AnalyzeTurn(u, v, w, angle);
+                if (turn_instruction == TurnInstruction::UTurn)
+                {
+                    distance += speed_profile.uTurnPenalty;
+                }
+                distance += turn_penalty;
+
+                const bool edge_is_compressed = m_geometry_compressor.HasEntryForID(e1);
+
+                if (edge_is_compressed)
+                {
+                    ++compressed;
+                }
+
+                original_edge_data_vector.emplace_back(
+                    (edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : v),
+                    edge_data1.nameID,
+                    turn_instruction,
+                    edge_is_compressed);
+
+                ++original_edges_counter;
+
+                if (original_edge_data_vector.size() > 1024 * 1024 * 10)
+                {
+                    FlushVectorToStream(edge_data_file, original_edge_data_vector);
+                }
+
+                BOOST_ASSERT(SPECIAL_NODEID != edge_data1.edgeBasedNodeID);
+                BOOST_ASSERT(SPECIAL_NODEID != edge_data2.edgeBasedNodeID);
+
+                m_edge_based_edge_list.emplace_back(EdgeBasedEdge(edge_data1.edgeBasedNodeID,
+                                                                  edge_data2.edgeBasedNodeID,
+                                                                  m_edge_based_edge_list.size(),
+                                                                  distance,
+                                                                  true,
+                                                                  false));
             }
         }
         p.printIncrement();
     }
-    originalEdgeDataOutFile.write((char*)&(original_edge_data_vector[0]), original_edge_data_vector.size()*sizeof(OriginalEdgeData));
-    originalEdgeDataOutFile.seekp(std::ios::beg);
-    originalEdgeDataOutFile.write((char*)&numberOfOriginalEdges, sizeof(unsigned));
-    originalEdgeDataOutFile.close();
-
-//    INFO("Sorting edge-based Nodes");
-//    std::sort(edgeBasedNodes.begin(), edgeBasedNodes.end());
-//    INFO("Removing duplicate nodes (if any)");
-//    edgeBasedNodes.erase( std::unique(edgeBasedNodes.begin(), edgeBasedNodes.end()), edgeBasedNodes.end() );
-//    INFO("Applying vector self-swap trick to free up memory");
-//    INFO("size: " << edgeBasedNodes.size() << ", cap: " << edgeBasedNodes.capacity());
-//    std::vector<EdgeBasedNode>(edgeBasedNodes).swap(edgeBasedNodes);
-//    INFO("size: " << edgeBasedNodes.size() << ", cap: " << edgeBasedNodes.capacity());
-    INFO("Node-based graph contains " << nodeBasedEdgeCounter     << " edges");
-    INFO("Edge-based graph contains " << edgeBasedEdges.size()    << " edges");
-//    INFO("Edge-based graph contains " << edgeBasedEdges.size()    << " edges, blowup is " << 2*((double)edgeBasedEdges.size()/(double)nodeBasedEdgeCounter));
-    INFO("Edge-based graph skipped "  << numberOfSkippedTurns     << " turns, defined by " << numberOfTurnRestrictions << " restrictions.");
-    INFO("Generated " << edgeBasedNodes.size() << " edge based nodes");
+    FlushVectorToStream(edge_data_file, original_edge_data_vector);
+
+    edge_data_file.seekp(std::ios::beg);
+    edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned));
+    edge_data_file.close();
+
+    SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() << " edge based nodes";
+    SimpleLogger().Write() << "Node-based graph contains " << node_based_edge_counter << " edges";
+    SimpleLogger().Write() << "Edge-expanded graph ...";
+    SimpleLogger().Write() << "  contains " << m_edge_based_edge_list.size() << " edges";
+    SimpleLogger().Write() << "  skips " << restricted_turns_counter << " turns, "
+                                                                        "defined by "
+                           << m_restriction_map->size() << " restrictions";
+    SimpleLogger().Write() << "  skips " << skipped_uturns_counter << " U turns";
+    SimpleLogger().Write() << "  skips " << skipped_barrier_turns_counter << " turns over barriers";
 }
 
-TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, unsigned& penalty, lua_State *myLuaState) const {
-    const double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]);
+int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) const
+{
 
-    if( speedProfile.has_turn_penalty_function ) {
-    	try {
-            //call lua profile to compute turn penalty
-            penalty = luabind::call_function<int>( myLuaState, "turn_function", 180-angle );
-        } catch (const luabind::error &er) {
-            std::cerr << er.what() << std::endl;
-            //TODO handle lua errors
+    if (speed_profile.has_turn_penalty_function)
+    {
+        try
+        {
+            // call lua profile to compute turn penalty
+            return luabind::call_function<int>(lua_state, "turn_function", 180. - angle);
         }
-    } else {
-        penalty = 0;
+        catch (const luabind::error &er) { SimpleLogger().Write(logWARNING) << er.what(); }
     }
+    return 0;
+}
 
-    if(u == w) {
-        return TurnInstructions.UTurn;
+TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u,
+                                                   const NodeID v,
+                                                   const NodeID w,
+                                                   double angle)
+    const
+{
+    if (u == w)
+    {
+        return TurnInstruction::UTurn;
     }
 
-    _NodeBasedDynamicGraph::EdgeIterator edge1 = _nodeBasedGraph->FindEdge(u, v);
-    _NodeBasedDynamicGraph::EdgeIterator edge2 = _nodeBasedGraph->FindEdge(v, w);
+    const EdgeID edge1 = m_node_based_graph->FindEdge(u, v);
+    const EdgeID edge2 = m_node_based_graph->FindEdge(v, w);
 
-    _NodeBasedDynamicGraph::EdgeData & data1 = _nodeBasedGraph->GetEdgeData(edge1);
-    _NodeBasedDynamicGraph::EdgeData & data2 = _nodeBasedGraph->GetEdgeData(edge2);
+    const EdgeData &data1 = m_node_based_graph->GetEdgeData(edge1);
+    const EdgeData &data2 = m_node_based_graph->GetEdgeData(edge2);
 
-    if(!data1.contraFlow && data2.contraFlow) {
-    	return TurnInstructions.EnterAgainstAllowedDirection;
+    if (!data1.contraFlow && data2.contraFlow)
+    {
+        return TurnInstruction::EnterAgainstAllowedDirection;
     }
-    if(data1.contraFlow && !data2.contraFlow) {
-    	return TurnInstructions.LeaveAgainstAllowedDirection;
+    if (data1.contraFlow && !data2.contraFlow)
+    {
+        return TurnInstruction::LeaveAgainstAllowedDirection;
     }
 
-    //roundabouts need to be handled explicitely
-    if(data1.roundabout && data2.roundabout) {
-        //Is a turn possible? If yes, we stay on the roundabout!
-        if( 1 == (_nodeBasedGraph->EndEdges(v) - _nodeBasedGraph->BeginEdges(v)) ) {
-            //No turn possible.
-            return TurnInstructions.NoTurn;
+    // roundabouts need to be handled explicitely
+    if (data1.roundabout && data2.roundabout)
+    {
+        // Is a turn possible? If yes, we stay on the roundabout!
+        if (1 == m_node_based_graph->GetDirectedOutDegree(v))
+        {
+            // No turn possible.
+            return TurnInstruction::NoTurn;
         }
-        return TurnInstructions.StayOnRoundAbout;
+        return TurnInstruction::StayOnRoundAbout;
     }
-    //Does turn start or end on roundabout?
-    if(data1.roundabout || data2.roundabout) {
-        //We are entering the roundabout
-        if( (!data1.roundabout) && data2.roundabout) {
-            return TurnInstructions.EnterRoundAbout;
+    // Does turn start or end on roundabout?
+    if (data1.roundabout || data2.roundabout)
+    {
+        // We are entering the roundabout
+        if ((!data1.roundabout) && data2.roundabout)
+        {
+            return TurnInstruction::EnterRoundAbout;
         }
-        //We are leaving the roundabout
-        if(data1.roundabout && (!data2.roundabout) ) {
-            return TurnInstructions.LeaveRoundAbout;
+        // We are leaving the roundabout
+        if (data1.roundabout && (!data2.roundabout))
+        {
+            return TurnInstruction::LeaveRoundAbout;
         }
     }
 
-    //If street names stay the same and if we are certain that it is not a roundabout, we skip it.
-    if( (data1.nameID == data2.nameID) && (0 != data1.nameID)) {
-        return TurnInstructions.NoTurn;
-    }
-    if( (data1.nameID == data2.nameID) && (0 == data1.nameID) && (_nodeBasedGraph->GetOutDegree(v) <= 2) ) {
-        return TurnInstructions.NoTurn;
+    // If street names stay the same and if we are certain that it is not a
+    // a segment of a roundabout, we skip it.
+    if (data1.nameID == data2.nameID)
+    {
+        // TODO: Here we should also do a small graph exploration to check for
+        //      more complex situations
+        if (0 != data1.nameID)
+        {
+            return TurnInstruction::NoTurn;
+        }
+        else if (m_node_based_graph->GetOutDegree(v) <= 2)
+        {
+            return TurnInstruction::NoTurn;
+        }
     }
 
-    return TurnInstructions.GetTurnDirectionOfInstruction(angle);
-}
-
-unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const {
-    return _nodeBasedGraph->GetNumberOfEdges();
+    return TurnInstructionsClass::GetTurnDirectionOfInstruction(angle);
 }
 
-/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
-template<class CoordinateT>
-double EdgeBasedGraphFactory::GetAngleBetweenTwoEdges(const CoordinateT& A, const CoordinateT& C, const CoordinateT& B) const {
-    const double v1x = (A.lon - C.lon)/100000.;
-    const double v1y = lat2y(A.lat/100000.) - lat2y(C.lat/100000.);
-    const double v2x = (B.lon - C.lon)/100000.;
-    const double v2y = lat2y(B.lat/100000.) - lat2y(C.lat/100000.);
-
-    double angle = (atan2(v2y,v2x) - atan2(v1y,v1x) )*180/M_PI;
-    while(angle < 0)
-        angle += 360;
-    return angle;
+unsigned EdgeBasedGraphFactory::GetNumberOfEdgeBasedNodes() const
+{
+    return m_number_of_edge_based_nodes;
 }
diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h
index c51e4d2..cf489c5 100644
--- a/Contractor/EdgeBasedGraphFactory.h
+++ b/Contractor/EdgeBasedGraphFactory.h
@@ -1,162 +1,126 @@
 /*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
 
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
- 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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-/*
- * This class constructs the edge base representation of a graph from a given node based edge list
- */
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+//  This class constructs the edge-expanded routing graph
 
 #ifndef EDGEBASEDGRAPHFACTORY_H_
 #define EDGEBASEDGRAPHFACTORY_H_
 
 #include "../typedefs.h"
 #include "../DataStructures/DeallocatingVector.h"
-#include "../DataStructures/DynamicGraph.h"
-#include "../Extractor/ExtractorStructs.h"
-#include "../DataStructures/HashTable.h"
-#include "../DataStructures/ImportEdge.h"
-#include "../DataStructures/MercatorUtil.h"
-#include "../DataStructures/QueryEdge.h"
-#include "../DataStructures/Percent.h"
+#include "../DataStructures/EdgeBasedNode.h"
+#include "../DataStructures/OriginalEdgeData.h"
+#include "../DataStructures/QueryNode.h"
 #include "../DataStructures/TurnInstructions.h"
-#include "../Util/BaseConfiguration.h"
-#include "../Util/LuaUtil.h"
-
-#include <stxxl.h>
-
-#include <boost/foreach.hpp>
-#include <boost/make_shared.hpp>
-#include <boost/noncopyable.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/unordered_map.hpp>
-#include <boost/unordered_set.hpp>
-
-#include <cstdlib>
+#include "../DataStructures/NodeBasedGraph.h"
+#include "../DataStructures/RestrictionMap.h"
+#include "GeometryCompressor.h"
 
 #include <algorithm>
+#include <iosfwd>
+#include <memory>
 #include <queue>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
-class EdgeBasedGraphFactory : boost::noncopyable {
-public:
-    struct EdgeBasedNode {
-        bool operator<(const EdgeBasedNode & other) const {
-            return other.id < id;
-        }
+struct lua_State;
 
-        bool operator==(const EdgeBasedNode & other) const {
-            return id == other.id;
-        }
+class EdgeBasedGraphFactory
+{
+  public:
+    EdgeBasedGraphFactory() = delete;
+    EdgeBasedGraphFactory(const EdgeBasedGraphFactory &) = delete;
 
-        inline _Coordinate Centroid() const {
-            _Coordinate centroid;
-            //The coordinates of the midpoint are given by:
-            //x = (x1 + x2) /2 and y = (y1 + y2) /2.
-            centroid.lon = (std::min(lon1, lon2) + std::max(lon1, lon2))/2;
-            centroid.lat = (std::min(lat1, lat2) + std::max(lat1, lat2))/2;
-            return centroid;
-        }
+    struct SpeedProfileProperties;
+
+    explicit EdgeBasedGraphFactory(const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph,
+                                   std::unique_ptr<RestrictionMap> restricion_map,
+                                   std::vector<NodeID> &barrier_node_list,
+                                   std::vector<NodeID> &traffic_light_node_list,
+                                   std::vector<NodeInfo> &m_node_info_list,
+                                   SpeedProfileProperties &speed_profile);
+
+    void Run(const std::string &original_edge_data_filename,
+             const std::string &geometry_filename,
+             lua_State *lua_state);
+
+    void GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &edges);
+
+    void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
+
+    TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, double angle) const;
 
-        inline bool isIgnored() const {
-            return ignoreInGrid;
+    int GetTurnPenalty(double angle, lua_State *lua_state) const;
+
+    unsigned GetNumberOfEdgeBasedNodes() const;
+
+    struct SpeedProfileProperties
+    {
+        SpeedProfileProperties()
+            : trafficSignalPenalty(0), uTurnPenalty(0), has_turn_penalty_function(false)
+        {
         }
-        NodeID id;
-        int lat1;
-        int lat2;
-        int lon1;
-        int lon2:31;
-        bool belongsToTinyComponent:1;
-        NodeID nameID;
-        unsigned weight:31;
-        bool ignoreInGrid:1;
-    };
-
-    struct SpeedProfileProperties{
-        SpeedProfileProperties()  : trafficSignalPenalty(0), uTurnPenalty(0), has_turn_penalty_function(false) {}
+
         int trafficSignalPenalty;
         int uTurnPenalty;
         bool has_turn_penalty_function;
-    } speedProfile;
-
-private:
-    struct _NodeBasedEdgeData {
-        int distance;
-        unsigned edgeBasedNodeID;
-        unsigned nameID;
-        short type;
-        bool isAccessRestricted:1;
-        bool shortcut:1;
-        bool forward:1;
-        bool backward:1;
-        bool roundabout:1;
-        bool ignoreInGrid:1;
-        bool contraFlow:1;
-    };
-
-    struct _EdgeBasedEdgeData {
-        int distance;
-        unsigned via;
-        unsigned nameID;
-        bool forward;
-        bool backward;
-        TurnInstruction turnInstruction;
-    };
-
-    typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph;
-    typedef _NodeBasedDynamicGraph::InputEdge _NodeBasedEdge;
-    std::vector<NodeInfo>               inputNodeInfoList;
-    unsigned numberOfTurnRestrictions;
-
-    boost::shared_ptr<_NodeBasedDynamicGraph>   _nodeBasedGraph;
-    boost::unordered_set<NodeID>          _barrierNodes;
-    boost::unordered_set<NodeID>          _trafficLights;
-
-    typedef std::pair<NodeID, NodeID> RestrictionSource;
-    typedef std::pair<NodeID, bool>   RestrictionTarget;
-    typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
-    typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
-    std::vector<EmanatingRestrictionsVector> _restrictionBucketVector;
-    RestrictionMap _restrictionMap;
-
-    DeallocatingVector<EdgeBasedEdge>   edgeBasedEdges;
-    std::vector<EdgeBasedNode>   edgeBasedNodes;
-
-    NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
-    bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
-    void InsertEdgeBasedNode(
-            _NodeBasedDynamicGraph::EdgeIterator e1,
-            _NodeBasedDynamicGraph::NodeIterator u,
-            _NodeBasedDynamicGraph::NodeIterator v,
-            bool belongsToTinyComponent);
-    template<class CoordinateT>
-    double GetAngleBetweenTwoEdges(const CoordinateT& A, const CoordinateT& C, const CoordinateT& B) const;
-
-public:
-    template< class InputEdgeT >
-    explicit EdgeBasedGraphFactory(int nodes, std::vector<InputEdgeT> & inputEdges, std::vector<NodeID> & _bollardNodes, std::vector<NodeID> & trafficLights, std::vector<_Restriction> & inputRestrictions, std::vector<NodeInfo> & nI, SpeedProfileProperties speedProfile);
-
-    void Run(const char * originalEdgeDataFilename, lua_State *myLuaState);
-    void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
-    void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes);
-    void GetOriginalEdgeData( std::vector< OriginalEdgeData> & originalEdgeData);
-    TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, unsigned& penalty, lua_State *myLuaState) const;
-    unsigned GetNumberOfNodes() const;
+    } speed_profile;
+
+  private:
+    typedef NodeBasedDynamicGraph::EdgeData EdgeData;
+
+    unsigned m_number_of_edge_based_nodes;
+
+    std::vector<NodeInfo> m_node_info_list;
+    std::vector<EdgeBasedNode> m_edge_based_node_list;
+    DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
+
+    std::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
+    std::unordered_set<NodeID> m_barrier_nodes;
+    std::unordered_set<NodeID> m_traffic_lights;
+
+    std::unique_ptr<RestrictionMap> m_restriction_map;
+
+    GeometryCompressor m_geometry_compressor;
+
+    void CompressGeometry();
+    void RenumberEdges();
+    void GenerateEdgeExpandedNodes();
+    void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
+                                   lua_State *lua_state);
+
+    void InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool belongsToTinyComponent);
+
+    void FlushVectorToStream(std::ofstream &edge_data_file,
+                             std::vector<OriginalEdgeData> &original_edge_data_vector) const;
+
+    unsigned max_id;
 };
 
 #endif /* EDGEBASEDGRAPHFACTORY_H_ */
diff --git a/Contractor/GeometryCompressor.cpp b/Contractor/GeometryCompressor.cpp
new file mode 100644
index 0000000..7c51910
--- /dev/null
+++ b/Contractor/GeometryCompressor.cpp
@@ -0,0 +1,227 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "GeometryCompressor.h"
+#include "../Util/SimpleLogger.h"
+
+#include <boost/assert.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+#include <limits>
+#include <string>
+
+int free_list_maximum = 0;
+int UniqueNumber() { return ++free_list_maximum; }
+
+GeometryCompressor::GeometryCompressor()
+{
+    m_free_list.reserve(100);
+    IncreaseFreeList();
+}
+
+void GeometryCompressor::IncreaseFreeList()
+{
+    m_compressed_geometries.resize(m_compressed_geometries.size() + 100);
+    for (unsigned i = 100; i > 0; --i)
+    {
+        m_free_list.emplace_back(free_list_maximum);
+        ++free_list_maximum;
+    }
+}
+
+bool GeometryCompressor::HasEntryForID(const EdgeID edge_id) const
+{
+    auto iter = m_edge_id_to_list_index_map.find(edge_id);
+    return iter != m_edge_id_to_list_index_map.end();
+}
+
+unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) const
+{
+    auto map_iterator = m_edge_id_to_list_index_map.find(edge_id);
+    BOOST_ASSERT(map_iterator != m_edge_id_to_list_index_map.end());
+    BOOST_ASSERT(map_iterator->second < m_compressed_geometries.size());
+    return map_iterator->second;
+}
+
+void GeometryCompressor::SerializeInternalVector(const std::string &path) const
+{
+
+    boost::filesystem::fstream geometry_out_stream(path, std::ios::binary | std::ios::out);
+    const unsigned compressed_geometries = m_compressed_geometries.size() + 1;
+    BOOST_ASSERT(std::numeric_limits<unsigned>::max() != compressed_geometries);
+    geometry_out_stream.write((char *)&compressed_geometries, sizeof(unsigned));
+
+    // write indices array
+    unsigned prefix_sum_of_list_indices = 0;
+    for (const auto &elem : m_compressed_geometries)
+    {
+        geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
+
+        const std::vector<CompressedNode> &current_vector = elem;
+        const unsigned unpacked_size = current_vector.size();
+        BOOST_ASSERT(std::numeric_limits<unsigned>::max() != unpacked_size);
+        prefix_sum_of_list_indices += unpacked_size;
+    }
+    // sentinel element
+    geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
+
+    // number of geometry entries to follow, it is the (inclusive) prefix sum
+    geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
+
+    unsigned control_sum = 0;
+    // write compressed geometries
+    for (auto &elem : m_compressed_geometries)
+    {
+        const std::vector<CompressedNode> &current_vector = elem;
+        const unsigned unpacked_size = current_vector.size();
+        control_sum += unpacked_size;
+        BOOST_ASSERT(std::numeric_limits<unsigned>::max() != unpacked_size);
+        for (const CompressedNode current_node : current_vector)
+        {
+            geometry_out_stream.write((char *)&(current_node.first), sizeof(NodeID));
+        }
+    }
+    BOOST_ASSERT(control_sum == prefix_sum_of_list_indices);
+    // all done, let's close the resource
+    geometry_out_stream.close();
+}
+
+void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
+                                      const EdgeID edge_id_2,
+                                      const NodeID via_node_id,
+                                      const NodeID target_node_id,
+                                      const EdgeWeight weight1,
+                                      const EdgeWeight weight2)
+{
+    // remove super-trivial geometries
+    BOOST_ASSERT(SPECIAL_EDGEID != edge_id_1);
+    BOOST_ASSERT(SPECIAL_EDGEID != edge_id_2);
+    BOOST_ASSERT(SPECIAL_NODEID != via_node_id);
+    BOOST_ASSERT(SPECIAL_NODEID != target_node_id);
+    BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight1);
+    BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight2);
+
+    // append list of removed edge_id plus via node to surviving edge id:
+    // <surv_1, .. , surv_n, via_node_id, rem_1, .. rem_n
+    //
+    // General scheme:
+    // 1. append via node id to list of edge_id_1
+    // 2. find list for edge_id_2, if yes add all elements and delete it
+
+    // Add via node id. List is created if it does not exist
+    if (!HasEntryForID(edge_id_1))
+    {
+        // create a new entry in the map
+        if (0 == m_free_list.size())
+        {
+            // make sure there is a place to put the entries
+            IncreaseFreeList();
+        }
+        BOOST_ASSERT(!m_free_list.empty());
+        m_edge_id_to_list_index_map[edge_id_1] = m_free_list.back();
+        m_free_list.pop_back();
+    }
+
+    // find bucket index
+    const auto iter = m_edge_id_to_list_index_map.find(edge_id_1);
+    BOOST_ASSERT(iter != m_edge_id_to_list_index_map.end());
+    const unsigned edge_bucket_id1 = iter->second;
+    BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1));
+    BOOST_ASSERT(edge_bucket_id1 < m_compressed_geometries.size());
+
+    std::vector<CompressedNode> &edge_bucket_list1 = m_compressed_geometries[edge_bucket_id1];
+
+    if (edge_bucket_list1.empty())
+    {
+        edge_bucket_list1.emplace_back(via_node_id, weight1);
+    }
+
+    BOOST_ASSERT(0 < edge_bucket_list1.size());
+    BOOST_ASSERT(!edge_bucket_list1.empty());
+
+    if (HasEntryForID(edge_id_2))
+    {
+        // second edge is not atomic anymore
+        const unsigned list_to_remove_index = GetPositionForID(edge_id_2);
+        BOOST_ASSERT(list_to_remove_index < m_compressed_geometries.size());
+
+        std::vector<CompressedNode> &edge_bucket_list2 =
+            m_compressed_geometries[list_to_remove_index];
+
+        // found an existing list, append it to the list of edge_id_1
+        edge_bucket_list1.insert(
+            edge_bucket_list1.end(), edge_bucket_list2.begin(), edge_bucket_list2.end());
+
+        // remove the list of edge_id_2
+        m_edge_id_to_list_index_map.erase(edge_id_2);
+        BOOST_ASSERT(m_edge_id_to_list_index_map.end() ==
+                     m_edge_id_to_list_index_map.find(edge_id_2));
+        edge_bucket_list2.clear();
+        BOOST_ASSERT(0 == edge_bucket_list2.size());
+        m_free_list.emplace_back(list_to_remove_index);
+        BOOST_ASSERT(list_to_remove_index == m_free_list.back());
+    }
+    else
+    {
+        // we are certain that the second edge is atomic.
+        edge_bucket_list1.emplace_back(target_node_id, weight2);
+    }
+}
+
+void GeometryCompressor::PrintStatistics() const
+{
+    const uint64_t compressed_edges = m_compressed_geometries.size();
+    BOOST_ASSERT(0 == compressed_edges % 2);
+    BOOST_ASSERT(m_compressed_geometries.size() + m_free_list.size() > 0);
+
+    uint64_t compressed_geometries = 0;
+    uint64_t longest_chain_length = 0;
+    for (const std::vector<CompressedNode> &current_vector : m_compressed_geometries)
+    {
+        compressed_geometries += current_vector.size();
+        longest_chain_length = std::max(longest_chain_length, (uint64_t)current_vector.size());
+    }
+
+    SimpleLogger().Write() << "Geometry successfully removed:"
+                              "\n  compressed edges: " << compressed_edges
+                           << "\n  compressed geometries: " << compressed_geometries
+                           << "\n  longest chain length: " << longest_chain_length
+                           << "\n  cmpr ratio: "
+                           << ((float)compressed_edges /
+                               std::max(compressed_geometries, (uint64_t)1))
+                           << "\n  avg chain length: "
+                           << (float)compressed_geometries /
+                                  std::max((uint64_t)1, compressed_edges);
+}
+
+const std::vector<GeometryCompressor::CompressedNode> &
+GeometryCompressor::GetBucketReference(const EdgeID edge_id) const
+{
+    const unsigned index = m_edge_id_to_list_index_map.at(edge_id);
+    return m_compressed_geometries.at(index);
+}
diff --git a/Contractor/GeometryCompressor.h b/Contractor/GeometryCompressor.h
new file mode 100644
index 0000000..7c4fba4
--- /dev/null
+++ b/Contractor/GeometryCompressor.h
@@ -0,0 +1,65 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "../typedefs.h"
+
+#include <unordered_map>
+
+#include <string>
+#include <vector>
+
+#ifndef GEOMETRY_COMPRESSOR_H
+#define GEOMETRY_COMPRESSOR_H
+
+class GeometryCompressor
+{
+  public:
+    typedef std::pair<NodeID, EdgeWeight> CompressedNode;
+
+    GeometryCompressor();
+    void CompressEdge(const EdgeID surviving_edge_id,
+                      const EdgeID removed_edge_id,
+                      const NodeID via_node_id,
+                      const NodeID target_node,
+                      const EdgeWeight weight1,
+                      const EdgeWeight weight2);
+
+    bool HasEntryForID(const EdgeID edge_id) const;
+    void PrintStatistics() const;
+    void SerializeInternalVector(const std::string &path) const;
+    unsigned GetPositionForID(const EdgeID edge_id) const;
+    const std::vector<GeometryCompressor::CompressedNode> &
+    GetBucketReference(const EdgeID edge_id) const;
+
+  private:
+    void IncreaseFreeList();
+    std::vector<std::vector<CompressedNode>> m_compressed_geometries;
+    std::vector<unsigned> m_free_list;
+    std::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map;
+};
+
+#endif // GEOMETRY_COMPRESSOR_H
diff --git a/Contractor/TemporaryStorage.cpp b/Contractor/TemporaryStorage.cpp
index 7c894b0..f9d4287 100644
--- a/Contractor/TemporaryStorage.cpp
+++ b/Contractor/TemporaryStorage.cpp
@@ -1,144 +1,172 @@
 /*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
 
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
- 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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#include <boost/foreach.hpp>
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #include "TemporaryStorage.h"
 
-TemporaryStorage::TemporaryStorage() {
-    try {
-        tempDirectory = boost::filesystem::temp_directory_path();
-    } catch(boost::filesystem::filesystem_error & e) {
-        ERR("could not retrieve location of temporary path: " << e.what());
+StreamData::StreamData()
+    : write_mode(true),
+      temp_path(boost::filesystem::unique_path(temp_directory / TemporaryFilePattern)),
+      temp_file(new boost::filesystem::fstream(
+          temp_path, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
+      readWriteMutex(std::make_shared<boost::mutex>())
+{
+    if (temp_file->fail())
+    {
+        throw OSRMException("temporary file could not be created");
     }
 }
 
-TemporaryStorage & TemporaryStorage::GetInstance(){
-    static TemporaryStorage runningInstance;
-    return runningInstance;
-}
+TemporaryStorage::TemporaryStorage() { temp_directory = boost::filesystem::temp_directory_path(); }
 
-TemporaryStorage::~TemporaryStorage() {
-    removeAll();
+TemporaryStorage &TemporaryStorage::GetInstance()
+{
+    static TemporaryStorage static_instance;
+    return static_instance;
 }
 
-void TemporaryStorage::removeAll() {
-    boost::mutex::scoped_lock lock(mutex);
-    try {
-        for(unsigned slotID = 0; slotID < vectorOfStreamDatas.size(); ++slotID)
-            deallocateSlot(slotID);
+TemporaryStorage::~TemporaryStorage() { RemoveAll(); }
 
-    } catch(boost::filesystem::filesystem_error & e) {
-        ERR("could not retrieve location of temporary path: " << e.what());
+void TemporaryStorage::RemoveAll()
+{
+    boost::mutex::scoped_lock lock(mutex);
+    for (unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id)
+    {
+        DeallocateSlot(slot_id);
     }
-    vectorOfStreamDatas.clear();
+    stream_data_list.clear();
 }
 
-int TemporaryStorage::allocateSlot() {
+int TemporaryStorage::AllocateSlot()
+{
     boost::mutex::scoped_lock lock(mutex);
-    try {
-        vectorOfStreamDatas.push_back(StreamData());
-        //INFO("created new temporary file: " << vectorOfStreamDatas.back().pathToTemporaryFile);
-    } catch(boost::filesystem::filesystem_error & e) {
-        abort(e);
-    }
-    return vectorOfStreamDatas.size() - 1;
+    try { stream_data_list.push_back(StreamData()); }
+    catch (boost::filesystem::filesystem_error &e) { Abort(e); }
+    CheckIfTemporaryDeviceFull();
+    return stream_data_list.size() - 1;
 }
 
-void TemporaryStorage::deallocateSlot(int slotID) {
-    try {
-        StreamData & data = vectorOfStreamDatas[slotID];
+void TemporaryStorage::DeallocateSlot(const int slot_id)
+{
+    try
+    {
+        StreamData &data = stream_data_list[slot_id];
         boost::mutex::scoped_lock lock(*data.readWriteMutex);
-                if(!boost::filesystem::exists(data.pathToTemporaryFile)) {
+        if (!boost::filesystem::exists(data.temp_path))
+        {
             return;
         }
-        if(data.streamToTemporaryFile->is_open())
-            data.streamToTemporaryFile->close();
+        if (data.temp_file->is_open())
+        {
+            data.temp_file->close();
+        }
 
-        //INFO("deallocating slot " << slotID << " and its file: " << data.pathToTemporaryFile);
-        boost::filesystem::remove(data.pathToTemporaryFile);
-    } catch(boost::filesystem::filesystem_error & e) {
-        abort(e);
+        boost::filesystem::remove(data.temp_path);
     }
+    catch (boost::filesystem::filesystem_error &e) { Abort(e); }
 }
 
-void TemporaryStorage::writeToSlot(int slotID, char * pointer, std::streamsize size) {
-    try {
-        StreamData & data = vectorOfStreamDatas[slotID];
+void TemporaryStorage::WriteToSlot(const int slot_id, char *pointer, const std::size_t size)
+{
+    try
+    {
+        StreamData &data = stream_data_list[slot_id];
+        BOOST_ASSERT(data.write_mode);
+
         boost::mutex::scoped_lock lock(*data.readWriteMutex);
-        if(!data.writeMode)
-            ERR("Writing after first read is not allowed");
-        data.streamToTemporaryFile->write(pointer, size);
-    } catch(boost::filesystem::filesystem_error & e) {
-        abort(e);
+        BOOST_ASSERT_MSG(data.write_mode, "Writing after first read is not allowed");
+        if (1073741824 < data.buffer.size())
+        {
+            data.temp_file->write(&data.buffer[0], data.buffer.size());
+            // data.temp_file->write(pointer, size);
+            data.buffer.clear();
+            CheckIfTemporaryDeviceFull();
+        }
+        data.buffer.insert(data.buffer.end(), pointer, pointer + size);
     }
+    catch (boost::filesystem::filesystem_error &e) { Abort(e); }
 }
-void TemporaryStorage::readFromSlot(int slotID, char * pointer, std::streamsize size) {
-    try {
-        StreamData & data = vectorOfStreamDatas[slotID];
+void TemporaryStorage::ReadFromSlot(const int slot_id, char *pointer, const std::size_t size)
+{
+    try
+    {
+        StreamData &data = stream_data_list[slot_id];
         boost::mutex::scoped_lock lock(*data.readWriteMutex);
-        if(data.writeMode) {
-            data.writeMode = false;
-            data.streamToTemporaryFile->seekg(0, data.streamToTemporaryFile->beg);
+        if (data.write_mode)
+        {
+            data.write_mode = false;
+            data.temp_file->write(&data.buffer[0], data.buffer.size());
+            data.buffer.clear();
+            data.temp_file->seekg(data.temp_file->beg);
+            BOOST_ASSERT(data.temp_file->beg == data.temp_file->tellg());
         }
-        data.streamToTemporaryFile->read(pointer, size);
-    } catch(boost::filesystem::filesystem_error & e) {
-        abort(e);
+        BOOST_ASSERT(!data.write_mode);
+        data.temp_file->read(pointer, size);
     }
+    catch (boost::filesystem::filesystem_error &error) { Abort(error); }
 }
 
-unsigned TemporaryStorage::getFreeBytesOnTemporaryDevice() {
-    boost::filesystem::space_info tempSpaceInfo;
-    try {
-        tempSpaceInfo = boost::filesystem::space(tempDirectory);
-    } catch(boost::filesystem::filesystem_error & e) {
-        abort(e);
+uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice()
+{
+    uint64_t value = -1;
+    try
+    {
+        boost::filesystem::path path = boost::filesystem::temp_directory_path();
+        boost::filesystem::space_info space_info = boost::filesystem::space(path);
+        value = space_info.free;
     }
-    return tempSpaceInfo.available;
+    catch (boost::filesystem::filesystem_error &error) { Abort(error); }
+    return value;
 }
 
-boost::filesystem::fstream::pos_type TemporaryStorage::tell(int slotID) {
+void TemporaryStorage::CheckIfTemporaryDeviceFull()
+{
+    boost::filesystem::path path = boost::filesystem::temp_directory_path();
+    boost::filesystem::space_info space_info = boost::filesystem::space(path);
+    if ((1024 * 1024) > space_info.free)
+    {
+        throw OSRMException("temporary device is full");
+    }
+}
+
+boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id)
+{
     boost::filesystem::fstream::pos_type position;
-    try {
-        StreamData & data = vectorOfStreamDatas[slotID];
+    try
+    {
+        StreamData &data = stream_data_list[slot_id];
         boost::mutex::scoped_lock lock(*data.readWriteMutex);
-        position = data.streamToTemporaryFile->tellp();
-    } catch(boost::filesystem::filesystem_error & e) {
-        abort(e);
-   }
-//    INFO("telling position: " << position);
+        position = data.temp_file->tellp();
+    }
+    catch (boost::filesystem::filesystem_error &e) { Abort(e); }
     return position;
 }
 
-void TemporaryStorage::abort(boost::filesystem::filesystem_error& ) {
-    removeAll();
-//    ERR("I/O Error occured: " << e.what());
-}
-
-void TemporaryStorage::seek(int slotID, boost::filesystem::fstream::pos_type position) {
-    try {
-        StreamData & data = vectorOfStreamDatas[slotID];
-        boost::mutex::scoped_lock lock(*data.readWriteMutex);
-        data.streamToTemporaryFile->seekg(position);
-//        INFO("seeking to position: " << position);
-    } catch(boost::filesystem::filesystem_error & e) {
-        abort(e);
-    }
+void TemporaryStorage::Abort(const boost::filesystem::filesystem_error &error)
+{
+    RemoveAll();
+    throw OSRMException(error.what());
 }
diff --git a/Contractor/TemporaryStorage.h b/Contractor/TemporaryStorage.h
index e189981..ca8598b 100644
--- a/Contractor/TemporaryStorage.h
+++ b/Contractor/TemporaryStorage.h
@@ -1,113 +1,96 @@
 /*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
 
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
- 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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef TEMPORARYSTORAGE_H_
 #define TEMPORARYSTORAGE_H_
 
-#include <vector>
-#include <fstream>
+#include "../Util/BoostFileSystemFix.h"
+#include "../Util/OSRMException.h"
+#include "../Util/SimpleLogger.h"
+#include "../typedefs.h"
 
+#include <boost/assert.hpp>
 #include <boost/filesystem.hpp>
 #include <boost/filesystem/fstream.hpp>
-#include <boost/shared_ptr.hpp>
 #include <boost/thread/mutex.hpp>
 
-#include "../typedefs.h"
+#include <cstdint>
+
+#include <vector>
+#include <fstream>
+#include <memory>
 
-//This is one big workaround for latest boost renaming woes.
-
-#if BOOST_FILESYSTEM_VERSION < 3
-#warning Boost Installation with Filesystem3 missing, activating workaround
-#include <cstdio>
-namespace boost {
-namespace filesystem {
-inline path temp_directory_path() {
-	char * buffer;
-	buffer = tmpnam (NULL);
-
-	return path(buffer);
-}
-
-inline path unique_path(const path&) {
-	return temp_directory_path();
-}
-
-}
-}
-
-#endif
-
-#ifndef BOOST_FILESYSTEM_VERSION
-#define BOOST_FILESYSTEM_VERSION 3
-#endif
-/**
- * This class implements a singleton file storage for temporary data.
- * temporary slots can be accessed by other objects through an int
- * On deallocation every slot gets deallocated
- *
- * Access is sequential, which means, that there is no random access
- * -> Data is written in first phase and reread in second.
- */
-
-static boost::filesystem::path tempDirectory;
+struct StreamData
+{
+    bool write_mode;
+    boost::filesystem::path temp_path;
+    std::shared_ptr<boost::filesystem::fstream> temp_file;
+    std::shared_ptr<boost::mutex> readWriteMutex;
+    std::vector<char> buffer;
+
+    StreamData();
+};
+
+// This class implements a singleton file storage for temporary data.
+// temporary slots can be accessed by other objects through an int
+// On deallocation every slot gets deallocated
+//
+// Access is sequential, which means, that there is no random access
+// -> Data is written in first phase and reread in second.
+
+static boost::filesystem::path temp_directory;
 static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%");
-class TemporaryStorage {
-public:
-    static TemporaryStorage & GetInstance();
+class TemporaryStorage
+{
+  public:
+    static TemporaryStorage &GetInstance();
     virtual ~TemporaryStorage();
 
-    int allocateSlot();
-    void deallocateSlot(int slotID);
-    void writeToSlot(int slotID, char * pointer, std::streamsize size);
-    void readFromSlot(int slotID, char * pointer, std::streamsize size);
-    //returns the number of free bytes
-    unsigned getFreeBytesOnTemporaryDevice();
-    boost::filesystem::fstream::pos_type tell(int slotID);
-    void seek(int slotID, boost::filesystem::fstream::pos_type);
-    void removeAll();
-private:
+    int AllocateSlot();
+    void DeallocateSlot(const int slot_id);
+    void WriteToSlot(const int slot_id, char *pointer, const std::size_t size);
+    void ReadFromSlot(const int slot_id, char *pointer, const std::size_t size);
+    // returns the number of free bytes
+    uint64_t GetFreeBytesOnTemporaryDevice();
+    boost::filesystem::fstream::pos_type Tell(const int slot_id);
+    void RemoveAll();
+
+  private:
     TemporaryStorage();
-    TemporaryStorage(TemporaryStorage const &){};
-    TemporaryStorage& operator=(TemporaryStorage const &) {
-        return *this;
-    }
-    void abort(boost::filesystem::filesystem_error& e);
-
-    struct StreamData {
-        bool writeMode;
-        boost::filesystem::path pathToTemporaryFile;
-        boost::shared_ptr<boost::filesystem::fstream> streamToTemporaryFile;
-        boost::shared_ptr<boost::mutex> readWriteMutex;
-        StreamData() :
-            writeMode(true),
-            pathToTemporaryFile (boost::filesystem::unique_path(tempDirectory.append(TemporaryFilePattern.begin(), TemporaryFilePattern.end()))),
-            streamToTemporaryFile(new boost::filesystem::fstream(pathToTemporaryFile, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
-            readWriteMutex(new boost::mutex)
-        {
-            if(streamToTemporaryFile->fail())
-                ERR("Aborting, because temporary file at " << pathToTemporaryFile << " could not be created");
-        }
-    };
-    //vector of file streams that is used to store temporary data
-    std::vector<StreamData> vectorOfStreamDatas;
+    TemporaryStorage(TemporaryStorage const &) {};
+
+    TemporaryStorage &operator=(TemporaryStorage const &) { return *this; }
+
+    void Abort(const boost::filesystem::filesystem_error &e);
+    void CheckIfTemporaryDeviceFull();
+
+    // vector of file streams that is used to store temporary data
     boost::mutex mutex;
+    std::vector<StreamData> stream_data_list;
 };
 
 #endif /* TEMPORARYSTORAGE_H_ */
diff --git a/DataStructures/BinaryHeap.h b/DataStructures/BinaryHeap.h
index f8b3470..00d3782 100644
--- a/DataStructures/BinaryHeap.h
+++ b/DataStructures/BinaryHeap.h
@@ -1,267 +1,289 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef BINARYHEAP_H_INCLUDED
-#define BINARYHEAP_H_INCLUDED
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-//Not compatible with non contiguous node ids
+*/
+
+#ifndef BINARY_HEAP_H
+#define BINARY_HEAP_H
+
+#include <boost/assert.hpp>
 
-#include <cassert>
-#include <limits>
-#include <vector>
 #include <algorithm>
+#include <limits>
 #include <map>
-#include <boost/unordered_map.hpp>
-
-template< typename NodeID, typename Key >
-class ArrayStorage {
-public:
+#include <type_traits>
+#include <unordered_map>
+#include <vector>
 
-    ArrayStorage( size_t size ) : positions( new Key[size] ) {
-        memset(positions, 0, size*sizeof(Key));
+template <typename NodeID, typename Key> class ArrayStorage
+{
+  public:
+    explicit ArrayStorage(size_t size) : positions(new Key[size])
+    {
+        memset(positions, 0, size * sizeof(Key));
     }
 
-    ~ArrayStorage() {
-        delete[] positions;
-    }
+    ~ArrayStorage() { delete[] positions; }
 
-    Key &operator[]( NodeID node ) {
-        return positions[node];
-    }
+    Key &operator[](NodeID node) { return positions[node]; }
 
     void Clear() {}
 
-private:
-    Key* positions;
+  private:
+    Key *positions;
 };
 
-template< typename NodeID, typename Key >
-class MapStorage {
-public:
+template <typename NodeID, typename Key> class MapStorage
+{
+  public:
+    explicit MapStorage(size_t) {}
 
-    MapStorage( size_t ) {}
+    Key &operator[](NodeID node) { return nodes[node]; }
 
-    Key &operator[]( NodeID node ) {
-        return nodes[node];
-    }
-
-    void Clear() {
-        nodes.clear();
-    }
-
-private:
-    std::map< NodeID, Key > nodes;
+    void Clear() { nodes.clear(); }
 
+  private:
+    std::map<NodeID, Key> nodes;
 };
 
-template< typename NodeID, typename Key >
-class UnorderedMapStorage {
-public:
-
-	UnorderedMapStorage( size_t ) {
-		//hash table gets 1000 Buckets
-		nodes.rehash(1000);
-	}
+template <typename NodeID, typename Key> class UnorderedMapStorage
+{
+  public:
+    explicit UnorderedMapStorage(size_t) { nodes.rehash(1000); }
 
-    Key &operator[]( const NodeID node ) {
-    	return nodes[node];
-    }
+    Key &operator[](const NodeID node) { return nodes[node]; }
 
-    void Clear() {
-        nodes.clear();
+    Key const &operator[](const NodeID node) const
+    {
+        auto iter = nodes.find(node);
+        return iter->second;
     }
 
-private:
-    boost::unordered_map< NodeID, Key > nodes;
-};
+    void Clear() { nodes.clear(); }
 
-template<typename NodeID = unsigned>
-struct _SimpleHeapData {
-    NodeID parent;
-    _SimpleHeapData( NodeID p ) : parent(p) { }
+  private:
+    std::unordered_map<NodeID, Key> nodes;
 };
 
-template < typename NodeID, typename Key, typename Weight, typename Data, typename IndexStorage = ArrayStorage<NodeID, NodeID> >
-class BinaryHeap {
-private:
-    BinaryHeap( const BinaryHeap& right );
-    void operator=( const BinaryHeap& right );
-public:
+template <typename NodeID,
+          typename Key,
+          typename Weight,
+          typename Data,
+          typename IndexStorage = ArrayStorage<NodeID, NodeID>>
+class BinaryHeap
+{
+  private:
+    BinaryHeap(const BinaryHeap &right);
+    void operator=(const BinaryHeap &right);
+
+  public:
     typedef Weight WeightType;
     typedef Data DataType;
 
-    BinaryHeap( size_t maxID )
-    : nodeIndex( maxID ) {
-        Clear();
-    }
+    explicit BinaryHeap(size_t maxID) : node_index(maxID) { Clear(); }
 
-    void Clear() {
-        heap.resize( 1 );
-        insertedNodes.clear();
-        heap[0].weight = std::numeric_limits< Weight >::min();
-        nodeIndex.Clear();
+    void Clear()
+    {
+        heap.resize(1);
+        inserted_nodes.clear();
+        heap[0].weight = std::numeric_limits<Weight>::min();
+        node_index.Clear();
     }
 
-    Key Size() const {
-        return static_cast<Key>( heap.size() - 1 );
-    }
+    std::size_t Size() const { return (heap.size() - 1); }
 
-    void Insert( NodeID node, Weight weight, const Data &data ) {
+    bool Empty() const { return 0 == Size(); }
+
+    void Insert(NodeID node, Weight weight, const Data &data)
+    {
         HeapElement element;
-        element.index = static_cast<NodeID>(insertedNodes.size());
+        element.index = static_cast<NodeID>(inserted_nodes.size());
         element.weight = weight;
         const Key key = static_cast<Key>(heap.size());
-        heap.push_back( element );
-        insertedNodes.push_back( HeapNode( node, key, weight, data ) );
-        nodeIndex[node] = element.index;
-        Upheap( key );
+        heap.emplace_back(element);
+        inserted_nodes.emplace_back(node, key, weight, data);
+        node_index[node] = element.index;
+        Upheap(key);
         CheckHeap();
     }
 
-    Data& GetData( NodeID node ) {
-        const Key index = nodeIndex[node];
-        return insertedNodes[index].data;
+    Data &GetData(NodeID node)
+    {
+        const Key index = node_index[node];
+        return inserted_nodes[index].data;
+    }
+
+    Data const &GetData(NodeID node) const
+    {
+        const Key index = node_index[node];
+        return inserted_nodes[index].data;
     }
 
-    Weight& GetKey( NodeID node ) {
-        const Key index = nodeIndex[node];
-        return insertedNodes[index].weight;
+    Weight &GetKey(NodeID node)
+    {
+        const Key index = node_index[node];
+        return inserted_nodes[index].weight;
     }
 
-    bool WasRemoved( NodeID node ) {
-        assert( WasInserted( node ) );
-        const Key index = nodeIndex[node];
-        return insertedNodes[index].key == 0;
+    bool WasRemoved(const NodeID node)
+    {
+        BOOST_ASSERT(WasInserted(node));
+        const Key index = node_index[node];
+        return inserted_nodes[index].key == 0;
     }
 
-    bool WasInserted( NodeID node ) {
-        const Key index = nodeIndex[node];
-        if ( index >= static_cast<Key> (insertedNodes.size()) )
+    bool WasInserted(const NodeID node)
+    {
+        const Key index = node_index[node];
+        if (index >= static_cast<Key>(inserted_nodes.size()))
+        {
             return false;
-        return insertedNodes[index].node == node;
+        }
+        return inserted_nodes[index].node == node;
     }
 
-    NodeID Min() const {
-        assert( heap.size() > 1 );
-        return insertedNodes[heap[1].index].node;
+    NodeID Min() const
+    {
+        BOOST_ASSERT(heap.size() > 1);
+        return inserted_nodes[heap[1].index].node;
     }
 
-    NodeID DeleteMin() {
-        assert( heap.size() > 1 );
+    NodeID DeleteMin()
+    {
+        BOOST_ASSERT(heap.size() > 1);
         const Key removedIndex = heap[1].index;
-        heap[1] = heap[heap.size()-1];
+        heap[1] = heap[heap.size() - 1];
         heap.pop_back();
-        if ( heap.size() > 1 )
-            Downheap( 1 );
-        insertedNodes[removedIndex].key = 0;
+        if (heap.size() > 1)
+        {
+            Downheap(1);
+        }
+        inserted_nodes[removedIndex].key = 0;
         CheckHeap();
-        return insertedNodes[removedIndex].node;
+        return inserted_nodes[removedIndex].node;
     }
 
-    void DeleteAll() {
-        for ( typename std::vector< HeapElement >::iterator i = heap.begin() + 1, iend = heap.end(); i != iend; ++i )
-            insertedNodes[i->index].key = 0;
-        heap.resize( 1 );
-        heap[0].weight = (std::numeric_limits< Weight >::min)();
+    void DeleteAll()
+    {
+        auto iend = heap.end();
+        for (typename std::vector<HeapElement>::iterator i = heap.begin() + 1; i != iend; ++i)
+        {
+            inserted_nodes[i->index].key = 0;
+        }
+        heap.resize(1);
+        heap[0].weight = (std::numeric_limits<Weight>::min)();
     }
 
-    void DecreaseKey( NodeID node, Weight weight ) {
-        assert( UINT_MAX != node );
-        const Key index = nodeIndex[node];
-        Key key = insertedNodes[index].key;
-        assert ( key >= 0 );
+    void DecreaseKey(NodeID node, Weight weight)
+    {
+        BOOST_ASSERT(std::numeric_limits<NodeID>::max() != node);
+        const Key &index = node_index[node];
+        Key &key = inserted_nodes[index].key;
+        BOOST_ASSERT(key >= 0);
 
-        insertedNodes[index].weight = weight;
+        inserted_nodes[index].weight = weight;
         heap[key].weight = weight;
-        Upheap( key );
+        Upheap(key);
         CheckHeap();
     }
 
-private:
-    class HeapNode {
-    public:
-        HeapNode() {
-        }
-        HeapNode( NodeID n, Key k, Weight w, Data d )
-        : node( n ), key( k ), weight( w ), data( d ) {
-        }
+  private:
+    class HeapNode
+    {
+      public:
+        HeapNode(NodeID n, Key k, Weight w, Data d) : node(n), key(k), weight(w), data(d) {}
 
         NodeID node;
         Key key;
         Weight weight;
         Data data;
     };
-    struct HeapElement {
+    struct HeapElement
+    {
         Key index;
         Weight weight;
     };
 
-    std::vector< HeapNode > insertedNodes;
-    std::vector< HeapElement > heap;
-    IndexStorage nodeIndex;
+    std::vector<HeapNode> inserted_nodes;
+    std::vector<HeapElement> heap;
+    IndexStorage node_index;
 
-    void Downheap( Key key ) {
+    void Downheap(Key key)
+    {
         const Key droppingIndex = heap[key].index;
         const Weight weight = heap[key].weight;
         Key nextKey = key << 1;
-        while ( nextKey < static_cast<Key>( heap.size() ) ) {
+        while (nextKey < static_cast<Key>(heap.size()))
+        {
             const Key nextKeyOther = nextKey + 1;
-            if ( ( nextKeyOther < static_cast<Key> ( heap.size() ) )&& ( heap[nextKey].weight > heap[nextKeyOther].weight) )
+            if ((nextKeyOther < static_cast<Key>(heap.size())) &&
+                (heap[nextKey].weight > heap[nextKeyOther].weight))
+            {
                 nextKey = nextKeyOther;
-
-            if ( weight <= heap[nextKey].weight )
+            }
+            if (weight <= heap[nextKey].weight)
+            {
                 break;
-
+            }
             heap[key] = heap[nextKey];
-            insertedNodes[heap[key].index].key = key;
+            inserted_nodes[heap[key].index].key = key;
             key = nextKey;
             nextKey <<= 1;
         }
         heap[key].index = droppingIndex;
         heap[key].weight = weight;
-        insertedNodes[droppingIndex].key = key;
+        inserted_nodes[droppingIndex].key = key;
     }
 
-    void Upheap( Key key ) {
+    void Upheap(Key key)
+    {
         const Key risingIndex = heap[key].index;
         const Weight weight = heap[key].weight;
         Key nextKey = key >> 1;
-        while ( heap[nextKey].weight > weight ) {
-            assert( nextKey != 0 );
+        while (heap[nextKey].weight > weight)
+        {
+            BOOST_ASSERT(nextKey != 0);
             heap[key] = heap[nextKey];
-            insertedNodes[heap[key].index].key = key;
+            inserted_nodes[heap[key].index].key = key;
             key = nextKey;
             nextKey >>= 1;
         }
         heap[key].index = risingIndex;
         heap[key].weight = weight;
-        insertedNodes[risingIndex].key = key;
+        inserted_nodes[risingIndex].key = key;
     }
 
-    void CheckHeap() {
+    void CheckHeap()
+    {
 #ifndef NDEBUG
-        for ( Key i = 2; i < (Key) heap.size(); ++i ) {
-            assert( heap[i].weight >= heap[i >> 1].weight );
+        for (Key i = 2; i < (Key)heap.size(); ++i)
+        {
+            BOOST_ASSERT(heap[i].weight >= heap[i >> 1].weight);
         }
 #endif
     }
 };
 
-#endif //#ifndef BINARYHEAP_H_INCLUDED
+#endif // BINARY_HEAP_H
diff --git a/DataStructures/ConcurrentQueue.h b/DataStructures/ConcurrentQueue.h
index 0466ab2..9d5b366 100644
--- a/DataStructures/ConcurrentQueue.h
+++ b/DataStructures/ConcurrentQueue.h
@@ -1,83 +1,85 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef CONCURRENTQUEUE_H_INCLUDED
-#define CONCURRENTQUEUE_H_INCLUDED
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <boost/bind.hpp>
-#include <boost/circular_buffer.hpp>
-#include <boost/thread/condition.hpp>
-#include <boost/thread/mutex.hpp>
-#include <boost/thread/thread.hpp>
-
-#include "../typedefs.h"
-
-template<typename Data>
-class ConcurrentQueue {
+*/
 
-    typedef typename boost::circular_buffer<Data>::size_type size_t;
+#ifndef CONCURRENT_QUEUE_H
+#define CONCURRENT_QUEUE_H
 
-public:
-    ConcurrentQueue(const size_t max_size) : internal_queue(max_size) { }
+#include "../typedefs.h"
 
-    inline void push(Data const& data) {
-        boost::mutex::scoped_lock lock(m_mutex);
-        m_not_full.wait(lock, boost::bind(&ConcurrentQueue<Data>::is_not_full, this));
-        internal_queue.push_back(data);
-        lock.unlock();
+#include <boost/circular_buffer.hpp>
+#include <condition_variable>
+#include <mutex>
+
+template <typename Data> class ConcurrentQueue
+{
+  public:
+    explicit ConcurrentQueue(const size_t max_size) : m_internal_queue(max_size) {}
+
+    inline void push(const Data &data)
+    {
+        std::unique_lock<std::mutex> lock(m_mutex);
+        m_not_full.wait(lock,
+                        [this]
+                        { return m_internal_queue.size() < m_internal_queue.capacity(); });
+        m_internal_queue.push_back(data);
         m_not_empty.notify_one();
     }
 
-    inline bool empty() const {
-        return internal_queue.empty();
-    }
+    inline bool empty() const { return m_internal_queue.empty(); }
 
-    inline void wait_and_pop(Data& popped_value) {
-        boost::mutex::scoped_lock lock(m_mutex);
-        m_not_empty.wait(lock, boost::bind(&ConcurrentQueue<Data>::is_not_empty, this));
-        popped_value=internal_queue.front();
-        internal_queue.pop_front();
-        lock.unlock();
+    inline void wait_and_pop(Data &popped_value)
+    {
+        std::unique_lock<std::mutex> lock(m_mutex);
+        m_not_empty.wait(lock,
+                         [this]
+                         { return !m_internal_queue.empty(); });
+        popped_value = m_internal_queue.front();
+        m_internal_queue.pop_front();
         m_not_full.notify_one();
     }
 
-    inline bool try_pop(Data& popped_value) {
-        boost::mutex::scoped_lock lock(m_mutex);
-        if(internal_queue.empty()) {
+    inline bool try_pop(Data &popped_value)
+    {
+        std::unique_lock<std::mutex> lock(m_mutex);
+        if (m_internal_queue.empty())
+        {
             return false;
         }
-        popped_value=internal_queue.front();
-        internal_queue.pop_front();
-        lock.unlock();
+        popped_value = m_internal_queue.front();
+        m_internal_queue.pop_front();
         m_not_full.notify_one();
         return true;
     }
 
-private:
-    boost::circular_buffer<Data> internal_queue;
-    boost::mutex m_mutex;
-    boost::condition m_not_empty;
-    boost::condition m_not_full;
-
-    inline bool is_not_empty() const { return internal_queue.size() > 0; }
-    inline bool is_not_full() const { return internal_queue.size() < internal_queue.capacity(); }
+  private:
+    boost::circular_buffer<Data> m_internal_queue;
+    std::mutex m_mutex;
+    std::condition_variable m_not_empty;
+    std::condition_variable m_not_full;
 };
 
-#endif //#ifndef CONCURRENTQUEUE_H_INCLUDED
+#endif // CONCURRENT_QUEUE_H
diff --git a/DataStructures/Coordinate.cpp b/DataStructures/Coordinate.cpp
new file mode 100644
index 0000000..9c453e7
--- /dev/null
+++ b/DataStructures/Coordinate.cpp
@@ -0,0 +1,446 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <osrm/Coordinate.h>
+#include "../Util/MercatorUtil.h"
+#include "../Util/SimpleLogger.h"
+#include "../Util/StringUtil.h"
+
+#include <boost/assert.hpp>
+
+#ifndef NDEBUG
+#include <bitset>
+#endif
+#include <iostream>
+#include <limits>
+
+FixedPointCoordinate::FixedPointCoordinate()
+    : lat(std::numeric_limits<int>::min()), lon(std::numeric_limits<int>::min())
+{
+}
+
+FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon)
+{
+#ifndef NDEBUG
+    if (0 != (std::abs(lat) >> 30))
+    {
+        std::bitset<32> y_coordinate_vector(lat);
+        SimpleLogger().Write(logDEBUG) << "broken lat: " << lat
+                                       << ", bits: " << y_coordinate_vector;
+    }
+    if (0 != (std::abs(lon) >> 30))
+    {
+        std::bitset<32> x_coordinate_vector(lon);
+        SimpleLogger().Write(logDEBUG) << "broken lon: " << lon
+                                       << ", bits: " << x_coordinate_vector;
+    }
+#endif
+}
+
+void FixedPointCoordinate::Reset()
+{
+    lat = std::numeric_limits<int>::min();
+    lon = std::numeric_limits<int>::min();
+}
+bool FixedPointCoordinate::isSet() const
+{
+    return (std::numeric_limits<int>::min() != lat) && (std::numeric_limits<int>::min() != lon);
+}
+bool FixedPointCoordinate::isValid() const
+{
+    if (lat > 90 * COORDINATE_PRECISION || lat < -90 * COORDINATE_PRECISION ||
+        lon > 180 * COORDINATE_PRECISION || lon < -180 * COORDINATE_PRECISION)
+    {
+        return false;
+    }
+    return true;
+}
+bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const
+{
+    return lat == other.lat && lon == other.lon;
+}
+
+double FixedPointCoordinate::ApproximateDistance(const int lat1,
+                                                 const int lon1,
+                                                 const int lat2,
+                                                 const int lon2)
+{
+    BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
+    BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
+    BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
+    BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
+    double RAD = 0.017453292519943295769236907684886;
+    double lt1 = lat1 / COORDINATE_PRECISION;
+    double ln1 = lon1 / COORDINATE_PRECISION;
+    double lt2 = lat2 / COORDINATE_PRECISION;
+    double ln2 = lon2 / COORDINATE_PRECISION;
+    double dlat1 = lt1 * (RAD);
+
+    double dlong1 = ln1 * (RAD);
+    double dlat2 = lt2 * (RAD);
+    double dlong2 = ln2 * (RAD);
+
+    double dLong = dlong1 - dlong2;
+    double dLat = dlat1 - dlat2;
+
+    double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2);
+    double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv));
+    // earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
+    // The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
+    const double earth = 6372797.560856;
+    return earth * cHarv;
+}
+
+double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &coordinate_1,
+                                                 const FixedPointCoordinate &coordinate_2)
+{
+    return ApproximateDistance(
+        coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
+}
+
+float FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &coordinate_1,
+                                                         const FixedPointCoordinate &coordinate_2)
+{
+    return ApproximateEuclideanDistance(
+        coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
+}
+
+float FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1,
+                                                         const int lon1,
+                                                         const int lat2,
+                                                         const int lon2)
+{
+    BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
+    BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
+    BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
+    BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
+
+    const float RAD = 0.017453292519943295769236907684886f;
+    const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
+    const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
+    const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
+    const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
+
+    const float x_value = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.f);
+    const float y_value = float_lat2 - float_lat1;
+    const float earth_radius = 6372797.560856f;
+    return sqrt(x_value * x_value + y_value * y_value) * earth_radius;
+}
+
+float
+FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate,
+                                                   const FixedPointCoordinate &target_coordinate,
+                                                   const FixedPointCoordinate &point)
+{
+    // initialize values
+    const float x_value = lat2y(point.lat / COORDINATE_PRECISION);
+    const float y_value = point.lon / COORDINATE_PRECISION;
+    const float a = lat2y(source_coordinate.lat / COORDINATE_PRECISION);
+    const float b = source_coordinate.lon / COORDINATE_PRECISION;
+    const float c = lat2y(target_coordinate.lat / COORDINATE_PRECISION);
+    const float d = target_coordinate.lon / COORDINATE_PRECISION;
+    float p, q;
+    if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
+    {
+        const float slope = (d - b) / (c - a); // slope
+        // Projection of (x,y) on line joining (a,b) and (c,d)
+        p = ((x_value + (slope * y_value)) + (slope * slope * a - slope * b)) /
+            (1.f + slope * slope);
+        q = b + slope * (p - a);
+    }
+    else
+    {
+        p = c;
+        q = y_value;
+    }
+
+    float nY = (d * p - c * q) / (a * d - b * c);
+    // discretize the result to coordinate precision. it's a hack!
+    if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
+    {
+        nY = 0.f;
+    }
+
+    // compute ratio
+    float ratio = (p - nY * a) / c;
+    if (std::isnan(ratio))
+    {
+        ratio = (target_coordinate == point ? 1.f : 0.f);
+    }
+    else if (std::abs(ratio) <= std::numeric_limits<float>::epsilon())
+    {
+        ratio = 0.f;
+    }
+    else if (std::abs(ratio - 1.f) <= std::numeric_limits<float>::epsilon())
+    {
+        ratio = 1.f;
+    }
+
+    //compute the nearest location
+    FixedPointCoordinate nearest_location;
+    BOOST_ASSERT(!std::isnan(ratio));
+    if (ratio <= 0.f)
+    { // point is "left" of edge
+        nearest_location = source_coordinate;
+    }
+    else if (ratio >= 1.f)
+    { // point is "right" of edge
+        nearest_location = target_coordinate;
+    }
+    else
+    { // point lies in between
+        nearest_location.lat = static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
+        nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
+    }
+    BOOST_ASSERT(nearest_location.isValid());
+    return FixedPointCoordinate::ApproximateEuclideanDistance(point, nearest_location);
+}
+
+float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
+                                                         const FixedPointCoordinate &segment_target,
+                                                         const FixedPointCoordinate &query_location,
+                                                         FixedPointCoordinate &nearest_location,
+                                                         float &ratio)
+{
+    BOOST_ASSERT(query_location.isValid());
+
+    // initialize values
+    const float x = lat2y(query_location.lat / COORDINATE_PRECISION);
+    const float y = query_location.lon / COORDINATE_PRECISION;
+    const float a = lat2y(segment_source.lat / COORDINATE_PRECISION);
+    const float b = segment_source.lon / COORDINATE_PRECISION;
+    const float c = lat2y(segment_target.lat / COORDINATE_PRECISION);
+    const float d = segment_target.lon / COORDINATE_PRECISION;
+    float p, q /*,mX*/, nY;
+    if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
+    {
+        const float m = (d - b) / (c - a); // slope
+        // Projection of (x,y) on line joining (a,b) and (c,d)
+        p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
+        q = b + m * (p - a);
+    }
+    else
+    {
+        p = c;
+        q = y;
+    }
+    nY = (d * p - c * q) / (a * d - b * c);
+
+    // discretize the result to coordinate precision. it's a hack!
+    if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
+    {
+        nY = 0.f;
+    }
+
+    // compute ratio
+    ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
+    // not calculate the explicit values of m an n as we
+    // are just interested in the ratio
+    if (std::isnan(ratio))
+    {
+        ratio = (segment_target == query_location ? 1.f : 0.f);
+    }
+    else if (std::abs(ratio) <= std::numeric_limits<float>::epsilon())
+    {
+        ratio = 0.;
+    }
+    else if (std::abs(ratio - 1.f) <= std::numeric_limits<float>::epsilon())
+    {
+        ratio = 1.f;
+    }
+
+    // compute nearest location
+    BOOST_ASSERT(!std::isnan(ratio));
+    if (ratio <= 0.f)
+    {
+        nearest_location = segment_source;
+    }
+    else if (ratio >= 1.)
+    {
+        nearest_location = segment_target;
+    }
+    else
+    {
+        // point lies in between
+        nearest_location.lat = static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
+        nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
+    }
+    BOOST_ASSERT(nearest_location.isValid());
+
+    const float approximate_distance =
+        FixedPointCoordinate::ApproximateEuclideanDistance(query_location, nearest_location);
+    BOOST_ASSERT(0. <= approximate_distance);
+    return approximate_distance;
+}
+
+void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output)
+{
+    char buffer[12];
+    buffer[11] = 0; // zero termination
+    output = printInt<11, 6>(buffer, value);
+}
+
+void FixedPointCoordinate::convertInternalCoordinateToString(const FixedPointCoordinate &coord,
+                                                             std::string &output)
+{
+    std::string tmp;
+    tmp.reserve(23);
+    convertInternalLatLonToString(coord.lon, tmp);
+    output = tmp;
+    output += ",";
+    convertInternalLatLonToString(coord.lat, tmp);
+    output += tmp;
+}
+
+void
+FixedPointCoordinate::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
+                                                                std::string &output)
+{
+    std::string tmp;
+    tmp.reserve(23);
+    convertInternalLatLonToString(coord.lat, tmp);
+    output = tmp;
+    output += ",";
+    convertInternalLatLonToString(coord.lon, tmp);
+    output += tmp;
+}
+
+void FixedPointCoordinate::Output(std::ostream &out) const
+{
+    out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
+}
+
+float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &first_coordinate,
+                                       const FixedPointCoordinate &second_coordinate)
+{
+    const float lon_diff = second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION;
+    const float lon_delta = DegreeToRadian(lon_diff);
+    const float lat1 = DegreeToRadian(first_coordinate.lat / COORDINATE_PRECISION);
+    const float lat2 = DegreeToRadian(second_coordinate.lat / COORDINATE_PRECISION);
+    const float y = sin(lon_delta) * cos(lat2);
+    const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon_delta);
+    float result = RadianToDegree(std::atan2(y, x));
+    while (result < 0.f)
+    {
+        result += 360.f;
+    }
+
+    while (result >= 360.f)
+    {
+        result -= 360.f;
+    }
+    return result;
+}
+
+float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const
+{
+    const float lon_delta =
+        DegreeToRadian(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION);
+    const float lat1 = DegreeToRadian(other.lat / COORDINATE_PRECISION);
+    const float lat2 = DegreeToRadian(lat / COORDINATE_PRECISION);
+    const float y_value = std::sin(lon_delta) * std::cos(lat2);
+    const float x_value =
+        std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta);
+    float result = RadianToDegree(std::atan2(y_value, x_value));
+
+    while (result < 0.f)
+    {
+        result += 360.f;
+    }
+
+    while (result >= 360.f)
+    {
+        result -= 360.f;
+    }
+    return result;
+}
+
+float FixedPointCoordinate::DegreeToRadian(const float degree) { return degree * (static_cast<float>(M_PI) / 180.f); }
+
+float FixedPointCoordinate::RadianToDegree(const float radian) { return radian * (180.f * static_cast<float>(M_1_PI)); }
+
+// This distance computation does integer arithmetic only and is a lot faster than
+// the other distance function which are numerically correct('ish).
+// It preserves some order among the elements that make it useful for certain purposes
+int FixedPointCoordinate::OrderedPerpendicularDistanceApproximation(
+    const FixedPointCoordinate &input_point,
+    const FixedPointCoordinate &segment_source,
+    const FixedPointCoordinate &segment_target)
+{
+    // initialize values
+    const float x = lat2y(input_point.lat / COORDINATE_PRECISION);
+    const float y = input_point.lon / COORDINATE_PRECISION;
+    const float a = lat2y(segment_source.lat / COORDINATE_PRECISION);
+    const float b = segment_source.lon / COORDINATE_PRECISION;
+    const float c = lat2y(segment_target.lat / COORDINATE_PRECISION);
+    const float d = segment_target.lon / COORDINATE_PRECISION;
+
+    float p, q;
+    if (a == c)
+    {
+        p = c;
+        q = y;
+    }
+    else
+    {
+        const float m = (d - b) / (c - a); // slope
+        // Projection of (x,y) on line joining (a,b) and (c,d)
+        p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
+        q = b + m * (p - a);
+    }
+
+    const float nY = (d * p - c * q) / (a * d - b * c);
+    float ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
+    // not calculate the explicit values of m an n as we
+    // are just interested in the ratio
+    if (std::isnan(ratio))
+    {
+        ratio = (segment_target == input_point) ? 1.f : 0.f;
+    }
+
+    // compute target quasi-location
+    int dx, dy;
+    if (ratio < 0.f)
+    {
+        dx = input_point.lon - segment_source.lon;
+        dy = input_point.lat - segment_source.lat;
+    }
+    else if (ratio > 1.f)
+    {
+        dx = input_point.lon - segment_target.lon;
+        dy = input_point.lat - segment_target.lat;
+    }
+    else
+    {
+        // point lies in between
+        dx = input_point.lon - static_cast<int>(q * COORDINATE_PRECISION);
+        dy = input_point.lat - static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
+    }
+
+    // return an approximation in the plane
+    return static_cast<int>(sqrt(dx * dx + dy * dy));
+}
diff --git a/DataStructures/Coordinate.h b/DataStructures/Coordinate.h
deleted file mode 100644
index bc63289..0000000
--- a/DataStructures/Coordinate.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef COORDINATE_H_
-#define COORDINATE_H_
-
-#include <cassert>
-#include <cmath>
-#include <climits>
-
-#include <iostream>
-
-struct _Coordinate {
-    int lat;
-    int lon;
-    _Coordinate () : lat(INT_MIN), lon(INT_MIN) {}
-    _Coordinate (int t, int n) : lat(t) , lon(n) {}
-    void Reset() {
-        lat = INT_MIN;
-        lon = INT_MIN;
-    }
-    bool isSet() const {
-        return (INT_MIN != lat) && (INT_MIN != lon);
-    }
-    inline bool isValid() const {
-        if(lat > 90*100000 || lat < -90*100000 || lon > 180*100000 || lon <-180*100000) {
-            return false;
-        }
-        return true;
-    }
-    bool operator==(const _Coordinate & other) const {
-        return lat == other.lat && lon == other.lon;
-    }
-};
-
-inline std::ostream & operator<<(std::ostream & out, const _Coordinate & c){
-    out << "(" << c.lat << "," << c.lon << ")";
-    return out;
-}
-
-inline double ApproximateDistance( const int lat1, const int lon1, const int lat2, const int lon2 ) {
-    assert(lat1 != INT_MIN);
-    assert(lon1 != INT_MIN);
-    assert(lat2 != INT_MIN);
-    assert(lon2 != INT_MIN);
-    double RAD = 0.017453292519943295769236907684886;
-    double lt1 = lat1/100000.;
-    double ln1 = lon1/100000.;
-    double lt2 = lat2/100000.;
-    double ln2 = lon2/100000.;
-    double dlat1=lt1*(RAD);
-
-    double dlong1=ln1*(RAD);
-    double dlat2=lt2*(RAD);
-    double dlong2=ln2*(RAD);
-
-    double dLong=dlong1-dlong2;
-    double dLat=dlat1-dlat2;
-
-    double aHarv= pow(sin(dLat/2.0),2.0)+cos(dlat1)*cos(dlat2)*pow(sin(dLong/2.),2);
-    double cHarv=2.*atan2(sqrt(aHarv),sqrt(1.0-aHarv));
-    //earth's radius from wikipedia varies between 6,356.750 km — 6,378.135 km (˜3,949.901 — 3,963.189 miles)
-    //The IUGG value for the equatorial radius of the Earth is 6378.137 km (3963.19 mile)
-    const double earth=6372797.560856;//I am doing miles, just change this to radius in kilometers to get distances in km
-    double distance=earth*cHarv;
-    return distance;
-}
-
-inline double ApproximateDistance(const _Coordinate &c1, const _Coordinate &c2) {
-    return ApproximateDistance( c1.lat, c1.lon, c2.lat, c2.lon );
-}
-
-inline double ApproximateDistanceByEuclid(const _Coordinate &c1, const _Coordinate &c2) {
-    assert(c1.lat != INT_MIN);
-    assert(c1.lon != INT_MIN);
-    assert(c2.lat != INT_MIN);
-    assert(c2.lon != INT_MIN);
-    const double RAD = 0.017453292519943295769236907684886;
-    const double lat1 = (c1.lat/100000.)*RAD;
-    const double lon1 = (c1.lon/100000.)*RAD;
-    const double lat2 = (c2.lat/100000.)*RAD;
-    const double lon2 = (c2.lon/100000.)*RAD;
-
-    const double x = (lon2-lon1) * cos((lat1+lat2)/2.);
-    const double y = (lat2-lat1);
-    const double earthRadius = 6372797.560856;
-    const double d = sqrt(x*x + y*y) * earthRadius;
-    return d;
-}
-
-#endif /* COORDINATE_H_ */
diff --git a/DataStructures/DeallocatingVector.h b/DataStructures/DeallocatingVector.h
index 89d8e2c..013cc1d 100644
--- a/DataStructures/DeallocatingVector.h
+++ b/DataStructures/DeallocatingVector.h
@@ -1,317 +1,400 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef DEALLOCATINGVECTOR_H_
 #define DEALLOCATINGVECTOR_H_
 
-#include <cassert>
+#include <boost/assert.hpp>
+#include <cstring>
 #include <vector>
 
-#if __cplusplus > 199711L
-#define DEALLOCATION_VECTOR_NULL_PTR nullptr
-#else
-#define DEALLOCATION_VECTOR_NULL_PTR NULL
-#endif
-
+template <typename ElementT,
+          std::size_t bucketSizeC = 8388608 / sizeof(ElementT),
+          bool DeallocateC = false>
+class DeallocatingVectorIterator : public std::iterator<std::random_access_iterator_tag, ElementT>
+{
+  protected:
+    class DeallocatingVectorIteratorState
+    {
+      private:
+        // make constructors explicit, so we do not mix random access and deallocation iterators.
+        DeallocatingVectorIteratorState();
 
-template<typename ElementT, std::size_t bucketSizeC = 8388608/sizeof(ElementT), bool DeallocateC = false>
-class DeallocatingVectorIterator : public std::iterator<std::random_access_iterator_tag, ElementT> {
-protected:
+      public:
+        explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r)
+            : index(r.index), bucket_list(r.bucket_list)
+        {
+        }
+        explicit DeallocatingVectorIteratorState(const std::size_t idx,
+                                                 std::vector<ElementT *> &input_list)
+            : index(idx), bucket_list(input_list)
+        {
+        }
+        std::size_t index;
+        std::vector<ElementT *> &bucket_list;
 
-    class DeallocatingVectorIteratorState {
-    private:
-        //make constructors explicit, so we do not mix random access and deallocation iterators.
-        DeallocatingVectorIteratorState();
-    public:
-        explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r) : mData(r.mData), mIndex(r.mIndex), mBucketList(r.mBucketList) {}
-        //explicit DeallocatingVectorIteratorState(const ElementT * ptr, const std::size_t idx, const std::vector<ElementT *> & input_list) : mData(ptr), mIndex(idx), mBucketList(input_list) {}
-        explicit DeallocatingVectorIteratorState(const std::size_t idx, std::vector<ElementT *> & input_list) : mData(DEALLOCATION_VECTOR_NULL_PTR), mIndex(idx), mBucketList(input_list) {
-            setPointerForIndex();
+        inline bool operator!=(const DeallocatingVectorIteratorState &other)
+        {
+            return index != other.index;
         }
-        ElementT * mData;
-        std::size_t mIndex;
-        std::vector<ElementT *> & mBucketList;
-
-        inline void setPointerForIndex() {
-            if(bucketSizeC*mBucketList.size() <= mIndex) {
-                mData = DEALLOCATION_VECTOR_NULL_PTR;
-                return;
-            }
-            std::size_t _bucket = mIndex/bucketSizeC;
-            std::size_t _index = mIndex%bucketSizeC;
-            mData = &(mBucketList[_bucket][_index]);
-
-            if(DeallocateC) {
-                //if we hopped over the border of the previous bucket, then delete that bucket.
-                if(0 == _index && _bucket) {
-                    delete[] mBucketList[_bucket-1];
-                    mBucketList[_bucket-1] = DEALLOCATION_VECTOR_NULL_PTR;
-                }
-            }
 
+        inline bool operator==(const DeallocatingVectorIteratorState &other)
+        {
+            return index == other.index;
         }
-        inline bool operator!=(const DeallocatingVectorIteratorState &other) {
-            return (mData != other.mData) || (mIndex != other.mIndex) || (mBucketList != other.mBucketList);
+
+        bool operator<(const DeallocatingVectorIteratorState &other) const
+        {
+            return index < other.index;
         }
 
-        inline bool operator==(const DeallocatingVectorIteratorState &other) {
-            return (mData == other.mData) && (mIndex == other.mIndex) && (mBucketList == other.mBucketList);
+        bool operator>(const DeallocatingVectorIteratorState &other) const
+        {
+            return index > other.index;
         }
 
-        inline bool operator<(const DeallocatingVectorIteratorState &other) {
-            return mIndex < other.mIndex;
+        bool operator>=(const DeallocatingVectorIteratorState &other) const
+        {
+            return index >= other.index;
         }
 
-        //This is a hack to make assignment operator possible with reference member
-        inline DeallocatingVectorIteratorState& operator= (const DeallocatingVectorIteratorState &a) {
-            if (this != &a) {
-                this->DeallocatingVectorIteratorState::~DeallocatingVectorIteratorState(); // explicit non-virtual destructor
+        // This is a hack to make assignment operator possible with reference member
+        inline DeallocatingVectorIteratorState &operator=(const DeallocatingVectorIteratorState &a)
+        {
+            if (this != &a)
+            {
+                this->DeallocatingVectorIteratorState::
+                    ~DeallocatingVectorIteratorState();        // explicit non-virtual destructor
                 new (this) DeallocatingVectorIteratorState(a); // placement new
             }
             return *this;
         }
     };
 
-    DeallocatingVectorIteratorState mState;
+    DeallocatingVectorIteratorState current_state;
 
-public:
+  public:
     typedef std::random_access_iterator_tag iterator_category;
-    typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::value_type value_type;
-    typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::difference_type difference_type;
+    typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::value_type
+    value_type;
+    typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::difference_type
+    difference_type;
     typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::reference reference;
     typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::pointer pointer;
 
     DeallocatingVectorIterator() {}
 
-    template<typename T2>
-    DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
+    template <typename T2>
+    explicit DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> &r)
+        : current_state(r.current_state)
+    {
+    }
 
-    DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
-    //DeallocatingVectorIterator(std::size_t idx, const std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
-    DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
+    DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> &input_list)
+        : current_state(idx, input_list)
+    {
+    }
+    explicit DeallocatingVectorIterator(const DeallocatingVectorIteratorState &r) : current_state(r) {}
 
-    template<typename T2>
-    DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
-        if(DeallocateC) assert(false);
-        mState = r.mState; return *this;
+    template <typename T2>
+    DeallocatingVectorIterator &operator=(const DeallocatingVectorIterator<T2> &r)
+    {
+        if (DeallocateC)
+        {
+            BOOST_ASSERT(false);
+        }
+        current_state = r.current_state;
+        return *this;
+    }
+
+    inline DeallocatingVectorIterator &operator++()
+    { // prefix
+        ++current_state.index;
+        return *this;
+    }
+
+    inline DeallocatingVectorIterator &operator--()
+    { // prefix
+        if (DeallocateC)
+        {
+            BOOST_ASSERT(false);
+        }
+        --current_state.index;
+        return *this;
     }
 
-    inline DeallocatingVectorIterator& operator++() { //prefix
-//        if(DeallocateC) assert(false);
-        ++mState.mIndex; mState.setPointerForIndex(); return *this;
+    inline DeallocatingVectorIterator operator++(int)
+    { // postfix
+        DeallocatingVectorIteratorState my_state(current_state);
+        current_state.index++;
+        return DeallocatingVectorIterator(my_state);
+    }
+    inline DeallocatingVectorIterator operator--(int)
+    { // postfix
+        if (DeallocateC)
+        {
+            BOOST_ASSERT(false);
+        }
+        DeallocatingVectorIteratorState my_state(current_state);
+        current_state.index--;
+        return DeallocatingVectorIterator(my_state);
     }
 
-    inline DeallocatingVectorIterator& operator--() { //prefix
-        if(DeallocateC) assert(false);
-        --mState.mIndex; mState.setPointerForIndex(); return *this;
+    inline DeallocatingVectorIterator operator+(const difference_type &n) const
+    {
+        DeallocatingVectorIteratorState my_state(current_state);
+        my_state.index += n;
+        return DeallocatingVectorIterator(my_state);
     }
 
-    inline DeallocatingVectorIterator operator++(int) { //postfix
-        DeallocatingVectorIteratorState _myState(mState);
-        mState.mIndex++; mState.setPointerForIndex();
-        return DeallocatingVectorIterator(_myState);
+    inline DeallocatingVectorIterator &operator+=(const difference_type &n)
+    {
+        current_state.index += n;
+        return *this;
     }
-    inline DeallocatingVectorIterator operator --(int) { //postfix
-        if(DeallocateC) assert(false);
-        DeallocatingVectorIteratorState _myState(mState);
-        mState.mIndex--; mState.setPointerForIndex();
-        return DeallocatingVectorIterator(_myState);
+
+    inline DeallocatingVectorIterator operator-(const difference_type &n) const
+    {
+        if (DeallocateC)
+        {
+            BOOST_ASSERT(false);
+        }
+        DeallocatingVectorIteratorState my_state(current_state);
+        my_state.index -= n;
+        return DeallocatingVectorIterator(my_state);
     }
 
-    inline DeallocatingVectorIterator operator+(const difference_type& n) const {
-        DeallocatingVectorIteratorState _myState(mState);
-        _myState.mIndex+=n; _myState.setPointerForIndex();
-        return DeallocatingVectorIterator(_myState);
+    inline DeallocatingVectorIterator &operator-=(const difference_type &n) const
+    {
+        if (DeallocateC)
+        {
+            BOOST_ASSERT(false);
+        }
+        current_state.index -= n;
+        return *this;
     }
 
-    inline DeallocatingVectorIterator& operator+=(const difference_type& n) const {
-        mState.mIndex+=n; return *this;
+    inline reference operator*() const
+    {
+        std::size_t current_bucket = current_state.index / bucketSizeC;
+        std::size_t current_index = current_state.index % bucketSizeC;
+        return (current_state.bucket_list[current_bucket][current_index]);
     }
 
-    inline DeallocatingVectorIterator operator-(const difference_type& n) const {
-        if(DeallocateC) assert(false);
-        DeallocatingVectorIteratorState _myState(mState);
-        _myState.mIndex-=n; _myState.setPointerForIndex();
-        return DeallocatingVectorIterator(_myState);
+    inline pointer operator->() const
+    {
+        std::size_t current_bucket = current_state.index / bucketSizeC;
+        std::size_t current_index = current_state.index % bucketSizeC;
+        return &(current_state.bucket_list[current_bucket][current_index]);
     }
 
-    inline DeallocatingVectorIterator& operator-=(const difference_type &n) const {
-        if(DeallocateC) assert(false);
-        mState.mIndex-=n; return *this;
+    inline bool operator!=(const DeallocatingVectorIterator &other)
+    {
+        return current_state != other.current_state;
     }
-    inline reference operator*() const { return *mState.mData; }
-    inline pointer operator->() const { return mState.mData; }
-    inline reference operator[](const difference_type &n) const {
-        if(DeallocateC) assert(false);
-        DeallocatingVectorIteratorState _myState(mState);
-        _myState.mIndex += n;
-        _myState.setPointerForIndex;
-        return _myState.mData;
+
+    inline bool operator==(const DeallocatingVectorIterator &other)
+    {
+        return current_state == other.current_state;
     }
 
-    inline bool operator!=(const DeallocatingVectorIterator & other) {
-        return mState != other.mState;
+    inline bool operator<(const DeallocatingVectorIterator &other) const
+    {
+        return current_state < other.current_state;
     }
 
-    inline bool operator==(const DeallocatingVectorIterator & other) {
-        return mState == other.mState;
+    inline bool operator>(const DeallocatingVectorIterator &other) const
+    {
+        return current_state > other.current_state;
     }
 
-    bool operator<(const DeallocatingVectorIterator & other) {
-        return mState < other.mState;
+    inline bool operator>=(const DeallocatingVectorIterator &other) const
+    {
+        return current_state >= other.current_state;
     }
 
-    difference_type operator-(const DeallocatingVectorIterator & other) {
-        if(DeallocateC) assert(false);
-        return mState.mIndex-other.mState.mIndex;
+    difference_type operator-(const DeallocatingVectorIterator &other)
+    {
+        if (DeallocateC)
+        {
+            BOOST_ASSERT(false);
+        }
+        return current_state.index - other.current_state.index;
     }
 };
 
-template<typename ElementT, std::size_t bucketSizeC = 8388608/sizeof(ElementT) >
-class DeallocatingVector {
-private:
-    std::size_t mCurrentSize;
-    std::vector<ElementT *> mBucketList;
+template <typename ElementT, std::size_t bucketSizeC = 8388608 / sizeof(ElementT)>
+class DeallocatingVector
+{
+  private:
+    std::size_t current_size;
+    std::vector<ElementT *> bucket_list;
 
-public:
+  public:
     typedef ElementT value_type;
     typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> iterator;
     typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> const_iterator;
 
-    //this iterator deallocates all buckets that have been visited. Iterators to visited objects become invalid.
+    // this iterator deallocates all buckets that have been visited. Iterators to visited objects
+    // become invalid.
     typedef DeallocatingVectorIterator<ElementT, bucketSizeC, true> deallocation_iterator;
 
-    DeallocatingVector() : mCurrentSize(0) {
-        //initial bucket
-        mBucketList.push_back(new ElementT[bucketSizeC]);
+    DeallocatingVector() : current_size(0)
+    {
+        // initial bucket
+        bucket_list.emplace_back(new ElementT[bucketSizeC]);
     }
 
-    ~DeallocatingVector() {
-        clear();
-    }
+    ~DeallocatingVector() { clear(); }
 
-    inline void swap(DeallocatingVector<ElementT, bucketSizeC> & other) {
-        std::swap(mCurrentSize, other.mCurrentSize);
-        mBucketList.swap(other.mBucketList);
+    inline void swap(DeallocatingVector<ElementT, bucketSizeC> &other)
+    {
+        std::swap(current_size, other.current_size);
+        bucket_list.swap(other.bucket_list);
     }
 
-    inline void clear() {
-        //Delete[]'ing ptr's to all Buckets
-        for(unsigned i = 0; i < mBucketList.size(); ++i) {
-            if(DEALLOCATION_VECTOR_NULL_PTR != mBucketList[i]) {
-                delete[] mBucketList[i];
-                mBucketList[i] = DEALLOCATION_VECTOR_NULL_PTR;
+    inline void clear()
+    {
+        // Delete[]'ing ptr's to all Buckets
+        for (unsigned i = 0; i < bucket_list.size(); ++i)
+        {
+            if (nullptr != bucket_list[i])
+            {
+                delete[] bucket_list[i];
+                bucket_list[i] = nullptr;
             }
         }
-        //Removing all ptrs from vector
-        std::vector<ElementT *>().swap(mBucketList);
-        mCurrentSize = 0;
+        // Removing all ptrs from vector
+        std::vector<ElementT *>().swap(bucket_list);
+        current_size = 0;
+    }
+
+    inline void push_back(const ElementT &element)
+    {
+        const std::size_t current_capacity = capacity();
+        if (current_size == current_capacity)
+        {
+            bucket_list.push_back(new ElementT[bucketSizeC]);
+        }
+
+        std::size_t current_index = size() % bucketSizeC;
+        bucket_list.back()[current_index] = element;
+        ++current_size;
     }
 
-    inline void push_back(const ElementT & element) {
-        std::size_t _capacity = capacity();
-        if(mCurrentSize == _capacity) {
-            mBucketList.push_back(new ElementT[bucketSizeC]);
+    inline void emplace_back(const ElementT &&element)
+    {
+        const std::size_t current_capacity = capacity();
+        if (current_size == current_capacity)
+        {
+            bucket_list.push_back(new ElementT[bucketSizeC]);
         }
 
-        std::size_t _index = size()%bucketSizeC;
-        mBucketList.back()[_index] = element;
-        ++mCurrentSize;
+        const std::size_t current_index = size() % bucketSizeC;
+        bucket_list.back()[current_index] = element;
+        ++current_size;
     }
 
-    inline void reserve(const std::size_t) const {
-        //don't do anything
+    inline void reserve(const std::size_t) const
+    {
+        // don't do anything
     }
 
-    inline void resize(const std::size_t new_size) {
-        if(new_size > mCurrentSize) {
-            while(capacity() < new_size) {
-                mBucketList.push_back(new ElementT[bucketSizeC]);
+    inline void resize(const std::size_t new_size)
+    {
+        if (new_size > current_size)
+        {
+            while (capacity() < new_size)
+            {
+                bucket_list.push_back(new ElementT[bucketSizeC]);
             }
-            mCurrentSize = new_size;
+            current_size = new_size;
         }
-        if(new_size < mCurrentSize) {
-            std::size_t number_of_necessary_buckets = 1+(new_size / bucketSizeC);
+        if (new_size < current_size)
+        {
+            const std::size_t number_of_necessary_buckets = 1 + (new_size / bucketSizeC);
 
-            for(unsigned i = number_of_necessary_buckets; i < mBucketList.size(); ++i) {
-                delete[] mBucketList[i];
+            for (std::size_t i = number_of_necessary_buckets; i < bucket_list.size(); ++i)
+            {
+                delete[] bucket_list[i];
             }
-            mBucketList.resize(number_of_necessary_buckets);
-            mCurrentSize = new_size;
+            bucket_list.resize(number_of_necessary_buckets);
+            current_size = new_size;
         }
     }
 
-    inline std::size_t size() const {
-        return mCurrentSize;
-    }
+    inline std::size_t size() const { return current_size; }
 
-    inline std::size_t capacity() const {
-        return mBucketList.size() * bucketSizeC;
-    }
+    inline std::size_t capacity() const { return bucket_list.size() * bucketSizeC; }
 
-    inline iterator begin() {
-        return iterator(static_cast<std::size_t>(0), mBucketList);
-    }
+    inline iterator begin() { return iterator(static_cast<std::size_t>(0), bucket_list); }
 
-    inline iterator end() {
-        return iterator(size(), mBucketList);
-    }
+    inline iterator end() { return iterator(size(), bucket_list); }
 
-    inline deallocation_iterator dbegin() {
-        return deallocation_iterator(static_cast<std::size_t>(0), mBucketList);
+    inline deallocation_iterator dbegin()
+    {
+        return deallocation_iterator(static_cast<std::size_t>(0), bucket_list);
     }
 
-    inline deallocation_iterator dend() {
-        return deallocation_iterator(size(), mBucketList);
-    }
+    inline deallocation_iterator dend() { return deallocation_iterator(size(), bucket_list); }
 
-    inline const_iterator begin() const {
-        return const_iterator(static_cast<std::size_t>(0), mBucketList);
+    inline const_iterator begin() const
+    {
+        return const_iterator(static_cast<std::size_t>(0), bucket_list);
     }
 
-    inline const_iterator end() const {
-        return const_iterator(size(), mBucketList);
-    }
+    inline const_iterator end() const { return const_iterator(size(), bucket_list); }
 
-    inline ElementT & operator[](const std::size_t index) {
+    inline ElementT &operator[](const std::size_t index)
+    {
         std::size_t _bucket = index / bucketSizeC;
         std::size_t _index = index % bucketSizeC;
-        return (mBucketList[_bucket][_index]);
+        return (bucket_list[_bucket][_index]);
     }
 
-    const inline ElementT & operator[](const std::size_t index) const {
+    const inline ElementT &operator[](const std::size_t index) const
+    {
         std::size_t _bucket = index / bucketSizeC;
         std::size_t _index = index % bucketSizeC;
-        return (mBucketList[_bucket][_index]);
+        return (bucket_list[_bucket][_index]);
     }
 
-    inline ElementT & back() {
-        std::size_t _bucket = mCurrentSize / bucketSizeC;
-    	std::size_t _index = mCurrentSize % bucketSizeC;
-    	return (mBucketList[_bucket][_index]);
+    inline ElementT &back()
+    {
+        std::size_t _bucket = current_size / bucketSizeC;
+        std::size_t _index = current_size % bucketSizeC;
+        return (bucket_list[_bucket][_index]);
     }
 
-    const inline ElementT & back() const {
-        std::size_t _bucket = mCurrentSize / bucketSizeC;
-        std::size_t _index = mCurrentSize % bucketSizeC;
-    	return (mBucketList[_bucket][_index]);
+    const inline ElementT &back() const
+    {
+        std::size_t _bucket = current_size / bucketSizeC;
+        std::size_t _index = current_size % bucketSizeC;
+        return (bucket_list[_bucket][_index]);
     }
 };
 
diff --git a/DataStructures/DynamicGraph.h b/DataStructures/DynamicGraph.h
index 67db065..3dc48b6 100644
--- a/DataStructures/DynamicGraph.h
+++ b/DataStructures/DynamicGraph.h
@@ -1,233 +1,280 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef DYNAMICGRAPH_H_INCLUDED
-#define DYNAMICGRAPH_H_INCLUDED
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef DYNAMICGRAPH_H
+#define DYNAMICGRAPH_H
 
 #include "../DataStructures/DeallocatingVector.h"
 
 #include <boost/assert.hpp>
-#include <boost/integer.hpp>
+#include <boost/range/irange.hpp>
+
+#include <cstdint>
 
 #include <algorithm>
 #include <limits>
 #include <vector>
-
-template< typename EdgeDataT>
-class DynamicGraph {
-    public:
-        typedef EdgeDataT EdgeData;
-        typedef uint32_t NodeIterator;
-        typedef uint32_t EdgeIterator;
-
-        class InputEdge {
-            public:
-                NodeIterator source;
-                NodeIterator target;
-                EdgeDataT data;
-                bool operator<( const InputEdge& right ) const {
-                    if ( source != right.source )
-                        return source < right.source;
-                    return target < right.target;
-                }
-        };
-
-        //Constructs an empty graph with a given number of nodes.
-        DynamicGraph( int32_t nodes ) : m_numNodes(nodes), m_numEdges(0) {
-            m_nodes.reserve( m_numNodes );
-            m_nodes.resize( m_numNodes );
-
-            m_edges.reserve( m_numNodes * 1.1 );
-            m_edges.resize( m_numNodes );
+#include <atomic>
+
+template <typename EdgeDataT> class DynamicGraph
+{
+  public:
+    typedef decltype(boost::irange(0u,0u)) EdgeRange;
+    typedef EdgeDataT EdgeData;
+    typedef unsigned NodeIterator;
+    typedef unsigned EdgeIterator;
+
+    class InputEdge
+    {
+      public:
+        NodeIterator source;
+        NodeIterator target;
+        EdgeDataT data;
+        bool operator<(const InputEdge &right) const
+        {
+            if (source != right.source)
+                return source < right.source;
+            return target < right.target;
         }
-
-        template<class ContainerT>
-        DynamicGraph( const int32_t nodes, const ContainerT &graph ) {
-            m_numNodes = nodes;
-            m_numEdges = ( EdgeIterator ) graph.size();
-            m_nodes.reserve( m_numNodes +1);
-            m_nodes.resize( m_numNodes +1);
-            EdgeIterator edge = 0;
-            EdgeIterator position = 0;
-            for ( NodeIterator node = 0; node < m_numNodes; ++node ) {
-                EdgeIterator lastEdge = edge;
-                while ( edge < m_numEdges && graph[edge].source == node ) {
-                    ++edge;
-                }
-                m_nodes[node].firstEdge = position;
-                m_nodes[node].edges = edge - lastEdge;
-                position += m_nodes[node].edges;
-            }
-            m_nodes.back().firstEdge = position;
-            m_edges.reserve( position * 1.1 );
-            m_edges.resize( position );
-            edge = 0;
-            for ( NodeIterator node = 0; node < m_numNodes; ++node ) {
-                for ( EdgeIterator i = m_nodes[node].firstEdge, e = m_nodes[node].firstEdge + m_nodes[node].edges; i != e; ++i ) {
-                    m_edges[i].target = graph[edge].target;
-                    m_edges[i].data = graph[edge].data;
-                    BOOST_ASSERT_MSG(
-                        graph[edge].data.distance > 0,
-                        "edge distance invalid"
-                    );
-                    ++edge;
-                }
+    };
+
+    // Constructs an empty graph with a given number of nodes.
+    explicit DynamicGraph(int32_t nodes) : m_numNodes(nodes), m_numEdges(0)
+    {
+        m_nodes.reserve(m_numNodes);
+        m_nodes.resize(m_numNodes);
+
+        m_edges.reserve(m_numNodes * 1.1);
+        m_edges.resize(m_numNodes);
+    }
+
+    template <class ContainerT> DynamicGraph(const int32_t nodes, const ContainerT &graph)
+    {
+        m_numNodes = nodes;
+        m_numEdges = (EdgeIterator)graph.size();
+        m_nodes.reserve(m_numNodes + 1);
+        m_nodes.resize(m_numNodes + 1);
+        EdgeIterator edge = 0;
+        EdgeIterator position = 0;
+        for (NodeIterator node = 0; node < m_numNodes; ++node)
+        {
+            EdgeIterator lastEdge = edge;
+            while (edge < m_numEdges && graph[edge].source == node)
+            {
+                ++edge;
             }
+            m_nodes[node].firstEdge = position;
+            m_nodes[node].edges = edge - lastEdge;
+            position += m_nodes[node].edges;
         }
-
-        ~DynamicGraph(){ }
-
-        uint32_t GetNumberOfNodes() const {
-            return m_numNodes;
-        }
-
-        uint32_t GetNumberOfEdges() const {
-            return m_numEdges;
-        }
-
-        uint32_t GetOutDegree( const NodeIterator n ) const {
-            return m_nodes[n].edges;
-        }
-
-        NodeIterator GetTarget( const EdgeIterator e ) const {
-            return NodeIterator( m_edges[e].target );
+        m_nodes.back().firstEdge = position;
+        m_edges.reserve(static_cast<std::size_t>(position * 1.1));
+        m_edges.resize(position);
+        edge = 0;
+        for (NodeIterator node = 0; node < m_numNodes; ++node)
+        {
+            for (EdgeIterator i = m_nodes[node].firstEdge,
+                              e = m_nodes[node].firstEdge + m_nodes[node].edges;
+                 i != e;
+                 ++i)
+            {
+                m_edges[i].target = graph[edge].target;
+                m_edges[i].data = graph[edge].data;
+                BOOST_ASSERT_MSG(graph[edge].data.distance > 0, "edge distance invalid");
+                ++edge;
+            }
         }
+    }
 
-        EdgeDataT &GetEdgeData( const EdgeIterator e ) {
-            return m_edges[e].data;
-        }
+    ~DynamicGraph() {}
 
-        const EdgeDataT &GetEdgeData( const EdgeIterator e ) const {
-            return m_edges[e].data;
-        }
+    unsigned GetNumberOfNodes() const { return m_numNodes; }
 
-        EdgeIterator BeginEdges( const NodeIterator n ) const {
-            return EdgeIterator( m_nodes[n].firstEdge );
-        }
+    unsigned GetNumberOfEdges() const { return m_numEdges; }
 
-        EdgeIterator EndEdges( const NodeIterator n ) const {
-            return EdgeIterator( m_nodes[n].firstEdge + m_nodes[n].edges );
-        }
+    unsigned GetOutDegree(const NodeIterator n) const { return m_nodes[n].edges; }
 
-        //adds an edge. Invalidates edge iterators for the source node
-        EdgeIterator InsertEdge( const NodeIterator from, const NodeIterator to, const EdgeDataT &data ) {
-            Node &node = m_nodes[from];
-            EdgeIterator newFirstEdge = node.edges + node.firstEdge;
-            if ( newFirstEdge >= m_edges.size() || !isDummy( newFirstEdge ) ) {
-                if ( node.firstEdge != 0 && isDummy( node.firstEdge - 1 ) ) {
-                    node.firstEdge--;
-                    m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
-                } else {
-                    EdgeIterator newFirstEdge = ( EdgeIterator ) m_edges.size();
-                    uint32_t newSize = node.edges * 1.1 + 2;
-                    EdgeIterator requiredCapacity = newSize + m_edges.size();
-                    EdgeIterator oldCapacity = m_edges.capacity();
-                    if ( requiredCapacity >= oldCapacity ) {
-                        m_edges.reserve( requiredCapacity * 1.1 );
-                    }
-                    m_edges.resize( m_edges.size() + newSize );
-                    for ( EdgeIterator i = 0; i < node.edges; ++i ) {
-                        m_edges[newFirstEdge + i ] = m_edges[node.firstEdge + i];
-                        makeDummy( node.firstEdge + i );
-                    }
-                    for ( EdgeIterator i = node.edges + 1; i < newSize; ++i )
-                        makeDummy( newFirstEdge + i );
-                    node.firstEdge = newFirstEdge;
-                }
+    unsigned GetDirectedOutDegree(const NodeIterator n) const
+    {
+        unsigned degree = 0;
+        for(EdgeIterator edge = BeginEdges(n); edge < EndEdges(n); ++edge)
+        {
+            if (GetEdgeData(edge).forward)
+            {
+                ++degree;
             }
-            Edge &edge = m_edges[node.firstEdge + node.edges];
-            edge.target = to;
-            edge.data = data;
-            ++m_numEdges;
-            ++node.edges;
-            return EdgeIterator( node.firstEdge + node.edges );
         }
-
-        //removes an edge. Invalidates edge iterators for the source node
-        void DeleteEdge( const NodeIterator source, const EdgeIterator e ) {
-            Node &node = m_nodes[source];
-            --m_numEdges;
-            --node.edges;
-            const uint32_t last = node.firstEdge + node.edges;
-            //swap with last edge
-            m_edges[e] = m_edges[last];
-            makeDummy( last );
-        }
-
-        //removes all edges (source,target)
-        int32_t DeleteEdgesTo( const NodeIterator source, const NodeIterator target ) {
-            int32_t deleted = 0;
-            for ( EdgeIterator i = BeginEdges( source ), iend = EndEdges( source ); i < iend - deleted; ++i ) {
-                if ( m_edges[i].target == target ) {
-                    do {
-                        deleted++;
-                        m_edges[i] = m_edges[iend - deleted];
-                        makeDummy( iend - deleted );
-                    } while ( i < iend - deleted && m_edges[i].target == target );
+        return degree;
+    }
+
+    NodeIterator GetTarget(const EdgeIterator e) const { return NodeIterator(m_edges[e].target); }
+
+    void SetTarget(const EdgeIterator e, const NodeIterator n) { m_edges[e].target = n; }
+
+    EdgeDataT &GetEdgeData(const EdgeIterator e) { return m_edges[e].data; }
+
+    const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return m_edges[e].data; }
+
+    EdgeIterator BeginEdges(const NodeIterator n) const
+    {
+        return EdgeIterator(m_nodes[n].firstEdge);
+    }
+
+    EdgeIterator EndEdges(const NodeIterator n) const
+    {
+        return EdgeIterator(m_nodes[n].firstEdge + m_nodes[n].edges);
+    }
+
+    EdgeRange GetAdjacentEdgeRange(const NodeIterator node) const
+    {
+        return boost::irange(BeginEdges(node), EndEdges(node));
+    }
+
+    // adds an edge. Invalidates edge iterators for the source node
+    EdgeIterator InsertEdge(const NodeIterator from, const NodeIterator to, const EdgeDataT &data)
+    {
+        Node &node = m_nodes[from];
+        EdgeIterator newFirstEdge = node.edges + node.firstEdge;
+        if (newFirstEdge >= m_edges.size() || !isDummy(newFirstEdge))
+        {
+            if (node.firstEdge != 0 && isDummy(node.firstEdge - 1))
+            {
+                node.firstEdge--;
+                m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
+            }
+            else
+            {
+                EdgeIterator newFirstEdge = (EdgeIterator)m_edges.size();
+                unsigned newSize = node.edges * 1.1 + 2;
+                EdgeIterator requiredCapacity = newSize + m_edges.size();
+                EdgeIterator oldCapacity = m_edges.capacity();
+                if (requiredCapacity >= oldCapacity)
+                {
+                    m_edges.reserve(requiredCapacity * 1.1);
+                }
+                m_edges.resize(m_edges.size() + newSize);
+                for (EdgeIterator i = 0; i < node.edges; ++i)
+                {
+                    m_edges[newFirstEdge + i] = m_edges[node.firstEdge + i];
+                    makeDummy(node.firstEdge + i);
                 }
+                for (EdgeIterator i = node.edges + 1; i < newSize; ++i)
+                    makeDummy(newFirstEdge + i);
+                node.firstEdge = newFirstEdge;
             }
-
-            #pragma omp atomic
-            m_numEdges -= deleted;
-            m_nodes[source].edges -= deleted;
-
-            return deleted;
         }
-
-        //searches for a specific edge
-        EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
-            for ( EdgeIterator i = BeginEdges( from ), iend = EndEdges( from ); i != iend; ++i ) {
-                if ( m_edges[i].target == to ) {
-                    return i;
-                }
+        Edge &edge = m_edges[node.firstEdge + node.edges];
+        edge.target = to;
+        edge.data = data;
+        ++m_numEdges;
+        ++node.edges;
+        return EdgeIterator(node.firstEdge + node.edges);
+    }
+
+    // removes an edge. Invalidates edge iterators for the source node
+    void DeleteEdge(const NodeIterator source, const EdgeIterator e)
+    {
+        Node &node = m_nodes[source];
+        --m_numEdges;
+        --node.edges;
+        BOOST_ASSERT(std::numeric_limits<unsigned>::max() != node.edges);
+        const unsigned last = node.firstEdge + node.edges;
+        BOOST_ASSERT(std::numeric_limits<unsigned>::max() != last);
+        // swap with last edge
+        m_edges[e] = m_edges[last];
+        makeDummy(last);
+    }
+
+    // removes all edges (source,target)
+    int32_t DeleteEdgesTo(const NodeIterator source, const NodeIterator target)
+    {
+        int32_t deleted = 0;
+        for (EdgeIterator i = BeginEdges(source), iend = EndEdges(source); i < iend - deleted; ++i)
+        {
+            if (m_edges[i].target == target)
+            {
+                do
+                {
+                    deleted++;
+                    m_edges[i] = m_edges[iend - deleted];
+                    makeDummy(iend - deleted);
+                } while (i < iend - deleted && m_edges[i].target == target);
             }
-            return EndEdges( from );
         }
 
-    protected:
+        m_numEdges -= deleted;
+        m_nodes[source].edges -= deleted;
 
-        bool isDummy( const EdgeIterator edge ) const {
-            return m_edges[edge].target == (std::numeric_limits< NodeIterator >::max)();
-        }
+        return deleted;
+    }
 
-        void makeDummy( const EdgeIterator edge ) {
-            m_edges[edge].target = (std::numeric_limits< NodeIterator >::max)();
+    // searches for a specific edge
+    EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
+    {
+        for (EdgeIterator i = BeginEdges(from), iend = EndEdges(from); i != iend; ++i)
+        {
+            if (to == m_edges[i].target)
+            {
+                return i;
+            }
         }
-
-        struct Node {
-            //index of the first edge
-            EdgeIterator firstEdge;
-            //amount of edges
-            uint32_t edges;
-        };
-
-        struct Edge {
-            NodeIterator target;
-            EdgeDataT data;
-        };
-
-        NodeIterator m_numNodes;
-        EdgeIterator m_numEdges;
-
-        std::vector< Node > m_nodes;
-        DeallocatingVector< Edge > m_edges;
+        return EndEdges(from);
+    }
+
+  protected:
+    bool isDummy(const EdgeIterator edge) const
+    {
+        return m_edges[edge].target == (std::numeric_limits<NodeIterator>::max)();
+    }
+
+    void makeDummy(const EdgeIterator edge)
+    {
+        m_edges[edge].target = (std::numeric_limits<NodeIterator>::max)();
+    }
+
+    struct Node
+    {
+        // index of the first edge
+        EdgeIterator firstEdge;
+        // amount of edges
+        unsigned edges;
+    };
+
+    struct Edge
+    {
+        NodeIterator target;
+        EdgeDataT data;
+    };
+
+    NodeIterator m_numNodes;
+    std::atomic_uint m_numEdges;
+
+    std::vector<Node> m_nodes;
+    DeallocatingVector<Edge> m_edges;
 };
 
-#endif // DYNAMICGRAPH_H_INCLUDED
+#endif // DYNAMICGRAPH_H
diff --git a/DataStructures/EdgeBasedNode.h b/DataStructures/EdgeBasedNode.h
new file mode 100644
index 0000000..90f8b7c
--- /dev/null
+++ b/DataStructures/EdgeBasedNode.h
@@ -0,0 +1,90 @@
+#ifndef EDGE_BASED_NODE_H
+#define EDGE_BASED_NODE_H
+
+#include "../Util/SimpleLogger.h"
+#include "../typedefs.h"
+
+#include <osrm/Coordinate.h>
+
+#include <boost/assert.hpp>
+
+#include <limits>
+
+struct EdgeBasedNode
+{
+
+    EdgeBasedNode() :
+        forward_edge_based_node_id(SPECIAL_NODEID),
+        reverse_edge_based_node_id(SPECIAL_NODEID),
+        u(SPECIAL_NODEID),
+        v(SPECIAL_NODEID),
+        name_id(0),
+        forward_weight(INVALID_EDGE_WEIGHT >> 1),
+        reverse_weight(INVALID_EDGE_WEIGHT >> 1),
+        forward_offset(0),
+        reverse_offset(0),
+        packed_geometry_id(SPECIAL_EDGEID),
+        fwd_segment_position( std::numeric_limits<unsigned short>::max() ),
+        is_in_tiny_cc(false)
+    { }
+
+    explicit EdgeBasedNode(
+        NodeID forward_edge_based_node_id,
+        NodeID reverse_edge_based_node_id,
+        NodeID u,
+        NodeID v,
+        unsigned name_id,
+        int forward_weight,
+        int reverse_weight,
+        int forward_offset,
+        int reverse_offset,
+        unsigned packed_geometry_id,
+        unsigned short fwd_segment_position,
+        bool belongs_to_tiny_component
+    ) :
+        forward_edge_based_node_id(forward_edge_based_node_id),
+        reverse_edge_based_node_id(reverse_edge_based_node_id),
+        u(u),
+        v(v),
+        name_id(name_id),
+        forward_weight(forward_weight),
+        reverse_weight(reverse_weight),
+        forward_offset(forward_offset),
+        reverse_offset(reverse_offset),
+        packed_geometry_id(packed_geometry_id),
+        fwd_segment_position(fwd_segment_position),
+        is_in_tiny_cc(belongs_to_tiny_component)
+    {
+        BOOST_ASSERT((forward_edge_based_node_id != SPECIAL_NODEID) ||
+                     (reverse_edge_based_node_id != SPECIAL_NODEID));
+    }
+
+    static inline FixedPointCoordinate Centroid(const FixedPointCoordinate & a, const FixedPointCoordinate & b)
+    {
+        FixedPointCoordinate centroid;
+        //The coordinates of the midpoint are given by:
+        centroid.lat = (a.lat + b.lat)/2;
+        centroid.lon = (a.lon + b.lon)/2;
+        return centroid;
+    }
+
+    bool IsCompressed() const
+    {
+        return packed_geometry_id != SPECIAL_EDGEID;
+    }
+
+    NodeID forward_edge_based_node_id; // needed for edge-expanded graph
+    NodeID reverse_edge_based_node_id; // needed for edge-expanded graph
+    NodeID u;   // indices into the coordinates array
+    NodeID v;   // indices into the coordinates array
+    unsigned name_id;   // id of the edge name
+    int forward_weight; // weight of the edge
+    int reverse_weight; // weight in the other direction (may be different)
+    int forward_offset; // prefix sum of the weight up the edge TODO: short must suffice
+    int reverse_offset; // prefix sum of the weight from the edge TODO: short must suffice
+    unsigned packed_geometry_id; // if set, then the edge represents a packed geometry
+    unsigned short fwd_segment_position; // segment id in a compressed geometry
+    bool is_in_tiny_cc;
+};
+
+#endif //EDGE_BASED_NODE_H
diff --git a/DataStructures/GridEdge.h b/DataStructures/GridEdge.h
deleted file mode 100644
index 7b2dd78..0000000
--- a/DataStructures/GridEdge.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef GRIDEDGE_H_
-#define GRIDEDGE_H_
-
-#include "Coordinate.h"
-
-struct _GridEdge {
-    _GridEdge(NodeID n, NodeID na, int w, _Coordinate sc, _Coordinate tc, bool bttc) : edgeBasedNode(n), nameID(na), weight(w), startCoord(sc), targetCoord(tc), belongsToTinyComponent(bttc) {}
-    _GridEdge() : edgeBasedNode(UINT_MAX), nameID(UINT_MAX), weight(INT_MAX), belongsToTinyComponent(false) {}
-    NodeID edgeBasedNode;
-    NodeID nameID;
-    int weight;
-    _Coordinate startCoord;
-    _Coordinate targetCoord;
-    bool belongsToTinyComponent;
-
-    bool operator< ( const _GridEdge& right) const {
-        return edgeBasedNode < right.edgeBasedNode;
-    }
-    bool operator== ( const _GridEdge& right) const {
-        return edgeBasedNode == right.edgeBasedNode;
-    }
-};
-
-struct GridEntry {
-    GridEntry() : fileIndex(UINT_MAX), ramIndex(UINT_MAX){}
-    GridEntry(_GridEdge e, unsigned f, unsigned r) : edge(e), fileIndex(f), ramIndex(r) {}
-    _GridEdge edge;
-    unsigned fileIndex;
-    unsigned ramIndex;
-    bool operator< ( const GridEntry& right ) const {
-        return (edge.edgeBasedNode < right.edge.edgeBasedNode);
-    }
-    bool operator==( const GridEntry& right ) const {
-        return right.edge.edgeBasedNode == edge.edgeBasedNode;
-    }
-};
-
-struct CompareGridEdgeDataByFileIndex {
-    bool operator ()  (const GridEntry & a, const GridEntry & b) const {
-        return a.fileIndex < b.fileIndex;
-    }
-};
-
-struct CompareGridEdgeDataByRamIndex {
-    typedef GridEntry value_type;
-
-    bool operator ()  (const GridEntry & a, const GridEntry & b) const {
-        return a.ramIndex < b.ramIndex;
-    }
-    value_type max_value() {
-        GridEntry e;
-        e.ramIndex = (1024*1024) - 1;
-        return e;
-    }
-    value_type min_value() {
-        GridEntry e;
-        e.ramIndex = 0;
-        return e;
-    }
-};
-
-#endif /* GRIDEDGE_H_ */
diff --git a/DataStructures/HashTable.h b/DataStructures/HashTable.h
index 57c2dde..199c6df 100644
--- a/DataStructures/HashTable.h
+++ b/DataStructures/HashTable.h
@@ -1,79 +1,78 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-  Created on: 18.11.2010
-  Author: dennis
- */
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#ifndef HASHTABLE_H_
-#define HASHTABLE_H_
+*/
 
-#include <boost/unordered_map.hpp>
+#ifndef HASH_TABLE_H
+#define HASH_TABLE_H
 
-template<typename keyT, typename valueT>
-class HashTable {
-    typedef boost::unordered_map<keyT, valueT> MyHashTable;
-public:
-    typedef typename boost::unordered_map<keyT, valueT>::const_iterator MyIterator;
-    typedef MyIterator iterator;
-    HashTable() { }
-    HashTable(const unsigned size) {
-        table.resize(size);
-    }
-    inline void Add(const keyT& key, const valueT& value){
-        table[key] = value;
-    }
-    inline void Set(const keyT& key, const valueT& value){
-        table[key] = value;
-    }
-    inline valueT Find(const keyT& key) const {
-        if(table.find(key) == table.end())
-            return valueT();
-        return table.find(key)->second;
-    }
+#include <vector>
 
-    inline bool Holds(const keyT& key) const {
-        if(table.find(key) == table.end())
-            return false;
-        return true;
-    }
-    void EraseAll() {
-        if(table.size() > 0)
-            table.clear();
-    }
+template <typename Key, typename Value>
+class HashTable
+{
+  private:
+    typedef std::pair<Key, Value> KeyValPair;
+    std::vector<KeyValPair> table;
+
+  public:
+    HashTable() {}
 
-    inline valueT operator[] (keyT key) const {
-    	if(table.find(key) == table.end())
-    		return valueT();
-    	return table.find(key)->second;
+    inline void Add(Key const &key, Value const &value)
+    {
+        table.emplace_back(std::move(key), std::move(value));
     }
-    inline unsigned Size() const {
-        return table.size();
+
+    inline void Clear()
+    {
+        table.clear();
     }
-    MyIterator begin() const {
-        return table.begin();
+
+    inline const Value Find(Key const &key) const
+    {
+        for (const auto &key_val_pair : table)
+        {
+            if (key_val_pair.first == key)
+            {
+                return key_val_pair.second;
+            }
+        }
+        return Value();
     }
-    MyIterator end() const {
-        return table.end();
+
+    inline const bool Holds(Key const &key) const
+    {
+        for (const auto &key_val_pair : table)
+        {
+            if (key_val_pair.first == key)
+            {
+                return true;
+            }
+        }
+        return false;
     }
-private:
-    MyHashTable table;
 };
 
-#endif /* HASHTABLE_H_ */
+#endif /* HASH_TABLE_H */
diff --git a/DataStructures/HilbertValue.cpp b/DataStructures/HilbertValue.cpp
new file mode 100644
index 0000000..9cb88c7
--- /dev/null
+++ b/DataStructures/HilbertValue.cpp
@@ -0,0 +1,100 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "HilbertValue.h"
+
+#include <osrm/Coordinate.h>
+
+uint64_t HilbertCode::operator()(const FixedPointCoordinate &current_coordinate) const
+{
+    unsigned location[2];
+    location[0] = current_coordinate.lat + static_cast<int>(90 * COORDINATE_PRECISION);
+    location[1] = current_coordinate.lon + static_cast<int>(180 * COORDINATE_PRECISION);
+
+    TransposeCoordinate(location);
+    return BitInterleaving(location[0], location[1]);
+}
+
+uint64_t HilbertCode::BitInterleaving(const uint32_t latitude, const uint32_t longitude) const
+{
+    uint64_t result = 0;
+    for (int8_t index = 31; index >= 0; --index)
+    {
+        result |= (latitude >> index) & 1;
+        result <<= 1;
+        result |= (longitude >> index) & 1;
+        if (0 != index)
+        {
+            result <<= 1;
+        }
+    }
+    return result;
+}
+
+void HilbertCode::TransposeCoordinate(uint32_t *X) const
+{
+    uint32_t M = 1 << (32 - 1), P, Q, t;
+    int i;
+    // Inverse undo
+    for (Q = M; Q > 1; Q >>= 1)
+    {
+        P = Q - 1;
+        for (i = 0; i < 2; ++i)
+        {
+
+            const bool condition = (X[i] & Q);
+            if (condition)
+            {
+                X[0] ^= P; // invert
+            }
+            else
+            {
+                t = (X[0] ^ X[i]) & P;
+                X[0] ^= t;
+                X[i] ^= t;
+            }
+        } // exchange
+    }
+    // Gray encode
+    for (i = 1; i < 2; ++i)
+    {
+        X[i] ^= X[i - 1];
+    }
+    t = 0;
+    for (Q = M; Q > 1; Q >>= 1)
+    {
+        const bool condition = (X[2 - 1] & Q);
+        if (condition)
+        {
+            t ^= Q - 1;
+        }
+    } // check if this for loop is wrong
+    for (i = 0; i < 2; ++i)
+    {
+        X[i] ^= t;
+    }
+}
diff --git a/DataStructures/HilbertValue.h b/DataStructures/HilbertValue.h
index 05e2bb1..9de2372 100644
--- a/DataStructures/HilbertValue.h
+++ b/DataStructures/HilbertValue.h
@@ -1,87 +1,49 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef HILBERTVALUE_H_
 #define HILBERTVALUE_H_
 
-#include <boost/integer.hpp>
-#include <boost/noncopyable.hpp>
+#include <cstdint>
 
 // computes a 64 bit value that corresponds to the hilbert space filling curve
 
-class HilbertCode : boost::noncopyable {
-public:
-	static uint64_t GetHilbertNumberForCoordinate(
-			const _Coordinate & current_coordinate) {
-		unsigned location[2];
-		location[0] = current_coordinate.lat+( 90*100000);
-		location[1] = current_coordinate.lon+(180*100000);
+struct FixedPointCoordinate;
 
-		TransposeCoordinate(location);
-		const uint64_t result = BitInterleaving(location[0], location[1]);
-		return result;
-	}
-private:
-	static inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b) {
-		uint64_t result = 0;
-		for(int8_t index = 31; index >= 0; --index){
-			result |= (a >> index) & 1;
-			result <<= 1;
-			result |= (b >> index) & 1;
-			if(0 != index){
-				result <<= 1;
-			}
-		}
-		return result;
-	}
+class HilbertCode
+{
+  public:
+    uint64_t operator()(const FixedPointCoordinate &current_coordinate) const;
+    HilbertCode() {}
+    HilbertCode(const HilbertCode &) = delete;
 
-	static inline void TransposeCoordinate( uint32_t * X) {
-		uint32_t M = 1 << (32-1), P, Q, t;
-		int i;
-		// Inverse undo
-		for( Q = M; Q > 1; Q >>= 1 ) {
-			P=Q-1;
-			for( i = 0; i < 2; ++i ) {
-				if( X[i] & Q ) {
-					X[0] ^= P; // invert
-				} else {
-					t = (X[0]^X[i]) & P;
-					X[0] ^= t;
-					X[i] ^= t;
-				}
-			} // exchange
-		}
-		// Gray encode
-		for( i = 1; i < 2; ++i ) {
-			X[i] ^= X[i-1];
-		}
-		t=0;
-		for( Q = M; Q > 1; Q >>= 1 ) {
-			if( X[2-1] & Q ) {
-				t ^= Q-1;
-			}
-		} //check if this for loop is wrong
-		for( i = 0; i < 2; ++i ) {
-			X[i] ^= t;
-		}
-	}
+  private:
+    inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b) const;
+    inline void TransposeCoordinate(uint32_t *X) const;
 };
 
 #endif /* HILBERTVALUE_H_ */
diff --git a/DataStructures/ImportEdge.cpp b/DataStructures/ImportEdge.cpp
new file mode 100644
index 0000000..0d04b9f
--- /dev/null
+++ b/DataStructures/ImportEdge.cpp
@@ -0,0 +1,107 @@
+/*
+
+Copyright (c) 2014, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "ImportEdge.h"
+
+#include <boost/assert.hpp>
+
+bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
+{
+    if (source == other.source)
+    {
+        if (target == other.target)
+        {
+            if (weight == other.weight)
+            {
+                return forward && backward && ((!other.forward) || (!other.backward));
+            }
+            return weight < other.weight;
+        }
+        return target < other.target;
+    }
+    return source < other.source;
+}
+
+NodeBasedEdge::NodeBasedEdge(NodeID source,
+                             NodeID target,
+                             NodeID name_id,
+                             EdgeWeight weight,
+                             bool forward,
+                             bool backward,
+                             short type,
+                             bool roundabout,
+                             bool in_tiny_cc,
+                             bool access_restricted,
+                             bool contra_flow,
+                             bool is_split)
+    : source(source), target(target), name_id(name_id), weight(weight), type(type),
+      forward(forward), backward(backward), roundabout(roundabout), in_tiny_cc(in_tiny_cc),
+      access_restricted(access_restricted), contra_flow(contra_flow), is_split(is_split)
+{
+    BOOST_ASSERT_MSG(type > 0, "negative edge type");
+}
+
+bool EdgeBasedEdge::operator<(const EdgeBasedEdge &other) const
+{
+    if (source == other.source)
+    {
+        if (target == other.target)
+        {
+            if (weight == other.weight)
+            {
+                return forward && backward && ((!other.forward) || (!other.backward));
+            }
+            return weight < other.weight;
+        }
+        return target < other.target;
+    }
+    return source < other.source;
+}
+
+template <class EdgeT>
+EdgeBasedEdge::EdgeBasedEdge(const EdgeT &other)
+    : source(other.source), target(other.target), edge_id(other.data.via),
+      weight(other.data.distance), forward(other.data.forward), backward(other.data.backward)
+{
+}
+
+/** Default constructor. target and weight are set to 0.*/
+EdgeBasedEdge::EdgeBasedEdge()
+    : source(0), target(0), edge_id(0), weight(0), forward(false), backward(false)
+{
+}
+
+EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
+                             const NodeID target,
+                             const NodeID edge_id,
+                             const EdgeWeight weight,
+                             const bool forward,
+                             const bool backward)
+    : source(source), target(target), edge_id(edge_id), weight(weight), forward(forward),
+      backward(backward)
+{
+}
diff --git a/DataStructures/ImportEdge.h b/DataStructures/ImportEdge.h
index 714560c..f79a484 100644
--- a/DataStructures/ImportEdge.h
+++ b/DataStructures/ImportEdge.h
@@ -1,142 +1,92 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef EDGE_H
-#define EDGE_H
-
-#include <cassert>
-
-class NodeBasedEdge {
-public:
-
-    bool operator< (const NodeBasedEdge& e) const {
-        if (source() == e.source()) {
-            if (target() == e.target()) {
-                if (weight() == e.weight()) {
-                    return (isForward() && isBackward() &&
-                            ((! e.isForward()) || (! e.isBackward())));
-                }
-                return (weight() < e.weight());
-            }
-            return (target() < e.target());
-        }
-        return (source() < e.source());
-    }
-
-    explicit NodeBasedEdge(NodeID s, NodeID t, NodeID n, EdgeWeight w, bool f, bool b, short ty, bool ra, bool ig, bool ar, bool cf) :
-                                            _source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty), _roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar), _contraFlow(cf) { if(ty < 0) {ERR("Type: " << ty);}; }
-
-    NodeID target() const {return _target; }
-    NodeID source() const {return _source; }
-    NodeID name() const { return _name; }
-    EdgeWeight weight() const {return _weight; }
-
-    short type() const { assert(_type >= 0); return _type; }
-    bool isBackward() const { return backward; }
-    bool isForward() const { return forward; }
-    bool isLocatable() const { return _type != 14; }
-    bool isRoundabout() const { return _roundabout; }
-    bool ignoreInGrid() const { return _ignoreInGrid; }
-    bool isAccessRestricted() const { return _accessRestricted; }
-    bool isContraFlow() const { return _contraFlow; }
-
-    NodeID _source;
-    NodeID _target;
-    NodeID _name;
-    EdgeWeight _weight;
-    bool forward;
-    bool backward;
-    short _type;
-    bool _roundabout;
-    bool _ignoreInGrid;
-    bool _accessRestricted;
-    bool _contraFlow;
-
-private:
-    /** Default constructor. target and weight are set to 0.*/
-    NodeBasedEdge() :
-        _source(0), _target(0), _name(0), _weight(0), forward(0), backward(0), _type(0), _roundabout(false), _ignoreInGrid(false), _accessRestricted(false), _contraFlow(false) { assert(false); } //shall not be used.
 
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef IMPORT_EDGE_H
+#define IMPORT_EDGE_H
+
+#include "../typedefs.h"
+
+struct NodeBasedEdge
+{
+    bool operator<(const NodeBasedEdge &e) const;
+
+    explicit NodeBasedEdge(NodeID source,
+                           NodeID target,
+                           NodeID name_id,
+                           EdgeWeight weight,
+                           bool forward,
+                           bool backward,
+                           short type,
+                           bool roundabout,
+                           bool in_tiny_cc,
+                           bool access_restricted,
+                           bool contra_flow,
+                           bool is_split);
+
+    NodeID source;
+    NodeID target;
+    NodeID name_id;
+    EdgeWeight weight;
+    short type;
+    bool forward : 1;
+    bool backward : 1;
+    bool roundabout : 1;
+    bool in_tiny_cc : 1;
+    bool access_restricted : 1;
+    bool contra_flow : 1;
+    bool is_split : 1;
+
+    NodeBasedEdge() = delete;
 };
 
-class EdgeBasedEdge {
-public:
-
-    bool operator< (const EdgeBasedEdge& e) const {
-        if (source() == e.source()) {
-            if (target() == e.target()) {
-                if (weight() == e.weight()) {
-                    return (isForward() && isBackward() &&
-                            ((! e.isForward()) || (! e.isBackward())));
-                }
-                return (weight() < e.weight());
-            }
-            return (target() < e.target());
-        }
-        return (source() < e.source());
-    }
-
-    template<class EdgeT>
-    EdgeBasedEdge(const EdgeT & myEdge ) :
-        m_source(myEdge.source),
-        m_target(myEdge.target),
-        m_edgeID(myEdge.data.via),
-        m_weight(myEdge.data.distance),
-        m_forward(myEdge.data.forward),
-        m_backward(myEdge.data.backward)
-    { }
-
-    /** Default constructor. target and weight are set to 0.*/
-    EdgeBasedEdge() :
-        m_source(0),
-        m_target(0),
-        m_edgeID(0),
-        m_weight(0),
-        m_forward(false),
-        m_backward(false)
-    { }
-
-    explicit EdgeBasedEdge(const NodeID s, const NodeID t, const NodeID v, const EdgeWeight w, const bool f, const bool b) :
-        m_source(s),
-        m_target(t),
-        m_edgeID(v),
-        m_weight(w),
-        m_forward(f),
-        m_backward(b)
-    {}
-
-    NodeID target() const {return m_target; }
-    NodeID source() const {return m_source; }
-    EdgeWeight weight() const {return m_weight; }
-    NodeID id() const { return m_edgeID; }
-    bool isBackward() const { return m_backward; }
-    bool isForward() const { return m_forward; }
-private:
-    NodeID m_source;
-    NodeID m_target;
-    NodeID m_edgeID;
-    EdgeWeight m_weight:30;
-    bool m_forward:1;
-    bool m_backward:1;
+struct EdgeBasedEdge
+{
+
+  public:
+    bool operator<(const EdgeBasedEdge &e) const;
+
+    template <class EdgeT> explicit EdgeBasedEdge(const EdgeT &myEdge);
+
+    EdgeBasedEdge();
+
+    explicit EdgeBasedEdge(const NodeID source,
+                           const NodeID target,
+                           const NodeID edge_id,
+                           const EdgeWeight weight,
+                           const bool forward,
+                           const bool backward);
+    NodeID source;
+    NodeID target;
+    NodeID edge_id;
+    EdgeWeight weight : 30;
+    bool forward : 1;
+    bool backward : 1;
 };
 
 typedef NodeBasedEdge ImportEdge;
 
-#endif // EDGE_H
+#endif /* IMPORT_EDGE_H */
diff --git a/DataStructures/ImportNode.cpp b/DataStructures/ImportNode.cpp
new file mode 100644
index 0000000..8975d40
--- /dev/null
+++ b/DataStructures/ImportNode.cpp
@@ -0,0 +1,64 @@
+/*
+
+Copyright (c) 2014, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "ImportNode.h"
+
+#include <limits>
+
+ExternalMemoryNode::ExternalMemoryNode(
+    int lat, int lon, unsigned int node_id, bool bollard, bool traffic_light)
+    : NodeInfo(lat, lon, node_id), bollard(bollard), trafficLight(traffic_light)
+{
+}
+
+ExternalMemoryNode::ExternalMemoryNode() : bollard(false), trafficLight(false)
+{
+}
+
+ExternalMemoryNode ExternalMemoryNode::min_value()
+{
+    return ExternalMemoryNode(0, 0, 0, false, false);
+}
+
+ExternalMemoryNode ExternalMemoryNode::max_value()
+{
+    return ExternalMemoryNode(std::numeric_limits<int>::max(),
+                              std::numeric_limits<int>::max(),
+                              std::numeric_limits<unsigned>::max(),
+                              false,
+                              false);
+}
+
+void ImportNode::Clear()
+{
+    keyVals.Clear();
+    lat = 0;
+    lon = 0;
+    node_id = 0;
+    bollard = false;
+    trafficLight = false;
+}
diff --git a/DataStructures/ImportNode.h b/DataStructures/ImportNode.h
index b9c27be..b8a9451 100644
--- a/DataStructures/ImportNode.h
+++ b/DataStructures/ImportNode.h
@@ -1,54 +1,57 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef IMPORTNODE_H_
 #define IMPORTNODE_H_
 
-#include "NodeCoords.h"
+#include "QueryNode.h"
 #include "../DataStructures/HashTable.h"
 
+#include <string>
+
+struct ExternalMemoryNode : NodeInfo
+{
+    ExternalMemoryNode(int lat, int lon, unsigned int id, bool bollard, bool traffic_light);
 
-struct _Node : NodeInfo{
-    _Node(int _lat, int _lon, unsigned int _id, bool _bollard, bool _trafficLight) : NodeInfo(_lat, _lon,  _id), bollard(_bollard), trafficLight(_trafficLight) {}
-    _Node() : bollard(false), trafficLight(false) {}
+    ExternalMemoryNode();
+
+    static ExternalMemoryNode min_value();
+
+    static ExternalMemoryNode max_value();
 
-    static _Node min_value() {
-        return _Node(0,0,0, false, false);
-    }
-    static _Node max_value() {
-        return _Node((std::numeric_limits<int>::max)(), (std::numeric_limits<int>::max)(), (std::numeric_limits<unsigned int>::max)(), false, false);
-    }
-    NodeID key() const {
-        return id;
-    }
     bool bollard;
     bool trafficLight;
 };
 
-struct ImportNode : public _Node {
+struct ImportNode : public ExternalMemoryNode
+{
     HashTable<std::string, std::string> keyVals;
-	
-	inline void Clear() {
-		keyVals.EraseAll();
-		lat = 0; lon = 0; id = 0; bollard = false; trafficLight = false;
-	}
+
+    inline void Clear();
 };
 
 #endif /* IMPORTNODE_H_ */
diff --git a/DataStructures/InputReaderFactory.h b/DataStructures/InputReaderFactory.h
index f58232f..3f6aa3c 100644
--- a/DataStructures/InputReaderFactory.h
+++ b/DataStructures/InputReaderFactory.h
@@ -1,94 +1,123 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef INPUTREADERFACTORY_H
-#define INPUTREADERFACTORY_H
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef INPUT_READER_FACTORY_H
+#define INPUT_READER_FACTORY_H
+
+#include <boost/assert.hpp>
 
 #include <bzlib.h>
 #include <libxml/xmlreader.h>
 
-struct BZ2Context {
-    FILE* file;
-    BZFILE* bz2;
+struct BZ2Context
+{
+    FILE *file;
+    BZFILE *bz2;
     int error;
     int nUnused;
     char unused[BZ_MAX_UNUSED];
 };
 
-int readFromBz2Stream( void* pointer, char* buffer, int len ) {
-    void *unusedTmpVoid=NULL;
-    char *unusedTmp=NULL;
-    BZ2Context* context = (BZ2Context*) pointer;
+int readFromBz2Stream(void *pointer, char *buffer, int len)
+{
+    void *unusedTmpVoid = nullptr;
+    char *unusedTmp = nullptr;
+    BZ2Context *context = (BZ2Context *)pointer;
     int read = 0;
-    while(0 == read && !(BZ_STREAM_END == context->error && 0 == context->nUnused && feof(context->file))) {
+    while (0 == read &&
+           !(BZ_STREAM_END == context->error && 0 == context->nUnused && feof(context->file)))
+    {
         read = BZ2_bzRead(&context->error, context->bz2, buffer, len);
-        if(BZ_OK == context->error) {
+        if (BZ_OK == context->error)
+        {
             return read;
-        } else if(BZ_STREAM_END == context->error) {
+        }
+        else if (BZ_STREAM_END == context->error)
+        {
             BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
-            if(BZ_OK != context->error) {std::cerr << "Could not BZ2_bzReadGetUnused" <<std::endl; exit(-1);};
-            unusedTmp = (char*)unusedTmpVoid;
-            for(int i=0;i<context->nUnused;i++) {
+            BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadGetUnused");
+            unusedTmp = (char *)unusedTmpVoid;
+            for (int i = 0; i < context->nUnused; i++)
+            {
                 context->unused[i] = unusedTmp[i];
             }
             BZ2_bzReadClose(&context->error, context->bz2);
-            if(BZ_OK != context->error) {std::cerr << "Could not BZ2_bzReadClose" <<std::endl; exit(-1);};
+            BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadClose");
             context->error = BZ_STREAM_END; // set to the stream end for next call to this function
-            if(0 == context->nUnused && feof(context->file)) {
+            if (0 == context->nUnused && feof(context->file))
+            {
                 return read;
-            } else {
-                context->bz2 = BZ2_bzReadOpen(&context->error, context->file, 0, 0, context->unused, context->nUnused);
-                if(NULL == context->bz2){std::cerr << "Could not open file" <<std::endl; exit(-1);};
             }
-        } else { std::cerr << "Could not read bz2 file" << std::endl; exit(-1); }
+            else
+            {
+                context->bz2 = BZ2_bzReadOpen(
+                    &context->error, context->file, 0, 0, context->unused, context->nUnused);
+                BOOST_ASSERT_MSG(nullptr != context->bz2, "Could not open file");
+            }
+        }
+        else
+        {
+            BOOST_ASSERT_MSG(false, "Could not read bz2 file");
+        }
     }
     return read;
 }
 
-int closeBz2Stream( void *pointer )
+int closeBz2Stream(void *pointer)
 {
-    BZ2Context* context = (BZ2Context*) pointer;
-    fclose( context->file );
+    BZ2Context *context = (BZ2Context *)pointer;
+    fclose(context->file);
     delete context;
     return 0;
 }
 
-xmlTextReaderPtr inputReaderFactory( const char* name )
+xmlTextReaderPtr inputReaderFactory(const char *name)
 {
     std::string inputName(name);
 
-    if(inputName.find(".osm.bz2")!=std::string::npos)
+    if (inputName.find(".osm.bz2") != std::string::npos)
     {
-        BZ2Context* context = new BZ2Context();
+        BZ2Context *context = new BZ2Context();
         context->error = false;
-        context->file = fopen( name, "r" );
+        context->file = fopen(name, "r");
         int error;
-        context->bz2 = BZ2_bzReadOpen( &error, context->file, 0, 0, context->unused, context->nUnused );
-        if ( context->bz2 == NULL || context->file == NULL ) {
+        context->bz2 =
+            BZ2_bzReadOpen(&error, context->file, 0, 0, context->unused, context->nUnused);
+        if (context->bz2 == nullptr || context->file == nullptr)
+        {
             delete context;
-            return NULL;
+            return nullptr;
         }
-        return xmlReaderForIO( readFromBz2Stream, closeBz2Stream, (void*) context, NULL, NULL, 0 );
-    } else {
+        return xmlReaderForIO(readFromBz2Stream, closeBz2Stream, (void *)context, nullptr, nullptr, 0);
+    }
+    else
+    {
         return xmlNewTextReaderFilename(name);
     }
 }
 
-#endif // INPUTREADERFACTORY_H
+#endif // INPUT_READER_FACTORY_H
diff --git a/DataStructures/JSONContainer.h b/DataStructures/JSONContainer.h
new file mode 100644
index 0000000..47dc34b
--- /dev/null
+++ b/DataStructures/JSONContainer.h
@@ -0,0 +1,237 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+// based on https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp
+
+#ifndef JSON_CONTAINER_H
+#define JSON_CONTAINER_H
+
+#include "../Util/StringUtil.h"
+
+#include <boost/variant.hpp>
+
+#include <iostream>
+#include <vector>
+#include <string>
+#include <unordered_map>
+
+namespace JSON
+{
+
+struct String;
+struct Number;
+struct Object;
+struct Array;
+struct True;
+struct False;
+struct Null;
+
+typedef boost::variant<boost::recursive_wrapper<String>,
+                       boost::recursive_wrapper<Number>,
+                       boost::recursive_wrapper<Object>,
+                       boost::recursive_wrapper<Array>,
+                       boost::recursive_wrapper<True>,
+                       boost::recursive_wrapper<False>,
+                       boost::recursive_wrapper<Null> > Value;
+
+struct String
+{
+    String() {}
+    String(const char *value) : value(value) {}
+    String(const std::string &value) : value(value) {}
+    std::string value;
+};
+
+struct Number
+{
+    Number() {}
+    Number(double value) : value(value) {}
+    double value;
+};
+
+struct Object
+{
+    std::unordered_map<std::string, Value> values;
+};
+
+struct Array
+{
+    std::vector<Value> values;
+};
+
+struct True
+{
+};
+
+struct False
+{
+};
+
+struct Null
+{
+};
+
+struct Renderer : boost::static_visitor<>
+{
+    Renderer(std::ostream &_out) : out(_out) {}
+
+    void operator()(const String &string) const { out << "\"" << string.value << "\""; }
+
+    void operator()(const Number &number) const
+    {
+        out.precision(10);
+        out << number.value;
+    }
+
+    void operator()(const Object &object) const
+    {
+        out << "{";
+        auto iterator = object.values.begin();
+        while (iterator != object.values.end())
+        {
+            out << "\"" << (*iterator).first << "\":";
+            boost::apply_visitor(Renderer(out), (*iterator).second);
+            if (++iterator != object.values.end())
+            {
+                out << ",";
+            }
+        }
+        out << "}";
+    }
+
+    void operator()(const Array &array) const
+    {
+        out << "[";
+        std::vector<Value>::const_iterator iterator;
+        iterator = array.values.begin();
+        while (iterator != array.values.end())
+        {
+            boost::apply_visitor(Renderer(out), *iterator);
+            if (++iterator != array.values.end())
+            {
+                out << ",";
+            }
+        }
+        out << "]";
+    }
+
+    void operator()(const True &) const { out << "true"; }
+
+    void operator()(const False &) const { out << "false"; }
+
+    void operator()(const Null &) const { out << "null"; }
+
+  private:
+    std::ostream &out;
+};
+
+struct ArrayRenderer : boost::static_visitor<>
+{
+    ArrayRenderer(std::vector<char> &_out) : out(_out) {}
+
+    void operator()(const String &string) const {
+        out.push_back('\"');
+        out.insert(out.end(), string.value.begin(), string.value.end());
+        out.push_back('\"');
+    }
+
+    void operator()(const Number &number) const
+    {
+        const std::string number_string = FixedDoubleToString(number.value);
+        out.insert(out.end(), number_string.begin(), number_string.end());
+    }
+
+    void operator()(const Object &object) const
+    {
+        out.push_back('{');
+        auto iterator = object.values.begin();
+        while (iterator != object.values.end())
+        {
+            out.push_back('\"');
+            out.insert(out.end(), (*iterator).first.begin(), (*iterator).first.end());
+            out.push_back('\"');
+            out.push_back(':');
+
+            boost::apply_visitor(ArrayRenderer(out), (*iterator).second);
+            if (++iterator != object.values.end())
+            {
+                out.push_back(',');
+            }
+        }
+        out.push_back('}');
+    }
+
+    void operator()(const Array &array) const
+    {
+        out.push_back('[');
+        std::vector<Value>::const_iterator iterator;
+        iterator = array.values.begin();
+        while (iterator != array.values.end())
+        {
+            boost::apply_visitor(ArrayRenderer(out), *iterator);
+            if (++iterator != array.values.end())
+            {
+                out.push_back(',');
+            }
+        }
+        out.push_back(']');
+    }
+
+    void operator()(const True &) const {
+        const std::string temp("true");
+        out.insert(out.end(), temp.begin(), temp.end());
+    }
+
+    void operator()(const False &) const {
+        const std::string temp("false");
+        out.insert(out.end(), temp.begin(), temp.end());
+    }
+
+    void operator()(const Null &) const {
+        const std::string temp("null");
+        out.insert(out.end(), temp.begin(), temp.end());
+    }
+
+  private:
+    std::vector<char> &out;
+};
+
+inline void render(std::ostream &out, const Object &object)
+{
+    Value value = object;
+    boost::apply_visitor(Renderer(out), value);
+}
+
+inline void render(std::vector<char> &out, const Object &object)
+{
+    Value value = object;
+    boost::apply_visitor(ArrayRenderer(out), value);
+}
+
+} // namespace JSON
+
+#endif // JSON_CONTAINER_H
diff --git a/DataStructures/LRUCache.h b/DataStructures/LRUCache.h
index a2c0b13..75b9139 100644
--- a/DataStructures/LRUCache.h
+++ b/DataStructures/LRUCache.h
@@ -1,82 +1,97 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef LRUCACHE_H
 #define LRUCACHE_H
 
 #include <list>
-#include <boost/unordered_map.hpp>
+#include <unordered_map>
 
-template<typename KeyT, typename ValueT>
-class LRUCache {
-private:
-    struct CacheEntry {
+template <typename KeyT, typename ValueT> class LRUCache
+{
+  private:
+    struct CacheEntry
+    {
         CacheEntry(KeyT k, ValueT v) : key(k), value(v) {}
         KeyT key;
         ValueT value;
     };
     unsigned capacity;
     std::list<CacheEntry> itemsInCache;
-    boost::unordered_map<KeyT, typename std::list<CacheEntry>::iterator > positionMap;
-public:
-    LRUCache(unsigned c) : capacity(c) {}
+    std::unordered_map<KeyT, typename std::list<CacheEntry>::iterator> positionMap;
 
-    bool Holds(KeyT key) {
-        if(positionMap.find(key) != positionMap.end()) {
+  public:
+    explicit LRUCache(unsigned c) : capacity(c) {}
+
+    bool Holds(KeyT key)
+    {
+        if (positionMap.find(key) != positionMap.end())
+        {
             return true;
         }
         return false;
     }
 
-    void Insert(const KeyT key, ValueT &value) {
+    void Insert(const KeyT key, ValueT &value)
+    {
         itemsInCache.push_front(CacheEntry(key, value));
         positionMap.insert(std::make_pair(key, itemsInCache.begin()));
-        if(itemsInCache.size() > capacity) {
+        if (itemsInCache.size() > capacity)
+        {
             positionMap.erase(itemsInCache.back().key);
             itemsInCache.pop_back();
         }
     }
 
-    void Insert(const KeyT key, ValueT value) {
+    void Insert(const KeyT key, ValueT value)
+    {
         itemsInCache.push_front(CacheEntry(key, value));
         positionMap.insert(std::make_pair(key, itemsInCache.begin()));
-        if(itemsInCache.size() > capacity) {
+        if (itemsInCache.size() > capacity)
+        {
             positionMap.erase(itemsInCache.back().key);
             itemsInCache.pop_back();
         }
     }
 
-    bool Fetch(const KeyT key, ValueT& result) {
-        if(Holds(key)) {
+    bool Fetch(const KeyT key, ValueT &result)
+    {
+        if (Holds(key))
+        {
             CacheEntry e = *(positionMap.find(key)->second);
             result = e.value;
 
-            //move to front
+            // move to front
             itemsInCache.splice(positionMap.find(key)->second, itemsInCache, itemsInCache.begin());
             positionMap.find(key)->second = itemsInCache.begin();
             return true;
         }
         return false;
     }
-    unsigned Size() const {
-        return itemsInCache.size();
-    }
+    unsigned Size() const { return itemsInCache.size(); }
 };
-#endif //LRUCACHE_H
+#endif // LRUCACHE_H
diff --git a/DataStructures/MercatorUtil.h b/DataStructures/MercatorUtil.h
deleted file mode 100644
index 15bea27..0000000
--- a/DataStructures/MercatorUtil.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
-*/
-
-#ifndef MERCATORUTIL_H_
-#define MERCATORUTIL_H_
-
-#include <cmath>
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-inline double y2lat(double a) {
-	return 180/M_PI * (2 * atan(exp(a*M_PI/180)) - M_PI/2);
-}
-
-inline double lat2y(double a) {
-	return 180/M_PI * log(tan(M_PI/4+a*(M_PI/180)/2));
-}
-
-#endif /* MERCATORUTIL_H_ */
diff --git a/DataStructures/NNGrid.h b/DataStructures/NNGrid.h
deleted file mode 100644
index 22cb4e2..0000000
--- a/DataStructures/NNGrid.h
+++ /dev/null
@@ -1,602 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef NNGRID_H_
-#define NNGRID_H_
-
-#include <cassert>
-#include <cfloat>
-#include <cmath>
-#include <cstring>
-
-#include <algorithm>
-#include <fstream>
-#include <limits>
-#include <vector>
-
-#ifndef ROUTED
-#include <stxxl.h>
-#endif
-
-#ifdef _WIN32
-#include <math.h>
-#endif
-
-#include <boost/thread.hpp>
-#include <boost/foreach.hpp>
-#include <boost/unordered_map.hpp>
-
-#include "DeallocatingVector.h"
-#include "GridEdge.h"
-#include "Percent.h"
-#include "PhantomNodes.h"
-#include "MercatorUtil.h"
-#include "StaticGraph.h"
-#include "TimingUtil.h"
-#include "../Algorithms/Bresenham.h"
-
-namespace NNGrid{
-
-static boost::thread_specific_ptr<std::ifstream> localStream;
-
-template<bool WriteAccess = false>
-class NNGrid {
-public:
-    NNGrid() /*: cellCache(500), fileCache(500)*/ {
-        ramIndexTable.resize((1024*1024), std::numeric_limits<uint64_t>::max());
-    }
-
-    NNGrid(const char* rif, const char* _i) {
-        if(WriteAccess) {
-            ERR("Not available in Write mode");
-        }
-        iif = std::string(_i);
-        ramIndexTable.resize((1024*1024), std::numeric_limits<uint64_t>::max());
-        ramInFile.open(rif, std::ios::in | std::ios::binary);
-        if(!ramInFile) { ERR(rif <<  " not found"); }
-
-    }
-
-    ~NNGrid() {
-        if(ramInFile.is_open()) ramInFile.close();
-
-#ifndef ROUTED
-        if (WriteAccess) {
-            entries.clear();
-        }
-#endif
-        if(localStream.get() && localStream->is_open()) {
-            localStream->close();
-        }
-    }
-
-    void OpenIndexFiles() {
-        assert(ramInFile.is_open());
-        ramInFile.read(static_cast<char*>(static_cast<void*>(&ramIndexTable[0]) ), sizeof(uint64_t)*1024*1024);
-        ramInFile.close();
-    }
-
-#ifndef ROUTED
-    template<typename EdgeT>
-    inline void ConstructGrid(DeallocatingVector<EdgeT> & edgeList, const char * ramIndexOut, const char * fileIndexOut) {
-    	//TODO: Implement this using STXXL-Streams
-        Percent p(edgeList.size());
-        BOOST_FOREACH(EdgeT & edge, edgeList) {
-            p.printIncrement();
-            if(edge.ignoreInGrid)
-                continue;
-            int slat = 100000*lat2y(edge.lat1/100000.);
-            int slon = edge.lon1;
-            int tlat = 100000*lat2y(edge.lat2/100000.);
-            int tlon = edge.lon2;
-            AddEdge( _GridEdge( edge.id, edge.nameID, edge.weight, _Coordinate(slat, slon), _Coordinate(tlat, tlon), edge.belongsToTinyComponent ) );
-        }
-        if( 0 == entries.size() ) {
-        	ERR("No viable edges for nearest neighbor index. Aborting");
-        }
-        double timestamp = get_timestamp();
-        //create index file on disk, old one is over written
-        indexOutFile.open(fileIndexOut, std::ios::out | std::ios::binary | std::ios::trunc);
-        //sort entries
-        stxxl::sort(entries.begin(), entries.end(), CompareGridEdgeDataByRamIndex(), 1024*1024*1024);
-        INFO("finished sorting after " << (get_timestamp() - timestamp) << "s");
-        std::vector<GridEntry> entriesInFileWithRAMSameIndex;
-        unsigned indexInRamTable = entries.begin()->ramIndex;
-        uint64_t lastPositionInIndexFile = 0;
-        std::cout << "writing data ..." << std::flush;
-        p.reinit(entries.size());
-        boost::unordered_map< unsigned, unsigned > cellMap(1024);
-        BOOST_FOREACH(GridEntry & gridEntry, entries) {
-            p.printIncrement();
-            if(gridEntry.ramIndex != indexInRamTable) {
-                cellMap.clear();
-                BuildCellIndexToFileIndexMap(indexInRamTable, cellMap);
-
-                unsigned numberOfBytesInCell = FillCell(entriesInFileWithRAMSameIndex, lastPositionInIndexFile, cellMap);
-                ramIndexTable[indexInRamTable] = lastPositionInIndexFile;
-                lastPositionInIndexFile += numberOfBytesInCell;
-                entriesInFileWithRAMSameIndex.clear();
-                indexInRamTable = gridEntry.ramIndex;
-            }
-            entriesInFileWithRAMSameIndex.push_back(gridEntry);
-        }
-        cellMap.clear();
-        BuildCellIndexToFileIndexMap(indexInRamTable, cellMap);
-        /*unsigned numberOfBytesInCell = */FillCell(entriesInFileWithRAMSameIndex, lastPositionInIndexFile, cellMap);
-        ramIndexTable[indexInRamTable] = lastPositionInIndexFile;
-        entriesInFileWithRAMSameIndex.clear();
-        std::vector<GridEntry>().swap(entriesInFileWithRAMSameIndex);
-        assert(entriesInFileWithRAMSameIndex.size() == 0);
-        //close index file
-        indexOutFile.close();
-
-        //Serialize RAM Index
-        std::ofstream ramFile(ramIndexOut, std::ios::out | std::ios::binary | std::ios::trunc);
-        //write 4 MB of index Table in RAM
-        ramFile.write((char *)&ramIndexTable[0], sizeof(uint64_t)*1024*1024 );
-        //close ram index file
-        ramFile.close();
-    }
-#endif
-    inline bool CoordinatesAreEquivalent(const _Coordinate & a, const _Coordinate & b, const _Coordinate & c, const _Coordinate & d) const {
-        return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
-    }
-
-    bool FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode, const unsigned zoomLevel) {
-        bool ignoreTinyComponents = (zoomLevel <= 14);
-//        INFO("Coordinate: " << location << ", zoomLevel: " << zoomLevel << ", ignoring tinyComponentents: " << (ignoreTinyComponents ? "yes" : "no"));
-//        double time1 = get_timestamp();
-        bool foundNode = false;
-        const _Coordinate startCoord(100000*(lat2y(static_cast<double>(location.lat)/100000.)), location.lon);
-        /** search for point on edge close to source */
-        const unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon);
-        std::vector<_GridEdge> candidates;
-        const int lowerBoundForLoop = (fileIndex < 32768 ? 0 : -32768);
-        for(int j = lowerBoundForLoop; (j < (32768+1)) && (fileIndex != UINT_MAX); j+=32768) {
-            for(int i = -1; i < 2; ++i){
-//                unsigned oldSize = candidates.size();
-                GetContentsOfFileBucketEnumerated(fileIndex+i+j, candidates);
-//                INFO("Getting fileIndex=" << fileIndex+i+j << " with " << candidates.size() - oldSize << " candidates");
-            }
-        }
-//        INFO("looked up " << candidates.size());
-        _GridEdge smallestEdge;
-        _Coordinate tmp, edgeStartCoord, edgeEndCoord;
-        double dist = std::numeric_limits<double>::max();
-        double r, tmpDist;
-
-        BOOST_FOREACH(const _GridEdge & candidate, candidates) {
-            if(candidate.belongsToTinyComponent && ignoreTinyComponents)
-                continue;
-            r = 0.;
-            tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r);
-//            INFO("dist " << startCoord << "->[" << candidate.startCoord << "-" << candidate.targetCoord << "]=" << tmpDist );
-//            INFO("Looking at edge " << candidate.edgeBasedNode << " at distance " << tmpDist);
-            if(tmpDist < dist && !DoubleEpsilonCompare(dist, tmpDist)) {
-//                INFO("a) " << candidate.edgeBasedNode << ", dist: " << tmpDist << ", tinyCC: " << (candidate.belongsToTinyComponent ? "yes" : "no"));
-                dist = tmpDist;
-                resultNode.edgeBasedNode = candidate.edgeBasedNode;
-                resultNode.nodeBasedEdgeNameID = candidate.nameID;
-                resultNode.weight1 = candidate.weight;
-                resultNode.weight2 = INT_MAX;
-                resultNode.location.lat = tmp.lat;
-                resultNode.location.lon = tmp.lon;
-                edgeStartCoord = candidate.startCoord;
-                edgeEndCoord = candidate.targetCoord;
-                foundNode = true;
-                smallestEdge = candidate;
-                //}  else if(tmpDist < dist) {
-                //INFO("a) ignored " << candidate.edgeBasedNode << " at distance " << std::fabs(dist - tmpDist));
-            } else if(DoubleEpsilonCompare(dist, tmpDist) && 1 == std::abs(static_cast<int>(candidate.edgeBasedNode)-static_cast<int>(resultNode.edgeBasedNode) )  && CoordinatesAreEquivalent(edgeStartCoord, candidate.startCoord, edgeEndCoord, candidate.targetCoord)) {
-                resultNode.edgeBasedNode = std::min(candidate.edgeBasedNode, resultNode.edgeBasedNode);
-                resultNode.weight2 = candidate.weight;
-                //INFO("b) " << candidate.edgeBasedNode << ", dist: " << tmpDist);
-            }
-        }
-
-        //        INFO("startcoord: " << smallestEdge.startCoord << ", tgtcoord" <<  smallestEdge.targetCoord << "result: " << newEndpoint);
-        //        INFO("length of old edge: " << ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord));
-        //        INFO("Length of new edge: " << ApproximateDistance(smallestEdge.startCoord, newEndpoint));
-        //        assert(!resultNode.isBidirected() || (resultNode.weight1 == resultNode.weight2));
-        //        if(resultNode.weight1 != resultNode.weight2) {
-        //            INFO("-> Weight1: " << resultNode.weight1 << ", weight2: " << resultNode.weight2);
-        //            INFO("-> node: " << resultNode.edgeBasedNode << ", bidir: " << (resultNode.isBidirected() ? "yes" : "no"));
-        //        }
-
-//        INFO("startCoord: " << smallestEdge.startCoord << "; targetCoord: " << smallestEdge.targetCoord << "; newEndpoint: " << resultNode.location);
-        const double ratio = (foundNode ? std::min(1., ApproximateDistance(smallestEdge.startCoord, resultNode.location)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord)) : 0);
-        resultNode.location.lat = round(100000.*(y2lat(static_cast<double>(resultNode.location.lat)/100000.)));
-//        INFO("Length of vector: " << ApproximateDistance(smallestEdge.startCoord, resultNode.location)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord));
-        //Hack to fix rounding errors and wandering via nodes.
-        if(std::abs(location.lon - resultNode.location.lon) == 1)
-            resultNode.location.lon = location.lon;
-        if(std::abs(location.lat - resultNode.location.lat) == 1)
-            resultNode.location.lat = location.lat;
-
-        resultNode.weight1 *= ratio;
-        if(INT_MAX != resultNode.weight2) {
-            resultNode.weight2 *= (1.-ratio);
-        }
-        resultNode.ratio = ratio;
-//        INFO("start: " << edgeStartCoord << ", end: " << edgeEndCoord);
-//        INFO("selected node: " << resultNode.edgeBasedNode << ", bidirected: " << (resultNode.isBidirected() ? "yes" : "no"));
-//        INFO("New weight1: " << resultNode.weight1 << ", new weight2: " << resultNode.weight2 << ", ratio: " << ratio);
- //       INFO("distance to input coordinate: " << ApproximateDistance(location, resultNode.location) <<  "\n--");
-//        double time2 = get_timestamp();
-//        INFO("NN-Lookup in " << 1000*(time2-time1) << "ms");
-        return foundNode;
-    }
-
-    bool FindRoutingStarts(const _Coordinate& start, const _Coordinate& target, PhantomNodes & routingStarts, unsigned zoomLevel) {
-        routingStarts.Reset();
-        return (FindPhantomNodeForCoordinate( start, routingStarts.startPhantom, zoomLevel) &&
-                FindPhantomNodeForCoordinate( target, routingStarts.targetPhantom, zoomLevel) );
-    }
-
-    bool FindNearestCoordinateOnEdgeInNodeBasedGraph(const _Coordinate& inputCoordinate, _Coordinate& outputCoordinate, unsigned zoomLevel = 18) {
-        PhantomNode resultNode;
-        bool foundNode = FindPhantomNodeForCoordinate(inputCoordinate, resultNode, zoomLevel);
-        outputCoordinate = resultNode.location;
-        return foundNode;
-    }
-
-    void FindNearestPointOnEdge(const _Coordinate& inputCoordinate, _Coordinate& outputCoordinate) {
-        _Coordinate startCoord(100000*(lat2y(static_cast<double>(inputCoordinate.lat)/100000.)), inputCoordinate.lon);
-        unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon);
-
-        std::vector<_GridEdge> candidates;
-        boost::unordered_map< unsigned, unsigned > cellMap;
-        for(int j = -32768; j < (32768+1); j+=32768) {
-            for(int i = -1; i < 2; ++i) {
-                GetContentsOfFileBucket(fileIndex+i+j, candidates, cellMap);
-            }
-        }
-        _Coordinate tmp;
-        double dist = (std::numeric_limits<double>::max)();
-        BOOST_FOREACH(const _GridEdge & candidate, candidates) {
-            double r = 0.;
-            double tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r);
-            if(tmpDist < dist) {
-                dist = tmpDist;
-                outputCoordinate.lat = round(100000*(y2lat(static_cast<double>(tmp.lat)/100000.)));
-                outputCoordinate.lon = tmp.lon;
-            }
-        }
-    }
-
-
-private:
-    inline unsigned GetCellIndexFromRAMAndFileIndex(const unsigned ramIndex, const unsigned fileIndex) const {
-        unsigned lineBase = ramIndex/1024;
-        lineBase = lineBase*32*32768;
-        unsigned columnBase = ramIndex%1024;
-        columnBase=columnBase*32;
-        for (int i = 0;i < 32;++i) {
-            for (int j = 0;j < 32;++j) {
-                const unsigned localFileIndex = lineBase + i * 32768 + columnBase + j;
-                if(localFileIndex == fileIndex) {
-                    unsigned cellIndex = i * 32 + j;
-                    return cellIndex;
-                }
-            }
-        }
-        return UINT_MAX;
-    }
-
-    inline void BuildCellIndexToFileIndexMap(const unsigned ramIndex, boost::unordered_map<unsigned, unsigned >& cellMap){
-        unsigned lineBase = ramIndex/1024;
-        lineBase = lineBase*32*32768;
-        unsigned columnBase = ramIndex%1024;
-        columnBase=columnBase*32;
-        std::vector<std::pair<unsigned, unsigned> >insertionVector(1024);
-        for (int i = 0;i < 32;++i) {
-            for (int j = 0;j < 32;++j) {
-                unsigned fileIndex = lineBase + i * 32768 + columnBase + j;
-                unsigned cellIndex = i * 32 + j;
-                insertionVector[i * 32 + j] = std::make_pair(fileIndex, cellIndex);
-            }
-        }
-        cellMap.insert(insertionVector.begin(), insertionVector.end());
-    }
-
-    inline bool DoubleEpsilonCompare(const double d1, const double d2) const {
-        return (std::fabs(d1 - d2) < FLT_EPSILON);
-    }
-
-#ifndef ROUTED
-    inline unsigned FillCell(std::vector<GridEntry>& entriesWithSameRAMIndex, const uint64_t fileOffset, boost::unordered_map< unsigned, unsigned > & cellMap ) {
-        std::vector<char> tmpBuffer(32*32*4096,0);
-        uint64_t indexIntoTmpBuffer = 0;
-        unsigned numberOfWrittenBytes = 0;
-        assert(indexOutFile.is_open());
-
-        std::vector<uint64_t> cellIndex(32*32,std::numeric_limits<uint64_t>::max());
-
-        for(unsigned i = 0; i < entriesWithSameRAMIndex.size() -1; ++i) {
-            assert(entriesWithSameRAMIndex[i].ramIndex== entriesWithSameRAMIndex[i+1].ramIndex);
-        }
-
-        //sort & unique
-        std::sort(entriesWithSameRAMIndex.begin(), entriesWithSameRAMIndex.end(), CompareGridEdgeDataByFileIndex());
-//        entriesWithSameRAMIndex.erase(std::unique(entriesWithSameRAMIndex.begin(), entriesWithSameRAMIndex.end()), entriesWithSameRAMIndex.end());
-
-        //traverse each file bucket and write its contents to disk
-        std::vector<GridEntry> entriesWithSameFileIndex;
-        unsigned fileIndex = entriesWithSameRAMIndex.begin()->fileIndex;
-
-        BOOST_FOREACH(GridEntry & gridEntry, entriesWithSameRAMIndex) {
-            assert(cellMap.find(gridEntry.fileIndex) != cellMap.end() ); //asserting that file index belongs to cell index
-            if(gridEntry.fileIndex != fileIndex) {
-                // start in cellIndex vermerken
-                int localFileIndex = entriesWithSameFileIndex.begin()->fileIndex;
-                int localCellIndex = cellMap.find(localFileIndex)->second;
-                assert(cellMap.find(entriesWithSameFileIndex.begin()->fileIndex) != cellMap.end());
-
-                cellIndex[localCellIndex] = indexIntoTmpBuffer + fileOffset;
-                indexIntoTmpBuffer += FlushEntriesWithSameFileIndexToBuffer(entriesWithSameFileIndex, tmpBuffer, indexIntoTmpBuffer);
-                fileIndex = gridEntry.fileIndex;
-            }
-            entriesWithSameFileIndex.push_back(gridEntry);
-        }
-        assert(cellMap.find(entriesWithSameFileIndex.begin()->fileIndex) != cellMap.end());
-        int localFileIndex = entriesWithSameFileIndex.begin()->fileIndex;
-        int localCellIndex = cellMap.find(localFileIndex)->second;
-
-        cellIndex[localCellIndex] = indexIntoTmpBuffer + fileOffset;
-        indexIntoTmpBuffer += FlushEntriesWithSameFileIndexToBuffer(entriesWithSameFileIndex, tmpBuffer, indexIntoTmpBuffer);
-
-        assert(entriesWithSameFileIndex.size() == 0);
-        indexOutFile.write(static_cast<char*>(static_cast<void*>(&cellIndex[0])),32*32*sizeof(uint64_t));
-        numberOfWrittenBytes += 32*32*sizeof(uint64_t);
-
-        //write contents of tmpbuffer to disk
-        indexOutFile.write(&tmpBuffer[0], indexIntoTmpBuffer*sizeof(char));
-        numberOfWrittenBytes += indexIntoTmpBuffer*sizeof(char);
-
-        return numberOfWrittenBytes;
-    }
-
-    inline unsigned FlushEntriesWithSameFileIndexToBuffer( std::vector<GridEntry> &vectorWithSameFileIndex, std::vector<char> & tmpBuffer, const uint64_t index) const {
-        sort( vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end() );
-        vectorWithSameFileIndex.erase(unique(vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end()), vectorWithSameFileIndex.end());
-        const unsigned lengthOfBucket = vectorWithSameFileIndex.size();
-        tmpBuffer.resize(tmpBuffer.size()+(sizeof(_GridEdge)*lengthOfBucket) + sizeof(unsigned) );
-        unsigned counter = 0;
-
-        for(unsigned i = 0; i < vectorWithSameFileIndex.size()-1; ++i) {
-            assert( vectorWithSameFileIndex[i].fileIndex == vectorWithSameFileIndex[i+1].fileIndex );
-            assert( vectorWithSameFileIndex[i].ramIndex == vectorWithSameFileIndex[i+1].ramIndex );
-        }
-
-        //write length of bucket
-        memcpy((char*)&(tmpBuffer[index+counter]), (char*)&lengthOfBucket, sizeof(lengthOfBucket));
-        counter += sizeof(lengthOfBucket);
-
-        BOOST_FOREACH(const GridEntry & entry, vectorWithSameFileIndex) {
-            char * data = (char*)&(entry.edge);
-            memcpy(static_cast<char*>(static_cast<void*>(&(tmpBuffer[index+counter]) )), data, sizeof(entry.edge));
-            counter += sizeof(entry.edge);
-        }
-        //Freeing data
-        vectorWithSameFileIndex.clear();
-        return counter;
-    }
-#endif
-
-    inline void GetContentsOfFileBucketEnumerated(const unsigned fileIndex, std::vector<_GridEdge>& result) const {
-        unsigned ramIndex = GetRAMIndexFromFileIndex(fileIndex);
-        uint64_t startIndexInFile = ramIndexTable[ramIndex];
-        if(startIndexInFile == std::numeric_limits<uint64_t>::max()) {
-            return;
-        }
-        unsigned enumeratedIndex = GetCellIndexFromRAMAndFileIndex(ramIndex, fileIndex);
-
-        if(!localStream.get() || !localStream->is_open()) {
-            localStream.reset(new std::ifstream(iif.c_str(), std::ios::in | std::ios::binary));
-        }
-        if(!localStream->good()) {
-            localStream->clear(std::ios::goodbit);
-            DEBUG("Resetting stale filestream");
-        }
-
-        //only read the single necessary cell index
-        localStream->seekg(startIndexInFile+(enumeratedIndex*sizeof(uint64_t)));
-        uint64_t fetchedIndex = 0;
-        localStream->read(static_cast<char*>( static_cast<void*>(&fetchedIndex)), sizeof(uint64_t));
-
-        if(fetchedIndex == std::numeric_limits<uint64_t>::max()) {
-            return;
-        }
-        const uint64_t position = fetchedIndex + 32*32*sizeof(uint64_t) ;
-
-        unsigned lengthOfBucket;
-        unsigned currentSizeOfResult = result.size();
-        localStream->seekg(position);
-        localStream->read(static_cast<char*>( static_cast<void*>(&(lengthOfBucket))), sizeof(unsigned));
-        result.resize(currentSizeOfResult+lengthOfBucket);
-        localStream->read(static_cast<char*>( static_cast<void*>(&result[currentSizeOfResult])), lengthOfBucket*sizeof(_GridEdge));
-    }
-
-    inline void GetContentsOfFileBucket(const unsigned fileIndex, std::vector<_GridEdge>& result, boost::unordered_map< unsigned, unsigned> & cellMap) {
-        unsigned ramIndex = GetRAMIndexFromFileIndex(fileIndex);
-        uint64_t startIndexInFile = ramIndexTable[ramIndex];
-        if(startIndexInFile == std::numeric_limits<uint64_t>::max()) {
-            return;
-        }
-
-        uint64_t cellIndex[32*32];
-
-        cellMap.clear();
-        BuildCellIndexToFileIndexMap(ramIndex,  cellMap);
-        if(!localStream.get() || !localStream->is_open()) {
-            localStream.reset(new std::ifstream(iif.c_str(), std::ios::in | std::ios::binary));
-        }
-        if(!localStream->good()) {
-            localStream->clear(std::ios::goodbit);
-            DEBUG("Resetting stale filestream");
-        }
-
-        localStream->seekg(startIndexInFile);
-        localStream->read(static_cast<char*>(static_cast<void*>( cellIndex)), 32*32*sizeof(uint64_t));
-        assert(cellMap.find(fileIndex) != cellMap.end());
-        if(cellIndex[cellMap[fileIndex]] == std::numeric_limits<uint64_t>::max()) {
-            return;
-        }
-        const uint64_t position = cellIndex[cellMap[fileIndex]] + 32*32*sizeof(uint64_t) ;
-
-        unsigned lengthOfBucket;
-        unsigned currentSizeOfResult = result.size();
-        localStream->seekg(position);
-        localStream->read(static_cast<char*>(static_cast<void*>(&(lengthOfBucket))), sizeof(unsigned));
-        result.resize(currentSizeOfResult+lengthOfBucket);
-        localStream->read(static_cast<char*>(static_cast<void*>(&result[currentSizeOfResult])), lengthOfBucket*sizeof(_GridEdge));
-    }
-
-#ifndef ROUTED
-    inline void AddEdge(const _GridEdge & edge) {
-        std::vector<BresenhamPixel> indexList;
-        GetListOfIndexesForEdgeAndGridSize(edge.startCoord, edge.targetCoord, indexList);
-        for(unsigned i = 0; i < indexList.size(); ++i) {
-            entries.push_back(GridEntry(edge, indexList[i].first, indexList[i].second));
-        }
-    }
-#endif
-
-    inline double ComputeDistance(const _Coordinate& inputPoint, const _Coordinate& source, const _Coordinate& target, _Coordinate& nearest, double *r) {
-//        INFO("comparing point " << inputPoint << " to edge [" << source << "-" << target << "]");
-        const double x = static_cast<double>(inputPoint.lat);
-        const double y = static_cast<double>(inputPoint.lon);
-        const double a = static_cast<double>(source.lat);
-        const double b = static_cast<double>(source.lon);
-        const double c = static_cast<double>(target.lat);
-        const double d = static_cast<double>(target.lon);
-        double p,q,mX,nY;
-//        INFO("x=" << x << ", y=" << y << ", a=" << a << ", b=" << b << ", c=" << c << ", d=" << d);
-        if(fabs(a-c) > FLT_EPSILON){
-            const double m = (d-b)/(c-a); // slope
-            // Projection of (x,y) on line joining (a,b) and (c,d)
-            p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
-            q = b + m*(p - a);
-        }
-        else{
-            p = c;
-            q = y;
-        }
-        nY = (d*p - c*q)/(a*d - b*c);
-        mX = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we neednot calculate the values of m an n as we are just interested in the ratio
-//        INFO("p=" << p << ", q=" << q << ", nY=" << nY << ", mX=" << mX);
-        if(std::isnan(mX)) {
-            *r = (target == inputPoint) ? 1. : 0.;
-        } else {
-            *r = mX;
-        }
-//        INFO("r=" << *r);
-        if(*r<=0.){
-            nearest.lat = source.lat;
-            nearest.lon = source.lon;
-//            INFO("a returning distance " << ((b - y)*(b - y) + (a - x)*(a - x)))
-            return ((b - y)*(b - y) + (a - x)*(a - x));
-        }
-        else if(*r >= 1.){
-            nearest.lat = target.lat;
-            nearest.lon = target.lon;
-//            INFO("b returning distance " << ((d - y)*(d - y) + (c - x)*(c - x)))
-
-            return ((d - y)*(d - y) + (c - x)*(c - x));
-        }
-        // point lies in between
-        nearest.lat = p;
-        nearest.lon = q;
-//        INFO("c returning distance " << (p-x)*(p-x) + (q-y)*(q-y))
-
-        return (p-x)*(p-x) + (q-y)*(q-y);
-    }
-
-    inline void GetListOfIndexesForEdgeAndGridSize(const _Coordinate& start, const _Coordinate& target, std::vector<BresenhamPixel> &indexList) const {
-        double lat1 = start.lat/100000.;
-        double lon1 = start.lon/100000.;
-
-        double x1 = ( lon1 + 180.0 ) / 360.0;
-        double y1 = ( lat1 + 180.0 ) / 360.0;
-
-        double lat2 = target.lat/100000.;
-        double lon2 = target.lon/100000.;
-
-        double x2 = ( lon2 + 180.0 ) / 360.0;
-        double y2 = ( lat2 + 180.0 ) / 360.0;
-
-        Bresenham(x1*32768, y1*32768, x2*32768, y2*32768, indexList);
-        BOOST_FOREACH(BresenhamPixel & pixel, indexList) {
-            int fileIndex = (pixel.second-1)*32768 + pixel.first;
-            int ramIndex = GetRAMIndexFromFileIndex(fileIndex);
-            pixel.first = fileIndex;
-            pixel.second = ramIndex;
-        }
-    }
-
-    inline unsigned GetFileIndexForLatLon(const int lt, const int ln) const {
-        double lat = lt/100000.;
-        double lon = ln/100000.;
-
-        double x = ( lon + 180.0 ) / 360.0;
-        double y = ( lat + 180.0 ) / 360.0;
-
-        if( x>1.0 || x < 0.)
-            return UINT_MAX;
-        if( y>1.0 || y < 0.)
-            return UINT_MAX;
-
-        unsigned line = (32768 * (32768-1))*y;
-        line = line - (line % 32768);
-        assert(line % 32768 == 0);
-        unsigned column = 32768.*x;
-        unsigned fileIndex = line+column;
-        return fileIndex;
-    }
-
-    inline unsigned GetRAMIndexFromFileIndex(const int fileIndex) const {
-        unsigned fileLine = fileIndex / 32768;
-        fileLine = fileLine / 32;
-        fileLine = fileLine * 1024;
-        unsigned fileColumn = (fileIndex % 32768);
-        fileColumn = fileColumn / 32;
-        unsigned ramIndex = fileLine + fileColumn;
-        assert(ramIndex < 1024*1024);
-        return ramIndex;
-    }
-
-    const static uint64_t END_OF_BUCKET_DELIMITER = boost::integer_traits<uint64_t>::const_max;
-
-    std::ifstream ramInFile;
-#ifndef ROUTED
-    std::ofstream indexOutFile;
-    stxxl::vector<GridEntry> entries;
-#endif
-    std::vector<uint64_t> ramIndexTable; //8 MB for first level index in RAM
-    std::string iif;
-    //    LRUCache<int,std::vector<unsigned> > cellCache;
-    //    LRUCache<int,std::vector<_Edge> > fileCache;
-};
-}
-
-typedef NNGrid::NNGrid<false> ReadOnlyGrid;
-typedef NNGrid::NNGrid<true > WritableGrid;
-
-#endif /* NNGRID_H_ */
diff --git a/DataStructures/NodeBasedGraph.h b/DataStructures/NodeBasedGraph.h
new file mode 100644
index 0000000..98393fb
--- /dev/null
+++ b/DataStructures/NodeBasedGraph.h
@@ -0,0 +1,166 @@
+#ifndef __NODE_BASED_GRAPH_H__
+#define __NODE_BASED_GRAPH_H__
+
+#include "DynamicGraph.h"
+#include "ImportEdge.h"
+#include "../Util/SimpleLogger.h"
+
+#include <tbb/parallel_sort.h>
+
+#include <memory>
+
+struct NodeBasedEdgeData
+{
+    NodeBasedEdgeData()
+        : distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID),
+          nameID(std::numeric_limits<unsigned>::max()), type(std::numeric_limits<short>::max()),
+          isAccessRestricted(false), shortcut(false), forward(false), backward(false),
+          roundabout(false), ignore_in_grid(false), contraFlow(false)
+    {
+    }
+
+    int distance;
+    unsigned edgeBasedNodeID;
+    unsigned nameID;
+    short type;
+    bool isAccessRestricted : 1;
+    bool shortcut : 1;
+    bool forward : 1;
+    bool backward : 1;
+    bool roundabout : 1;
+    bool ignore_in_grid : 1;
+    bool contraFlow : 1;
+
+    void SwapDirectionFlags()
+    {
+        bool temp_flag = forward;
+        forward = backward;
+        backward = temp_flag;
+    }
+
+    bool IsEqualTo(const NodeBasedEdgeData &other) const
+    {
+        return (forward == other.forward) && (backward == other.backward) &&
+               (nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) &&
+               (contraFlow == other.contraFlow);
+    }
+};
+
+typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
+
+// Factory method to create NodeBasedDynamicGraph from ImportEdges
+inline std::shared_ptr<NodeBasedDynamicGraph>
+NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge> &input_edge_list)
+{
+    static_assert(sizeof(NodeBasedEdgeData) == 16, "changing node based edge data size changes memory consumption");
+    // tbb::parallel_sort(input_edge_list.begin(), input_edge_list.end());
+
+    DeallocatingVector<NodeBasedDynamicGraph::InputEdge> edges_list;
+    NodeBasedDynamicGraph::InputEdge edge;
+    for (const ImportEdge &import_edge : input_edge_list)
+    {
+        if (import_edge.forward)
+        {
+            edge.source = import_edge.source;
+            edge.target = import_edge.target;
+            edge.data.forward = import_edge.forward;
+            edge.data.backward = import_edge.backward;
+        }
+        else
+        {
+            edge.source = import_edge.target;
+            edge.target = import_edge.source;
+            edge.data.backward = import_edge.forward;
+            edge.data.forward = import_edge.backward;
+        }
+
+        if (edge.source == edge.target)
+        {
+            continue;
+        }
+
+        edge.data.distance = (std::max)((int)import_edge.weight, 1);
+        BOOST_ASSERT(edge.data.distance > 0);
+        edge.data.shortcut = false;
+        edge.data.roundabout = import_edge.roundabout;
+        edge.data.ignore_in_grid = import_edge.in_tiny_cc;
+        edge.data.nameID = import_edge.name_id;
+        edge.data.type = import_edge.type;
+        edge.data.isAccessRestricted = import_edge.access_restricted;
+        edge.data.contraFlow = import_edge.contra_flow;
+        edges_list.push_back(edge);
+
+        if (!import_edge.is_split)
+        {
+            using std::swap; // enable ADL
+            swap(edge.source, edge.target);
+            edge.data.SwapDirectionFlags();
+            edges_list.push_back(edge);
+        }
+    }
+
+    // remove duplicate edges
+    std::sort(edges_list.begin(), edges_list.end());
+    NodeID edge_count = 0;
+    for (NodeID i = 0; i < edges_list.size(); )
+    {
+        const NodeID source = edges_list[i].source;
+        const NodeID target = edges_list[i].target;
+        // remove eigenloops
+        if (source == target)
+        {
+            i++;
+            continue;
+        }
+        NodeBasedDynamicGraph::InputEdge forward_edge;
+        NodeBasedDynamicGraph::InputEdge reverse_edge;
+        forward_edge = reverse_edge = edges_list[i];
+        forward_edge.data.forward = reverse_edge.data.backward = true;
+        forward_edge.data.backward = reverse_edge.data.forward = false;
+        forward_edge.data.shortcut = reverse_edge.data.shortcut = false;
+        forward_edge.data.distance = reverse_edge.data.distance =
+            std::numeric_limits<int>::max();
+        // remove parallel edges
+        while (i < edges_list.size() && edges_list[i].source == source && edges_list[i].target == target)
+        {
+            if (edges_list[i].data.forward)
+            {
+                forward_edge.data.distance =
+                    std::min(edges_list[i].data.distance, forward_edge.data.distance);
+            }
+            if (edges_list[i].data.backward)
+            {
+                reverse_edge.data.distance =
+                    std::min(edges_list[i].data.distance, reverse_edge.data.distance);
+            }
+            ++i;
+        }
+        // merge edges (s,t) and (t,s) into bidirectional edge
+        if (forward_edge.data.distance == reverse_edge.data.distance)
+        {
+            if ((int)forward_edge.data.distance != std::numeric_limits<int>::max())
+            {
+                forward_edge.data.backward = true;
+                edges_list[edge_count++] = forward_edge;
+            }
+        }
+        else
+        { // insert seperate edges
+            if (((int)forward_edge.data.distance) != std::numeric_limits<int>::max())
+            {
+                edges_list[edge_count++] = forward_edge;
+            }
+            if ((int)reverse_edge.data.distance != std::numeric_limits<int>::max())
+            {
+                edges_list[edge_count++] = reverse_edge;
+            }
+        }
+    }
+    edges_list.resize(edge_count);
+    SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of " << edges_list.size();
+
+    auto graph = std::make_shared<NodeBasedDynamicGraph>(number_of_nodes, edges_list);
+    return graph;
+}
+
+#endif // __NODE_BASED_GRAPH_H__
diff --git a/DataStructures/NodeCoords.h b/DataStructures/NodeCoords.h
deleted file mode 100644
index 4893a9d..0000000
--- a/DataStructures/NodeCoords.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef _NODE_COORDS_H
-#define _NODE_COORDS_H
-
-#include <cassert>
-#include <cstddef>
-#include <climits>
-#include <limits>
-
-#include "../typedefs.h"
-
-template<typename NodeT>
-struct NodeCoords {
-	typedef unsigned key_type; 	//type of NodeID
-	typedef int value_type;		//type of lat,lons
-
-	NodeCoords(int _lat, int _lon, NodeT _id) : lat(_lat), lon(_lon), id(_id) {}
-	NodeCoords() : lat(INT_MAX), lon(INT_MAX), id(UINT_MAX) {}
-	int lat;
-	int lon;
-	NodeT id;
-
-	static NodeCoords<NodeT> min_value() {
-		return NodeCoords<NodeT>(-90*100000,-180*100000,std::numeric_limits<NodeT>::min());
-	}
-	static NodeCoords<NodeT> max_value() {
-		return NodeCoords<NodeT>(90*100000, 180*100000, std::numeric_limits<NodeT>::max());
-	}
-
-	value_type operator[](std::size_t n) const {
-		switch(n) {
-		case 1:
-			return lat;
-			break;
-		case 0:
-			return lon;
-			break;
-		default:
-			assert(false);
-			return UINT_MAX;
-			break;
-		}
-		assert(false);
-		return UINT_MAX;
-	}
-};
-
-typedef NodeCoords<NodeID> NodeInfo;
-
-#endif //_NODE_COORDS_H
diff --git a/DataStructures/NodeInformationHelpDesk.h b/DataStructures/NodeInformationHelpDesk.h
deleted file mode 100644
index f13c9ad..0000000
--- a/DataStructures/NodeInformationHelpDesk.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef NODEINFORMATIONHELPDESK_H_
-#define NODEINFORMATIONHELPDESK_H_
-
-#include "NodeCoords.h"
-#include "PhantomNodes.h"
-#include "QueryEdge.h"
-#include "StaticRTree.h"
-#include "../Contractor/EdgeBasedGraphFactory.h"
-#include "../typedefs.h"
-
-#include <boost/assert.hpp>
-#include <boost/noncopyable.hpp>
-
-#include <fstream>
-
-#include <iostream>
-#include <vector>
-
-typedef EdgeBasedGraphFactory::EdgeBasedNode RTreeLeaf;
-
-class NodeInformationHelpDesk : boost::noncopyable{
-public:
-    NodeInformationHelpDesk(
-        const char* ramIndexInput,
-        const char* fileIndexInput,
-        const unsigned number_of_nodes,
-        const unsigned crc) : number_of_nodes(number_of_nodes), checkSum(crc) {
-        read_only_rtree = new StaticRTree<RTreeLeaf>(
-            ramIndexInput,
-            fileIndexInput
-        );
-        BOOST_ASSERT_MSG(
-            0 == coordinateVector.size(),
-            "Coordinate vector not empty"
-        );
-    }
-
-    //Todo: Shared memory mechanism
-	~NodeInformationHelpDesk() {
-		delete read_only_rtree;
-	}
-
-	void initNNGrid(
-        std::ifstream& nodesInstream,
-        std::ifstream& edgesInStream
-    ) {
-	    DEBUG("Loading node data");
-		NodeInfo b;
-	    while(!nodesInstream.eof()) {
-			nodesInstream.read((char *)&b, sizeof(NodeInfo));
-			coordinateVector.push_back(_Coordinate(b.lat, b.lon));
-		}
-	    std::vector<_Coordinate>(coordinateVector).swap(coordinateVector);
-	    nodesInstream.close();
-
-        DEBUG("Loading edge data");
-        unsigned numberOfOrigEdges(0);
-        edgesInStream.read((char*)&numberOfOrigEdges, sizeof(unsigned));
-        origEdgeData_viaNode.resize(numberOfOrigEdges);
-        origEdgeData_nameID.resize(numberOfOrigEdges);
-        origEdgeData_turnInstruction.resize(numberOfOrigEdges);
-
-        OriginalEdgeData deserialized_originalEdgeData;
-        for(unsigned i = 0; i < numberOfOrigEdges; ++i) {
-        	edgesInStream.read((char*)&(deserialized_originalEdgeData), sizeof(OriginalEdgeData));
-            origEdgeData_viaNode[i] = deserialized_originalEdgeData.viaNode;
-            origEdgeData_nameID[i] 	= deserialized_originalEdgeData.nameID;
-            origEdgeData_turnInstruction[i] = deserialized_originalEdgeData.turnInstruction;
-        }
-        edgesInStream.close();
-        DEBUG("Loaded " << numberOfOrigEdges << " orig edges");
-	    DEBUG("Opening NN indices");
-	}
-
-	inline int getLatitudeOfNode(const unsigned id) const {
-	    const NodeID node = origEdgeData_viaNode.at(id);
-	    return coordinateVector.at(node).lat;
-	}
-
-	inline int getLongitudeOfNode(const unsigned id) const {
-        const NodeID node = origEdgeData_viaNode.at(id);
-	    return coordinateVector.at(node).lon;
-	}
-
-	inline unsigned getNameIndexFromEdgeID(const unsigned id) const {
-	    return origEdgeData_nameID.at(id);
-	}
-
-    inline TurnInstruction getTurnInstructionFromEdgeID(const unsigned id) const {
-        return origEdgeData_turnInstruction.at(id);
-    }
-
-    inline NodeID getNumberOfNodes() const {
-        return number_of_nodes;
-    }
-
-	inline NodeID getNumberOfNodes2() const {
-        return coordinateVector.size();
-    }
-
-    inline bool FindNearestNodeCoordForLatLon(
-            const _Coordinate& input_coordinate,
-            _Coordinate& result,
-            const unsigned zoom_level = 18
-    ) const {
-        PhantomNode resulting_phantom_node;
-        bool foundNode = FindPhantomNodeForCoordinate(input_coordinate, resulting_phantom_node, zoom_level);
-        result = resulting_phantom_node.location;
-        return foundNode;
-    }
-
-    inline bool FindPhantomNodeForCoordinate(
-            const _Coordinate & input_coordinate,
-            PhantomNode & resulting_phantom_node,
-            const unsigned zoom_level
-    ) const {
-        return read_only_rtree->FindPhantomNodeForCoordinate(
-                input_coordinate,
-                resulting_phantom_node,
-                zoom_level
-        );
-    }
-
-	inline unsigned GetCheckSum() const {
-	    return checkSum;
-	}
-
-private:
-	std::vector<_Coordinate> coordinateVector;
-	std::vector<NodeID> origEdgeData_viaNode;
-	std::vector<unsigned> origEdgeData_nameID;
-	std::vector<TurnInstruction> origEdgeData_turnInstruction;
-
-	StaticRTree<EdgeBasedGraphFactory::EdgeBasedNode> * read_only_rtree;
-	const unsigned number_of_nodes;
-	const unsigned checkSum;
-};
-
-#endif /*NODEINFORMATIONHELPDESK_H_*/
diff --git a/DataStructures/OriginalEdgeData.h b/DataStructures/OriginalEdgeData.h
new file mode 100644
index 0000000..f75aeda
--- /dev/null
+++ b/DataStructures/OriginalEdgeData.h
@@ -0,0 +1,60 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef ORIGINAL_EDGE_DATA_H
+#define ORIGINAL_EDGE_DATA_H
+
+#include "TurnInstructions.h"
+#include "../typedefs.h"
+
+#include <limits>
+
+struct OriginalEdgeData
+{
+    explicit OriginalEdgeData(NodeID via_node,
+                              unsigned name_id,
+                              TurnInstruction turn_instruction,
+                              bool compressed_geometry)
+        : via_node(via_node), name_id(name_id), turn_instruction(turn_instruction),
+          compressed_geometry(compressed_geometry)
+    {
+    }
+
+    OriginalEdgeData()
+        : via_node(std::numeric_limits<unsigned>::max()),
+          name_id(std::numeric_limits<unsigned>::max()),
+          turn_instruction(TurnInstruction::NoTurn), compressed_geometry(false)
+    {
+    }
+
+    NodeID via_node;
+    unsigned name_id;
+    TurnInstruction turn_instruction;
+    bool compressed_geometry;
+};
+
+#endif // ORIGINAL_EDGE_DATA_H
diff --git a/DataStructures/Percent.h b/DataStructures/Percent.h
index dafbe55..f201fc8 100644
--- a/DataStructures/Percent.h
+++ b/DataStructures/Percent.h
@@ -1,89 +1,96 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef PERCENT_H
 #define PERCENT_H
 
 #include <iostream>
-
+#include <atomic>
 
 class Percent
 {
-public:
-    /**
-     * Constructor.
-     * @param maxValue the value that corresponds to 100%
-     * @param step the progress is shown in steps of 'step' percent
-     */
-    Percent(unsigned maxValue, unsigned step = 5) {
-        reinit(maxValue, step);
-    }
+  public:
+    explicit Percent(unsigned max_value, unsigned step = 5) { reinit(max_value, step); }
 
-    /** Reinitializes this object. */
-    void reinit(unsigned maxValue, unsigned step = 5) {
-        _maxValue = maxValue;
-        _current_value = 0;
-        _intervalPercent = _maxValue / 100;
-        _nextThreshold = _intervalPercent;
-        _lastPercent = 0;
-        _step = step;
+   // Reinitializes
+    void reinit(unsigned max_value, unsigned step = 5)
+    {
+        m_max_value = max_value;
+        m_current_value = 0;
+        m_percent_interval = m_max_value / 100;
+        m_next_threshold = m_percent_interval;
+        m_last_percent = 0;
+        m_step = step;
     }
 
-    /** If there has been significant progress, display it. */
-    void printStatus(unsigned currentValue) {
-        if (currentValue >= _nextThreshold) {
-            _nextThreshold += _intervalPercent;
-            printPercent( currentValue / (double)_maxValue * 100 );
+    // If there has been significant progress, display it.
+    void printStatus(unsigned current_value)
+    {
+        if (current_value >= m_next_threshold)
+        {
+            m_next_threshold += m_percent_interval;
+            printPercent(current_value / (double)m_max_value * 100);
         }
-        if (currentValue + 1 == _maxValue)
+        if (current_value + 1 == m_max_value)
             std::cout << " 100%" << std::endl;
     }
 
     void printIncrement()
     {
-#pragma omp atomic
-        ++_current_value;
-        printStatus(_current_value);
+        ++m_current_value;
+        printStatus(m_current_value);
     }
 
-    void printAddition(const unsigned addition) {
-#pragma omp atomic
-        _current_value += addition;
-        printStatus(_current_value);
+    void printAddition(const unsigned addition)
+    {
+        m_current_value += addition;
+        printStatus(m_current_value);
     }
-private:
-    unsigned _current_value;
-    unsigned _maxValue;
-    unsigned _intervalPercent;
-    unsigned _nextThreshold;
-    unsigned _lastPercent;
-    unsigned _step;
 
-    /** Displays the new progress. */
-    void printPercent(double percent) {
-        while (percent >= _lastPercent+_step) {
-            _lastPercent+=_step;
-            if (_lastPercent % 10 == 0) {
-                std::cout << " " << _lastPercent << "% ";
+  private:
+    std::atomic_uint m_current_value;
+    unsigned m_max_value;
+    unsigned m_percent_interval;
+    unsigned m_next_threshold;
+    unsigned m_last_percent;
+    unsigned m_step;
+
+    // Displays progress.
+    void printPercent(double percent)
+    {
+        while (percent >= m_last_percent + m_step)
+        {
+            m_last_percent += m_step;
+            if (m_last_percent % 10 == 0)
+            {
+                std::cout << " " << m_last_percent << "% ";
             }
-            else {
+            else
+            {
                 std::cout << ".";
             }
             std::cout.flush();
diff --git a/DataStructures/PhantomNodes.h b/DataStructures/PhantomNodes.h
index 2827d7a..2a2a924 100644
--- a/DataStructures/PhantomNodes.h
+++ b/DataStructures/PhantomNodes.h
@@ -1,94 +1,173 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef PHANTOMNODES_H_
-#define PHANTOMNODES_H_
-
-#include "Coordinate.h"
-
-struct PhantomNode {
-    PhantomNode() : edgeBasedNode(UINT_MAX), nodeBasedEdgeNameID(UINT_MAX), weight1(INT_MAX), weight2(INT_MAX), ratio(0.) {}
-    NodeID edgeBasedNode;
-    unsigned nodeBasedEdgeNameID;
-    int weight1;
-    int weight2;
-    double ratio;
-    _Coordinate location;
-    void Reset() {
-        edgeBasedNode = UINT_MAX;
-        nodeBasedEdgeNameID = UINT_MAX;
-        weight1 = INT_MAX;
-        weight2 = INT_MAX;
-        ratio = 0.;
-        location.Reset();
-    }
-    bool isBidirected() const {
-        return weight2 != INT_MAX;
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef PHANTOM_NODES_H
+#define PHANTOM_NODES_H
+
+#include <osrm/Coordinate.h>
+#include "../Util/SimpleLogger.h"
+#include "../typedefs.h"
+
+#include <vector>
+
+struct PhantomNode
+{
+    PhantomNode(NodeID forward_node_id, NodeID reverse_node_id, unsigned name_id,
+                int forward_weight, int reverse_weight, int forward_offset, int reverse_offset,
+                unsigned packed_geometry_id, FixedPointCoordinate &location,
+                unsigned short fwd_segment_position) :
+        forward_node_id(forward_node_id),
+        reverse_node_id(reverse_node_id),
+        name_id(name_id),
+        forward_weight(forward_weight),
+        reverse_weight(reverse_weight),
+        forward_offset(forward_offset),
+        reverse_offset(reverse_offset),
+        packed_geometry_id(packed_geometry_id),
+        location(location),
+        fwd_segment_position(fwd_segment_position)
+    { }
+
+    PhantomNode() :
+        forward_node_id(SPECIAL_NODEID),
+        reverse_node_id(SPECIAL_NODEID),
+        name_id(std::numeric_limits<unsigned>::max()),
+        forward_weight(INVALID_EDGE_WEIGHT),
+        reverse_weight(INVALID_EDGE_WEIGHT),
+        forward_offset(0),
+        reverse_offset(0),
+        packed_geometry_id(SPECIAL_EDGEID),
+        fwd_segment_position(0)
+    { }
+
+    NodeID forward_node_id;
+    NodeID reverse_node_id;
+    unsigned name_id;
+    int forward_weight;
+    int reverse_weight;
+    int forward_offset;
+    int reverse_offset;
+    unsigned packed_geometry_id;
+    FixedPointCoordinate location;
+    unsigned short fwd_segment_position;
+
+    int GetForwardWeightPlusOffset() const
+    {
+        if (SPECIAL_NODEID == forward_node_id)
+        {
+            return 0;
+        }
+        const int result = (forward_offset + forward_weight);
+        return result;
     }
-    bool isValid(const unsigned numberOfNodes) const {
-        return location.isValid() && (edgeBasedNode < numberOfNodes) && (weight1 != INT_MAX) && (ratio >= 0.) && (ratio <= 1.) && (nodeBasedEdgeNameID != UINT_MAX);
+
+    int GetReverseWeightPlusOffset() const
+    {
+        if (SPECIAL_NODEID == reverse_node_id)
+        {
+            return 0;
+        }
+        const int result = (reverse_offset + reverse_weight);
+        return result;
     }
 
-    bool operator==(const PhantomNode & other) const {
-        return location == other.location;
+    bool isBidirected() const
+    {
+        return (forward_node_id != SPECIAL_NODEID) &&
+               (reverse_node_id != SPECIAL_NODEID);
     }
-};
 
-struct PhantomNodes {
-    PhantomNode startPhantom;
-    PhantomNode targetPhantom;
-    void Reset() {
-        startPhantom.Reset();
-        targetPhantom.Reset();
+    bool IsCompressed() const
+    {
+        return (forward_offset != 0) || (reverse_offset != 0);
     }
 
-    bool PhantomsAreOnSameNodeBasedEdge() const {
-        return (startPhantom.edgeBasedNode == targetPhantom.edgeBasedNode);
+    bool isValid(const unsigned numberOfNodes) const
+    {
+        return
+            location.isValid() &&
+            (
+                (forward_node_id < numberOfNodes) ||
+                (reverse_node_id < numberOfNodes)
+            ) &&
+            (
+                (forward_weight != INVALID_EDGE_WEIGHT) ||
+                (reverse_weight != INVALID_EDGE_WEIGHT)
+            ) &&
+            (name_id != std::numeric_limits<unsigned>::max()
+        );
     }
 
-    bool AtLeastOnePhantomNodeIsUINTMAX() const {
-        return !(startPhantom.edgeBasedNode == UINT_MAX || targetPhantom.edgeBasedNode == UINT_MAX);
+    bool isValid() const
+    {
+        return location.isValid() &&
+               (name_id != std::numeric_limits<unsigned>::max());
     }
 
-    bool PhantomNodesHaveEqualLocation() const {
-        return startPhantom == targetPhantom;
+    bool operator==(const PhantomNode & other) const
+    {
+        return location == other.location;
     }
 };
 
-inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn){
-    out << "Node1: " << pn.startPhantom.edgeBasedNode << std::endl;
-    out << "Node2: " << pn.targetPhantom.edgeBasedNode << std::endl;
-    out << "startCoord: " << pn.startPhantom.location << std::endl;
-    out << "targetCoord: " << pn.targetPhantom.location << std::endl;
+typedef std::vector<std::vector<PhantomNode>> PhantomNodeArray;
+
+struct PhantomNodeLists
+{
+    std::vector<PhantomNode> source_phantom_list;
+    std::vector<PhantomNode> target_phantom_list;
+};
+
+struct PhantomNodes
+{
+    PhantomNode source_phantom;
+    PhantomNode target_phantom;
+};
+
+inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn)
+{
+    out << "source_coord: " << pn.source_phantom.location        << "\n";
+    out << "target_coord: " << pn.target_phantom.location        << std::endl;
     return out;
 }
 
-inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn){
-    out << "node: " << pn.edgeBasedNode << ", name: " << pn.nodeBasedEdgeNameID << ", w1: " << pn.weight1 << ", w2: " << pn.weight2 << ", ratio: " << pn.ratio << ", loc: " << pn.location;
+inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn)
+{
+    out <<  "node1: " << pn.forward_node_id      << ", " <<
+            "node2: " << pn.reverse_node_id      << ", " <<
+            "name: "  << pn.name_id              << ", " <<
+            "fwd-w: " << pn.forward_weight       << ", " <<
+            "rev-w: " << pn.reverse_weight       << ", " <<
+            "fwd-o: " << pn.forward_offset       << ", " <<
+            "rev-o: " << pn.reverse_offset       << ", " <<
+            "geom: "  << pn.packed_geometry_id   << ", " <<
+            "pos: "   << pn.fwd_segment_position << ", " <<
+            "loc: "   << pn.location;
     return out;
 }
 
-struct NodesOfEdge {
-    NodeID edgeBasedNode;
-    double ratio;
-    _Coordinate projectedPoint;
-};
-
-#endif /* PHANTOMNODES_H_ */
+#endif // PHANTOM_NODES_H
diff --git a/DataStructures/QueryEdge.h b/DataStructures/QueryEdge.h
index 3a2aecb..b84c180 100644
--- a/DataStructures/QueryEdge.h
+++ b/DataStructures/QueryEdge.h
@@ -1,75 +1,63 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+*/
 
 #ifndef QUERYEDGE_H_
 #define QUERYEDGE_H_
 
-#include "TurnInstructions.h"
 #include "../typedefs.h"
 
-#include <climits>
-
-struct OriginalEdgeData{
-    explicit OriginalEdgeData(NodeID v, unsigned n, TurnInstruction t) : viaNode(v), nameID(n), turnInstruction(t) {}
-    OriginalEdgeData() : viaNode(UINT_MAX), nameID(UINT_MAX), turnInstruction(UCHAR_MAX) {}
-    NodeID viaNode;
-    unsigned nameID;
-    TurnInstruction turnInstruction;
-};
-
-struct QueryEdge {
+struct QueryEdge
+{
     NodeID source;
     NodeID target;
-    struct EdgeData {
-        NodeID id:31;
-        bool shortcut:1;
-        int distance:30;
-        bool forward:1;
-        bool backward:1;
+    struct EdgeData
+    {
+        NodeID id : 31;
+        bool shortcut : 1;
+        int distance : 30;
+        bool forward : 1;
+        bool backward : 1;
     } data;
-    bool operator<( const QueryEdge& right ) const {
-        if ( source != right.source )
+
+    bool operator<(const QueryEdge &right) const
+    {
+        if (source != right.source)
+        {
             return source < right.source;
+        }
         return target < right.target;
     }
 
-    //sorts by source and other attributes
-    static bool CompareBySource( const QueryEdge& left, const QueryEdge& right ) {
-        if ( left.source != right.source )
-            return left.source < right.source;
-        int l = ( left.data.forward ? -1 : 0 ) + ( left.data.backward ? -1 : 0 );
-        int r = ( right.data.forward ? -1 : 0 ) + ( right.data.backward ? -1 : 0 );
-        if ( l != r )
-            return l < r;
-        if ( left.target != right.target )
-            return left.target < right.target;
-        return left.data.distance < right.data.distance;
-    }
-
-    bool operator== ( const QueryEdge& right ) const {
-        return ( source == right.source && target == right.target && data.distance == right.data.distance &&
-                data.shortcut == right.data.shortcut && data.forward == right.data.forward && data.backward == right.data.backward
-                && data.id == right.data.id
-        );
+    bool operator==(const QueryEdge &right) const
+    {
+        return (source == right.source && target == right.target &&
+                data.distance == right.data.distance && data.shortcut == right.data.shortcut &&
+                data.forward == right.data.forward && data.backward == right.data.backward &&
+                data.id == right.data.id);
     }
 };
 
diff --git a/DataStructures/QueryNode.h b/DataStructures/QueryNode.h
new file mode 100644
index 0000000..ee6b278
--- /dev/null
+++ b/DataStructures/QueryNode.h
@@ -0,0 +1,85 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef QUERY_NODE_H
+#define QUERY_NODE_H
+
+#include "../typedefs.h"
+
+#include <osrm/Coordinate.h>
+
+#include <boost/assert.hpp>
+
+#include <limits>
+
+struct NodeInfo
+{
+    typedef NodeID key_type; // type of NodeID
+    typedef int value_type; // type of lat,lons
+
+    explicit NodeInfo(int lat, int lon, NodeID node_id) : lat(lat), lon(lon), node_id(node_id) {}
+    NodeInfo()
+        : lat(std::numeric_limits<int>::max()), lon(std::numeric_limits<int>::max()),
+          node_id(std::numeric_limits<unsigned>::max())
+    {
+    }
+
+    int lat;
+    int lon;
+    NodeID node_id;
+
+    static NodeInfo min_value()
+    {
+        return NodeInfo(static_cast<int>(-90 * COORDINATE_PRECISION),
+                        static_cast<int>(-180 * COORDINATE_PRECISION),
+                        std::numeric_limits<NodeID>::min());
+    }
+
+    static NodeInfo max_value()
+    {
+        return NodeInfo(static_cast<int>(90 * COORDINATE_PRECISION),
+                        static_cast<int>(180 * COORDINATE_PRECISION),
+                        std::numeric_limits<NodeID>::max());
+    }
+
+    value_type operator[](const std::size_t n) const
+    {
+        switch (n)
+        {
+        case 1:
+            return lat;
+        case 0:
+            return lon;
+        default:
+            break;
+        }
+        BOOST_ASSERT_MSG(false, "should not happen");
+        return std::numeric_limits<unsigned>::max();
+    }
+};
+
+#endif // QUERY_NODE_H
diff --git a/DataStructures/RangeTable.h b/DataStructures/RangeTable.h
new file mode 100644
index 0000000..f9ec254
--- /dev/null
+++ b/DataStructures/RangeTable.h
@@ -0,0 +1,231 @@
+#ifndef __RANGE_TABLE_H__
+#define __RANGE_TABLE_H__
+
+#include "SharedMemoryFactory.h"
+#include "SharedMemoryVectorWrapper.h"
+
+#include <boost/range/irange.hpp>
+
+#include <fstream>
+#include <vector>
+#include <array>
+
+/*
+ * These pre-declarations are needed because parsing C++ is hard
+ * and otherwise the compiler gets confused.
+ */
+
+template<unsigned BLOCK_SIZE=16, bool USE_SHARED_MEMORY = false> class RangeTable;
+
+template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
+std::ostream& operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
+
+template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
+std::istream& operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
+
+/**
+ * Stores adjacent ranges in a compressed format.
+ *
+ * Maximum supported length of a range is 255.
+ *
+ * Note: BLOCK_SIZE is the number of differential encodoed values.
+ * But each block consists of an absolute value and BLOCK_SIZE differential values.
+ * So the effective block size is sizeof(unsigned) + BLOCK_SIZE.
+ */
+template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
+class RangeTable
+{
+public:
+
+    typedef std::array<unsigned char, BLOCK_SIZE> BlockT;
+    typedef typename ShM<BlockT, USE_SHARED_MEMORY>::vector   BlockContainerT;
+    typedef typename ShM<unsigned, USE_SHARED_MEMORY>::vector OffsetContainerT;
+    typedef decltype(boost::irange(0u,0u))                    RangeT;
+
+    friend std::ostream& operator<< <>(std::ostream &out, const RangeTable &table);
+    friend std::istream& operator>> <>(std::istream &in, RangeTable &table);
+
+    RangeTable() : sum_lengths(0) {}
+
+    // for loading from shared memory
+    explicit RangeTable(OffsetContainerT& external_offsets, BlockContainerT& external_blocks, const unsigned sum_lengths)
+    : sum_lengths(sum_lengths)
+    {
+        block_offsets.swap(external_offsets);
+        diff_blocks.swap(external_blocks);
+    }
+
+    // construct table from length vector
+    explicit RangeTable(const std::vector<unsigned>& lengths)
+    {
+        const unsigned number_of_blocks = [&lengths]() {
+            unsigned num = (lengths.size() + 1) / (BLOCK_SIZE + 1);
+            if ((lengths.size() + 1) % (BLOCK_SIZE + 1) != 0)
+            {
+                num += 1;
+            }
+            return num;
+        }();
+
+        block_offsets.reserve(number_of_blocks);
+        diff_blocks.reserve(number_of_blocks);
+
+        unsigned last_length = 0;
+        unsigned lengths_prefix_sum = 0;
+        unsigned block_idx = 0;
+        unsigned block_counter = 0;
+        BlockT block;
+        unsigned block_sum = 0;
+        for (const unsigned l : lengths)
+        {
+            // first entry of a block: encode absolute offset
+            if (block_idx == 0)
+            {
+                block_offsets.push_back(lengths_prefix_sum);
+                block_sum = 0;
+            }
+            else
+            {
+                block[block_idx - 1] = last_length;
+                block_sum += last_length;
+            }
+
+            BOOST_ASSERT((block_idx == 0 && block_offsets[block_counter] == lengths_prefix_sum)
+                || lengths_prefix_sum == (block_offsets[block_counter]+block_sum));
+
+            // block is full
+            if (BLOCK_SIZE == block_idx)
+            {
+                diff_blocks.push_back(block);
+                block_counter++;
+            }
+
+            // we can only store strings with length 255
+            BOOST_ASSERT(l <= 255);
+
+            lengths_prefix_sum += l;
+            last_length = l;
+
+            block_idx = (block_idx + 1) % (BLOCK_SIZE + 1);
+        }
+
+        // Last block can't be finished because we didn't add the sentinel
+        BOOST_ASSERT (block_counter == (number_of_blocks - 1));
+
+        // one block missing: starts with guard value
+        if (0 == block_idx)
+        {
+            // the last value is used as sentinel
+            block_offsets.push_back(lengths_prefix_sum);
+            block_idx = (block_idx + 1) % BLOCK_SIZE;
+        }
+
+        while (0 != block_idx)
+        {
+            block[block_idx - 1] = last_length;
+            last_length = 0;
+            block_idx = (block_idx + 1) % (BLOCK_SIZE + 1);
+        }
+        diff_blocks.push_back(block);
+
+        BOOST_ASSERT(diff_blocks.size() == number_of_blocks && block_offsets.size() == number_of_blocks);
+
+        sum_lengths = lengths_prefix_sum;
+    }
+
+    inline RangeT GetRange(const unsigned id) const
+    {
+        BOOST_ASSERT(id < block_offsets.size() + diff_blocks.size() * BLOCK_SIZE);
+        // internal_idx 0 is implicitly stored in block_offsets[block_idx]
+        const unsigned internal_idx = id % (BLOCK_SIZE + 1);
+        const unsigned block_idx = id / (BLOCK_SIZE + 1);
+
+        BOOST_ASSERT(block_idx < diff_blocks.size());
+
+        unsigned begin_idx = 0;
+        unsigned end_idx = 0;
+        begin_idx = block_offsets[block_idx];
+        const BlockT& block = diff_blocks[block_idx];
+        if (internal_idx > 0)
+        {
+            begin_idx += PrefixSumAtIndex(internal_idx - 1, block);
+        }
+
+        // next index inside current block
+        if (internal_idx < BLOCK_SIZE)
+        {
+            // note internal_idx - 1 is the *current* index for uint8_blocks
+            end_idx = begin_idx + block[internal_idx];
+        }
+        else
+        {
+            BOOST_ASSERT(block_idx < block_offsets.size() - 1);
+            end_idx = block_offsets[block_idx + 1];
+        }
+
+        BOOST_ASSERT(begin_idx < sum_lengths && end_idx <= sum_lengths);
+        BOOST_ASSERT(begin_idx <= end_idx);
+
+        return boost::irange(begin_idx, end_idx);
+    }
+private:
+
+    inline unsigned PrefixSumAtIndex(int index, const BlockT& block) const;
+
+    // contains offset for each differential block
+    OffsetContainerT block_offsets;
+    // blocks of differential encoded offsets, should be aligned
+    BlockContainerT diff_blocks;
+    unsigned sum_lengths;
+};
+
+template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
+unsigned RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY>::PrefixSumAtIndex(int index, const BlockT& block) const
+{
+    // this loop looks inefficent, but a modern compiler
+    // will emit nice SIMD here, at least for sensible block sizes. (I checked.)
+    unsigned sum = 0;
+    for (int i = 0; i <= index; ++i)
+    {
+        sum += block[i];
+    }
+
+    return sum;
+}
+
+template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
+std::ostream& operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
+{
+    // write number of block
+    const unsigned number_of_blocks = table.diff_blocks.size();
+    out.write((char *) &number_of_blocks, sizeof(unsigned));
+    // write total length
+    out.write((char *) &table.sum_lengths, sizeof(unsigned));
+    // write block offsets
+    out.write((char *) table.block_offsets.data(), sizeof(unsigned) * table.block_offsets.size());
+    // write blocks
+    out.write((char *) table.diff_blocks.data(), BLOCK_SIZE * table.diff_blocks.size());
+
+    return out;
+}
+
+template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
+std::istream& operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
+{
+    // read number of block
+    unsigned number_of_blocks;
+    in.read((char *) &number_of_blocks, sizeof(unsigned));
+    // read total length
+    in.read((char *) &table.sum_lengths, sizeof(unsigned));
+
+    table.block_offsets.resize(number_of_blocks);
+    table.diff_blocks.resize(number_of_blocks);
+
+    // read block offsets
+    in.read((char *) table.block_offsets.data(), sizeof(unsigned) * number_of_blocks);
+    // read blocks
+    in.read((char *) table.diff_blocks.data(), BLOCK_SIZE * number_of_blocks);
+    return in;
+}
+
+#endif
diff --git a/DataStructures/RawRouteData.h b/DataStructures/RawRouteData.h
new file mode 100644
index 0000000..e034b43
--- /dev/null
+++ b/DataStructures/RawRouteData.h
@@ -0,0 +1,80 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef RAW_ROUTE_DATA_H
+#define RAW_ROUTE_DATA_H
+
+#include "../DataStructures/PhantomNodes.h"
+#include "../DataStructures/TurnInstructions.h"
+#include "../typedefs.h"
+
+#include <osrm/Coordinate.h>
+
+#include <vector>
+
+struct PathData
+{
+    PathData()
+        : node(SPECIAL_NODEID), name_id(INVALID_EDGE_WEIGHT),
+          segment_duration(INVALID_EDGE_WEIGHT),
+          turn_instruction(TurnInstruction::NoTurn)
+    {
+    }
+
+    PathData(NodeID node, unsigned name_id, TurnInstruction turn_instruction, EdgeWeight segment_duration)
+        : node(node), name_id(name_id), segment_duration(segment_duration), turn_instruction(turn_instruction)
+    {
+    }
+    NodeID node;
+    unsigned name_id;
+    EdgeWeight segment_duration;
+    TurnInstruction turn_instruction;
+};
+
+struct RawRouteData
+{
+    std::vector<std::vector<PathData>> unpacked_path_segments;
+    std::vector<PathData> unpacked_alternative;
+    std::vector<PhantomNodes> segment_end_coordinates;
+    std::vector<FixedPointCoordinate> raw_via_node_coordinates;
+    std::vector<bool> source_traversed_in_reverse;
+    std::vector<bool> target_traversed_in_reverse;
+    std::vector<bool> alt_source_traversed_in_reverse;
+    std::vector<bool> alt_target_traversed_in_reverse;
+    unsigned check_sum;
+    int shortest_path_length;
+    int alternative_path_length;
+
+    RawRouteData()
+        : check_sum(SPECIAL_NODEID),
+          shortest_path_length(INVALID_EDGE_WEIGHT),
+          alternative_path_length(INVALID_EDGE_WEIGHT)
+    {
+    }
+};
+
+#endif // RAW_ROUTE_DATA_H
diff --git a/DataStructures/Restriction.h b/DataStructures/Restriction.h
index 3627c6a..2b166f5 100644
--- a/DataStructures/Restriction.h
+++ b/DataStructures/Restriction.h
@@ -1,97 +1,126 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+*/
 
-#ifndef RESTRICTION_H_
-#define RESTRICTION_H_
+#ifndef RESTRICTION_H
+#define RESTRICTION_H
 
-#include <climits>
+#include "../typedefs.h"
 
-struct _Restriction {
+#include <limits>
+
+struct TurnRestriction
+{
     NodeID viaNode;
     NodeID fromNode;
     NodeID toNode;
-    struct Bits { //mostly unused
-        Bits() : isOnly(false), unused1(false), unused2(false), unused3(false), unused4(false), unused5(false), unused6(false), unused7(false) {}
-        char isOnly:1;
-        char unused1:1;
-        char unused2:1;
-        char unused3:1;
-        char unused4:1;
-        char unused5:1;
-        char unused6:1;
-        char unused7:1;
+    struct Bits
+    { // mostly unused
+        Bits()
+            : isOnly(false), unused1(false), unused2(false), unused3(false), unused4(false),
+              unused5(false), unused6(false), unused7(false)
+        {
+        }
+
+        bool isOnly : 1;
+        bool unused1 : 1;
+        bool unused2 : 1;
+        bool unused3 : 1;
+        bool unused4 : 1;
+        bool unused5 : 1;
+        bool unused6 : 1;
+        bool unused7 : 1;
     } flags;
 
-    _Restriction(NodeID vn) : viaNode(vn), fromNode(UINT_MAX), toNode(UINT_MAX) { }
-    _Restriction(bool isOnly = false) : viaNode(UINT_MAX), fromNode(UINT_MAX), toNode(UINT_MAX) {
+    explicit TurnRestriction(NodeID viaNode)
+        : viaNode(viaNode), fromNode(std::numeric_limits<unsigned>::max()),
+          toNode(std::numeric_limits<unsigned>::max())
+    {
+    }
+
+    explicit TurnRestriction(const bool isOnly = false)
+        : viaNode(std::numeric_limits<unsigned>::max()),
+          fromNode(std::numeric_limits<unsigned>::max()),
+          toNode(std::numeric_limits<unsigned>::max())
+    {
         flags.isOnly = isOnly;
     }
 };
 
-inline bool CmpRestrictionByFrom ( _Restriction a, _Restriction b) { return (a.fromNode < b.fromNode);  }
-
-struct _RawRestrictionContainer {
-    _Restriction restriction;
+struct InputRestrictionContainer
+{
     EdgeID fromWay;
     EdgeID toWay;
     unsigned viaNode;
+    TurnRestriction restriction;
 
-    _RawRestrictionContainer(EdgeID f, EdgeID t, NodeID vn, unsigned vw) : fromWay(f), toWay(t), viaNode(vw) { restriction.viaNode = vn;}
-    _RawRestrictionContainer(bool isOnly = false) : fromWay(UINT_MAX), toWay(UINT_MAX), viaNode(UINT_MAX) { restriction.flags.isOnly = isOnly;}
-
-    static _RawRestrictionContainer min_value() {
-        return _RawRestrictionContainer(0, 0, 0, 0);
+    InputRestrictionContainer(EdgeID fromWay, EdgeID toWay, NodeID vn, unsigned vw)
+        : fromWay(fromWay), toWay(toWay), viaNode(vw)
+    {
+        restriction.viaNode = vn;
+    }
+    explicit InputRestrictionContainer(bool isOnly = false)
+        : fromWay(std::numeric_limits<unsigned>::max()),
+          toWay(std::numeric_limits<unsigned>::max()), viaNode(std::numeric_limits<unsigned>::max())
+    {
+        restriction.flags.isOnly = isOnly;
     }
-    static _RawRestrictionContainer max_value() {
-        return _RawRestrictionContainer(UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX);
+
+    static InputRestrictionContainer min_value() { return InputRestrictionContainer(0, 0, 0, 0); }
+    static InputRestrictionContainer max_value()
+    {
+        return InputRestrictionContainer(std::numeric_limits<unsigned>::max(),
+                                         std::numeric_limits<unsigned>::max(),
+                                         std::numeric_limits<unsigned>::max(),
+                                         std::numeric_limits<unsigned>::max());
     }
 };
 
-struct CmpRestrictionContainerByFrom: public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
-    typedef _RawRestrictionContainer value_type;
-    bool operator ()  (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
+struct CmpRestrictionContainerByFrom
+{
+    typedef InputRestrictionContainer value_type;
+    inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
+        const
+    {
         return a.fromWay < b.fromWay;
     }
-    value_type max_value()  {
-        return _RawRestrictionContainer::max_value();
-    }
-    value_type min_value() {
-        return _RawRestrictionContainer::min_value();
-    }
+    inline value_type max_value() const { return InputRestrictionContainer::max_value(); }
+    inline value_type min_value() const { return InputRestrictionContainer::min_value(); }
 };
 
-struct CmpRestrictionContainerByTo: public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
-    typedef _RawRestrictionContainer value_type;
-    bool operator ()  (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
+struct CmpRestrictionContainerByTo
+{
+    typedef InputRestrictionContainer value_type;
+    inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
+        const
+    {
         return a.toWay < b.toWay;
     }
-    value_type max_value()  {
-        return _RawRestrictionContainer::max_value();
-    }
-    value_type min_value() {
-        return _RawRestrictionContainer::min_value();
-    }
+    value_type max_value() const { return InputRestrictionContainer::max_value(); }
+    value_type min_value() const { return InputRestrictionContainer::min_value(); }
 };
 
-
-
-#endif /* RESTRICTION_H_ */
+#endif // RESTRICTION_H
diff --git a/DataStructures/RestrictionMap.cpp b/DataStructures/RestrictionMap.cpp
new file mode 100644
index 0000000..1859b82
--- /dev/null
+++ b/DataStructures/RestrictionMap.cpp
@@ -0,0 +1,224 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "RestrictionMap.h"
+#include "NodeBasedGraph.h"
+
+#include "../Util/SimpleLogger.h"
+
+bool RestrictionMap::IsViaNode(const NodeID node) const
+{
+    return m_no_turn_via_node_set.find(node) != m_no_turn_via_node_set.end();
+}
+
+RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
+                               const std::vector<TurnRestriction> &restriction_list)
+    : m_count(0), m_graph(graph)
+{
+    // decompose restriction consisting of a start, via and end node into a
+    // a pair of starting edge and a list of all end nodes
+    for (auto &restriction : restriction_list)
+    {
+        m_restriction_start_nodes.insert(restriction.fromNode);
+        m_no_turn_via_node_set.insert(restriction.viaNode);
+
+        RestrictionSource restriction_source = {restriction.fromNode, restriction.viaNode};
+
+        unsigned index;
+        auto restriction_iter = m_restriction_map.find(restriction_source);
+        if (restriction_iter == m_restriction_map.end())
+        {
+            index = m_restriction_bucket_list.size();
+            m_restriction_bucket_list.resize(index + 1);
+            m_restriction_map.emplace(restriction_source, index);
+        }
+        else
+        {
+            index = restriction_iter->second;
+            // Map already contains an is_only_*-restriction
+            if (m_restriction_bucket_list.at(index).begin()->is_only)
+            {
+                continue;
+            }
+            else if (restriction.flags.isOnly)
+            {
+                // We are going to insert an is_only_*-restriction. There can be only one.
+                m_count -= m_restriction_bucket_list.at(index).size();
+                m_restriction_bucket_list.at(index).clear();
+            }
+        }
+        ++m_count;
+        m_restriction_bucket_list.at(index)
+            .emplace_back(restriction.toNode, restriction.flags.isOnly);
+    }
+}
+
+// Replace end v with w in each turn restriction containing u as via node
+void RestrictionMap::FixupArrivingTurnRestriction(const NodeID node_u,
+                                                  const NodeID node_v,
+                                                  const NodeID node_w)
+{
+    BOOST_ASSERT(node_u != SPECIAL_NODEID);
+    BOOST_ASSERT(node_v != SPECIAL_NODEID);
+    BOOST_ASSERT(node_w != SPECIAL_NODEID);
+
+    if (!IsViaNode(node_u))
+    {
+        return;
+    }
+
+    // find all potential start edges. It is more efficent to get a (small) list
+    // of potential start edges than iterating over all buckets
+    std::vector<NodeID> predecessors;
+    for (const EdgeID current_edge_id : m_graph->GetAdjacentEdgeRange(node_u))
+    {
+        const EdgeData &edge_data = m_graph->GetEdgeData(current_edge_id);
+        const NodeID target = m_graph->GetTarget(current_edge_id);
+        if (edge_data.backward && (node_v != target))
+        {
+            predecessors.push_back(target);
+        }
+    }
+
+    for (const NodeID node_x : predecessors)
+    {
+        const auto restriction_iterator = m_restriction_map.find({node_x, node_u});
+        if (restriction_iterator == m_restriction_map.end())
+        {
+            continue;
+        }
+
+        const unsigned index = restriction_iterator->second;
+        auto &bucket = m_restriction_bucket_list.at(index);
+        for (RestrictionTarget &restriction_target : bucket)
+        {
+            if (node_v == restriction_target.target_node)
+            {
+                restriction_target.target_node = node_w;
+            }
+        }
+    }
+}
+
+// Replaces start edge (v, w) with (u, w). Only start node changes.
+void RestrictionMap::FixupStartingTurnRestriction(const NodeID node_u,
+                                                  const NodeID node_v,
+                                                  const NodeID node_w)
+{
+    BOOST_ASSERT(node_u != SPECIAL_NODEID);
+    BOOST_ASSERT(node_v != SPECIAL_NODEID);
+    BOOST_ASSERT(node_w != SPECIAL_NODEID);
+
+    if (!IsSourceNode(node_v))
+    {
+        return;
+    }
+
+    const auto restriction_iterator = m_restriction_map.find({node_v, node_w});
+    if (restriction_iterator != m_restriction_map.end())
+    {
+        const unsigned index = restriction_iterator->second;
+        // remove old restriction start (v,w)
+        m_restriction_map.erase(restriction_iterator);
+        m_restriction_start_nodes.emplace(node_u);
+        // insert new restriction start (u,w) (pointing to index)
+        RestrictionSource new_source = {node_u, node_w};
+        m_restriction_map.emplace(new_source, index);
+    }
+}
+
+// Check if edge (u, v) is the start of any turn restriction.
+// If so returns id of first target node.
+NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(const NodeID node_u, const NodeID node_v) const
+{
+    BOOST_ASSERT(node_u != SPECIAL_NODEID);
+    BOOST_ASSERT(node_v != SPECIAL_NODEID);
+
+    if (!IsSourceNode(node_u))
+    {
+        return SPECIAL_NODEID;
+    }
+
+    auto restriction_iter = m_restriction_map.find({node_u, node_v});
+    if (restriction_iter != m_restriction_map.end())
+    {
+        const unsigned index = restriction_iter->second;
+        auto &bucket = m_restriction_bucket_list.at(index);
+        for (const RestrictionTarget &restriction_target : bucket)
+        {
+            if (restriction_target.is_only)
+            {
+                return restriction_target.target_node;
+            }
+        }
+    }
+    return SPECIAL_NODEID;
+}
+
+// Checks if turn <u,v,w> is actually a turn restriction.
+bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID node_u,
+                                             const NodeID node_v,
+                                             const NodeID node_w) const
+{
+    // return false;
+
+    BOOST_ASSERT(node_u != SPECIAL_NODEID);
+    BOOST_ASSERT(node_v != SPECIAL_NODEID);
+    BOOST_ASSERT(node_w != SPECIAL_NODEID);
+
+    if (!IsSourceNode(node_u))
+    {
+        return false;
+    }
+
+    auto restriction_iter = m_restriction_map.find({node_u, node_v});
+    if (restriction_iter != m_restriction_map.end())
+    {
+        const unsigned index = restriction_iter->second;
+        const auto &bucket = m_restriction_bucket_list.at(index);
+        for (const RestrictionTarget &restriction_target : bucket)
+        {
+            if ((node_w == restriction_target.target_node) && // target found
+                (!restriction_target.is_only)                 // and not an only_-restr.
+                )
+            {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+// check of node is the start of any restriction
+bool RestrictionMap::IsSourceNode(const NodeID node) const
+{
+    if (m_restriction_start_nodes.find(node) == m_restriction_start_nodes.end())
+    {
+        return false;
+    }
+    return true;
+}
diff --git a/DataStructures/RestrictionMap.h b/DataStructures/RestrictionMap.h
new file mode 100644
index 0000000..8207b80
--- /dev/null
+++ b/DataStructures/RestrictionMap.h
@@ -0,0 +1,126 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef __RESTRICTION_MAP_H__
+#define __RESTRICTION_MAP_H__
+
+#include <memory>
+
+#include "DynamicGraph.h"
+#include "Restriction.h"
+#include "NodeBasedGraph.h"
+#include "../Util/StdHashExtensions.h"
+#include "../typedefs.h"
+
+#include <unordered_map>
+#include <unordered_set>
+
+struct RestrictionSource
+{
+    NodeID start_node;
+    NodeID via_node;
+
+    RestrictionSource(NodeID start, NodeID via) : start_node(start), via_node(via)
+    {
+    }
+
+    friend inline bool operator==(const RestrictionSource &lhs, const RestrictionSource &rhs)
+    {
+        return (lhs.start_node == rhs.start_node && lhs.via_node == rhs.via_node);
+    }
+};
+
+struct RestrictionTarget
+{
+    NodeID target_node;
+    bool is_only;
+
+    explicit RestrictionTarget(NodeID target, bool only) : target_node(target), is_only(only)
+    {
+    }
+
+    friend inline bool operator==(const RestrictionTarget &lhs, const RestrictionTarget &rhs)
+    {
+        return (lhs.target_node == rhs.target_node && lhs.is_only == rhs.is_only);
+    }
+};
+
+namespace std
+{
+template <> struct hash<RestrictionSource>
+{
+    size_t operator()(const RestrictionSource &r_source) const
+    {
+        return hash_val(r_source.start_node, r_source.via_node);
+    }
+};
+
+template <> struct hash<RestrictionTarget>
+{
+    size_t operator()(const RestrictionTarget &r_target) const
+    {
+        return hash_val(r_target.target_node, r_target.is_only);
+    }
+};
+}
+
+/**
+    \brief Efficent look up if an edge is the start + via node of a TurnRestriction
+    EdgeBasedEdgeFactory decides by it if edges are inserted or geometry is compressed
+*/
+class RestrictionMap
+{
+  public:
+    RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
+                   const std::vector<TurnRestriction> &input_restrictions_list);
+
+    void FixupArrivingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
+    void FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
+    NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
+    bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
+    bool IsViaNode(const NodeID node) const;
+    unsigned size()
+    {
+        return m_count;
+    }
+
+  private:
+    bool IsSourceNode(const NodeID node) const;
+    typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
+    typedef NodeBasedDynamicGraph::EdgeData EdgeData;
+
+    unsigned m_count;
+    std::shared_ptr<NodeBasedDynamicGraph> m_graph;
+    //! index -> list of (target, isOnly)
+    std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
+    //! maps (start, via) -> bucket index
+    std::unordered_map<RestrictionSource, unsigned> m_restriction_map;
+    std::unordered_set<NodeID> m_restriction_start_nodes;
+    std::unordered_set<NodeID> m_no_turn_via_node_set;
+};
+
+#endif
diff --git a/DataStructures/RouteParameters.cpp b/DataStructures/RouteParameters.cpp
new file mode 100644
index 0000000..edc7311
--- /dev/null
+++ b/DataStructures/RouteParameters.cpp
@@ -0,0 +1,89 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <osrm/RouteParameters.h>
+
+#include <boost/fusion/container/vector.hpp>
+#include <boost/fusion/sequence/intrinsic.hpp>
+#include <boost/fusion/include/at_c.hpp>
+
+RouteParameters::RouteParameters()
+    : zoom_level(18), print_instructions(false), alternate_route(true), geometry(true),
+      compression(true), deprecatedAPI(false), check_sum(-1)
+{
+}
+
+void RouteParameters::setZoomLevel(const short level)
+{
+    if (18 >= level && 0 <= level)
+    {
+        zoom_level = level;
+    }
+}
+
+void RouteParameters::setAlternateRouteFlag(const bool flag) { alternate_route = flag; }
+
+void RouteParameters::setDeprecatedAPIFlag(const std::string &) { deprecatedAPI = true; }
+
+void RouteParameters::setChecksum(const unsigned sum) { check_sum = sum; }
+
+void RouteParameters::setInstructionFlag(const bool flag) { print_instructions = flag; }
+
+void RouteParameters::setService(const std::string &service_string) { service = service_string; }
+
+void RouteParameters::setOutputFormat(const std::string &format) { output_format = format; }
+
+void RouteParameters::setJSONpParameter(const std::string &parameter)
+{
+    jsonp_parameter = parameter;
+}
+
+void RouteParameters::addHint(const std::string &hint)
+{
+    hints.resize(coordinates.size());
+    if (!hints.empty())
+    {
+        hints.back() = hint;
+    }
+}
+
+void RouteParameters::setLanguage(const std::string &language_string)
+{
+    language = language_string;
+}
+
+void RouteParameters::setGeometryFlag(const bool flag) { geometry = flag; }
+
+void RouteParameters::setCompressionFlag(const bool flag) { compression = flag; }
+
+void
+RouteParameters::addCoordinate(const boost::fusion::vector<double, double> &transmitted_coordinates)
+{
+    coordinates.emplace_back(
+        static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<0>(transmitted_coordinates)),
+        static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<1>(transmitted_coordinates)));
+}
diff --git a/DataStructures/SearchEngine.cpp b/DataStructures/SearchEngine.cpp
deleted file mode 100644
index 2a538a7..0000000
--- a/DataStructures/SearchEngine.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#include "SearchEngine.h"
-
-SearchEngine::SearchEngine(
-    QueryGraph * g,
-    NodeInformationHelpDesk * nh,
-    std::vector<std::string> & n
-    ) :
-        _queryData(g, nh, n),
-        shortestPath(_queryData),
-        alternativePaths(_queryData)
-    {}
-    SearchEngine::~SearchEngine() {}
-
-void SearchEngine::GetCoordinatesForNodeID(
-    NodeID id,
-    _Coordinate& result
-    ) const {
-    result.lat = _queryData.nodeHelpDesk->getLatitudeOfNode(id);
-    result.lon = _queryData.nodeHelpDesk->getLongitudeOfNode(id);
-}
-
-void SearchEngine::FindPhantomNodeForCoordinate(
-    const _Coordinate & location,
-    PhantomNode & result,
-    const unsigned zoomLevel
-    ) const {
-    _queryData.nodeHelpDesk->FindPhantomNodeForCoordinate(
-        location,
-        result, zoomLevel
-    );
-}
-
-NodeID SearchEngine::GetNameIDForOriginDestinationNodeID(
-    const NodeID s,
-    const NodeID t
-    ) const {
-    if(s == t){
-        return 0;
-    }
-    EdgeID e = _queryData.graph->FindEdge(s, t);
-    if(e == UINT_MAX) {
-        e = _queryData.graph->FindEdge( t, s );
-    }
-    if(UINT_MAX == e) {
-        return 0;
-    }
-    assert(e != UINT_MAX);
-    const QueryEdge::EdgeData ed = _queryData.graph->GetEdgeData(e);
-    return ed.id;
-}
-
-std::string SearchEngine::GetEscapedNameForNameID(const unsigned nameID) const {
-    bool is_name_invalid = (nameID >= _queryData.names.size() || nameID == 0);
-    if (is_name_invalid) {
-        return std::string("");
-    }
-
-    return HTMLEntitize(_queryData.names.at(nameID));
-}
-
-SearchEngineHeapPtr SearchEngineData::forwardHeap;
-SearchEngineHeapPtr SearchEngineData::backwardHeap;
-
-SearchEngineHeapPtr SearchEngineData::forwardHeap2;
-SearchEngineHeapPtr SearchEngineData::backwardHeap2;
-
-SearchEngineHeapPtr SearchEngineData::forwardHeap3;
-SearchEngineHeapPtr SearchEngineData::backwardHeap3;
-
diff --git a/DataStructures/SearchEngine.h b/DataStructures/SearchEngine.h
index 64d273b..58f5e77 100644
--- a/DataStructures/SearchEngine.h
+++ b/DataStructures/SearchEngine.h
@@ -1,68 +1,60 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef SEARCHENGINE_H_
-#define SEARCHENGINE_H_
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef SEARCHENGINE_H
+#define SEARCHENGINE_H
 
-#include "Coordinate.h"
-#include "NodeInformationHelpDesk.h"
-#include "PhantomNodes.h"
-#include "QueryEdge.h"
 #include "SearchEngineData.h"
 #include "../RoutingAlgorithms/AlternativePathRouting.h"
+#include "../RoutingAlgorithms/ManyToManyRouting.h"
 #include "../RoutingAlgorithms/ShortestPathRouting.h"
 
-#include "../Util/StringUtil.h"
-#include "../typedefs.h"
-
-#include <climits>
-#include <string>
-#include <vector>
-
-class SearchEngine {
-private:
-    SearchEngineData _queryData;
-
-public:
-    ShortestPathRouting<SearchEngineData> shortestPath;
-    AlternativeRouting<SearchEngineData> alternativePaths;
-
-    SearchEngine(
-        QueryGraph * g, 
-        NodeInformationHelpDesk * nh, 
-        std::vector<std::string> & n
-    );
-	~SearchEngine();
+#include <type_traits>
 
-	void GetCoordinatesForNodeID(NodeID id, _Coordinate& result) const;
+template <class DataFacadeT> class SearchEngine
+{
+  private:
+    DataFacadeT *facade;
+    SearchEngineData engine_working_data;
 
-    void FindPhantomNodeForCoordinate(
-        const _Coordinate & location, 
-        PhantomNode & result, 
-        unsigned zoomLevel
-    ) const;
+  public:
+    ShortestPathRouting<DataFacadeT> shortest_path;
+    AlternativeRouting<DataFacadeT> alternative_path;
+    ManyToManyRouting<DataFacadeT> distance_table;
 
-    NodeID GetNameIDForOriginDestinationNodeID(
-        const NodeID s, const NodeID t) const;
+    explicit SearchEngine(DataFacadeT *facade)
+        : facade(facade), shortest_path(facade, engine_working_data),
+          alternative_path(facade, engine_working_data), distance_table(facade, engine_working_data)
+    {
+        static_assert(!std::is_pointer<DataFacadeT>::value, "don't instantiate with ptr type");
+        static_assert(std::is_object<DataFacadeT>::value, "don't instantiate with void, function, or reference");
+    }
 
-    std::string GetEscapedNameForNameID(const unsigned nameID) const;
+    ~SearchEngine() {}
 };
 
-#endif /* SEARCHENGINE_H_ */
+#endif // SEARCHENGINE_H
diff --git a/DataStructures/SearchEngineData.cpp b/DataStructures/SearchEngineData.cpp
index 77492f6..a5e4bfc 100644
--- a/DataStructures/SearchEngineData.cpp
+++ b/DataStructures/SearchEngineData.cpp
@@ -1,60 +1,93 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #include "SearchEngineData.h"
 
-void SearchEngineData::InitializeOrClearFirstThreadLocalStorage() {
-    if(!forwardHeap.get()) {
-        forwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
-    } else {
+#include "BinaryHeap.h"
+
+void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes)
+{
+    if (forwardHeap.get())
+    {
         forwardHeap->Clear();
     }
-    if(!backwardHeap.get()) {
-        backwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
-    } else {
+    else
+    {
+        forwardHeap.reset(new QueryHeap(number_of_nodes));
+    }
+
+    if (backwardHeap.get())
+    {
         backwardHeap->Clear();
     }
+    else
+    {
+        backwardHeap.reset(new QueryHeap(number_of_nodes));
+    }
 }
 
-void SearchEngineData::InitializeOrClearSecondThreadLocalStorage() {
-    if(!forwardHeap2.get()) {
-        forwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
-    } else {
+void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes)
+{
+    if (forwardHeap2.get())
+    {
         forwardHeap2->Clear();
     }
-    if(!backwardHeap2.get()) {
-        backwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
-     } else {
+    else
+    {
+        forwardHeap2.reset(new QueryHeap(number_of_nodes));
+    }
+
+    if (backwardHeap2.get())
+    {
         backwardHeap2->Clear();
     }
+    else
+    {
+        backwardHeap2.reset(new QueryHeap(number_of_nodes));
+    }
 }
 
-void SearchEngineData::InitializeOrClearThirdThreadLocalStorage() {
-    if(!forwardHeap3.get()) {
-        forwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
-    } else {
+void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes)
+{
+    if (forwardHeap3.get())
+    {
         forwardHeap3->Clear();
     }
-    if(!backwardHeap3.get()) {
-        backwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
-    } else {
+    else
+    {
+        forwardHeap3.reset(new QueryHeap(number_of_nodes));
+    }
+
+    if (backwardHeap3.get())
+    {
         backwardHeap3->Clear();
     }
+    else
+    {
+        backwardHeap3.reset(new QueryHeap(number_of_nodes));
+    }
 }
diff --git a/DataStructures/SearchEngineData.h b/DataStructures/SearchEngineData.h
index f9a2623..f0621e6 100644
--- a/DataStructures/SearchEngineData.h
+++ b/DataStructures/SearchEngineData.h
@@ -1,50 +1,49 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#include "BinaryHeap.h"
-#include "QueryEdge.h"
-#include "NodeInformationHelpDesk.h"
-#include "StaticGraph.h"
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include "../typedefs.h"
+*/
 
-#include <boost/thread.hpp>
+#ifndef SEARCH_ENGINE_DATA_H
+#define SEARCH_ENGINE_DATA_H
 
-#include <string>
-#include <vector>
+#include <boost/thread/tss.hpp>
+
+#include "../typedefs.h"
+#include "BinaryHeap.h"
 
-struct _HeapData {
+struct HeapData
+{
     NodeID parent;
-    _HeapData( NodeID p ) : parent(p) { }
+    /* explicit */ HeapData(NodeID p) : parent(p) {}
 };
-typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
-typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > QueryHeapType;
-typedef boost::thread_specific_ptr<QueryHeapType> SearchEngineHeapPtr;
-
-struct SearchEngineData {
-    typedef QueryGraph Graph;
-    typedef QueryHeapType QueryHeap;
-    SearchEngineData(QueryGraph * g, NodeInformationHelpDesk * nh, std::vector<std::string> & n) :graph(g), nodeHelpDesk(nh), names(n) {}
-    const QueryGraph * graph;
-    NodeInformationHelpDesk * nodeHelpDesk;
-    std::vector<std::string> & names;
+
+struct SearchEngineData
+{
+    typedef BinaryHeap<NodeID, NodeID, int, HeapData, UnorderedMapStorage<NodeID, int>> QueryHeap;
+    typedef boost::thread_specific_ptr<QueryHeap> SearchEngineHeapPtr;
+
     static SearchEngineHeapPtr forwardHeap;
     static SearchEngineHeapPtr backwardHeap;
     static SearchEngineHeapPtr forwardHeap2;
@@ -52,9 +51,11 @@ struct SearchEngineData {
     static SearchEngineHeapPtr forwardHeap3;
     static SearchEngineHeapPtr backwardHeap3;
 
-    void InitializeOrClearFirstThreadLocalStorage();
+    void InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes);
 
-    void InitializeOrClearSecondThreadLocalStorage();
+    void InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes);
 
-    void InitializeOrClearThirdThreadLocalStorage();
+    void InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes);
 };
+
+#endif // SEARCH_ENGINE_DATA_H
diff --git a/DataStructures/SegmentInformation.h b/DataStructures/SegmentInformation.h
index cbe4b81..f145804 100644
--- a/DataStructures/SegmentInformation.h
+++ b/DataStructures/SegmentInformation.h
@@ -1,42 +1,72 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef SEGMENTINFORMATION_H_
-#define SEGMENTINFORMATION_H_
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <climits>
+*/
+
+#ifndef SEGMENT_INFORMATION_H
+#define SEGMENT_INFORMATION_H
 
 #include "TurnInstructions.h"
 
-struct SegmentInformation {
-    _Coordinate location;
-    NodeID nameID;
-    double length;
-    unsigned duration;
-    double bearing;
-    TurnInstruction turnInstruction;
-    bool necessary;
-    SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr, const bool nec) :
-            location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(nec) {}
-    SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr) :
-        location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(tInstr != 0) {}
+#include "../typedefs.h"
+
+#include <osrm/Coordinate.h>
+
+// Struct fits everything in one cache line
+struct SegmentInformation
+{
+    FixedPointCoordinate location;
+    NodeID name_id;
+    EdgeWeight duration;
+    float length;
+    short bearing; // more than enough [0..3600] fits into 12 bits
+    TurnInstruction turn_instruction;
+    bool necessary:1;
+    bool is_via_location:1;
+
+    explicit SegmentInformation(const FixedPointCoordinate &location,
+                                const NodeID name_id,
+                                const EdgeWeight duration,
+                                const float length,
+                                const TurnInstruction turn_instruction,
+                                const bool necessary,
+                                const bool is_via_location)
+        : location(location), name_id(name_id), duration(duration), length(length), bearing(0),
+          turn_instruction(turn_instruction), necessary(necessary), is_via_location(is_via_location)
+    {
+    }
+
+    explicit SegmentInformation(const FixedPointCoordinate &location,
+                                const NodeID name_id,
+                                const EdgeWeight duration,
+                                const float length,
+                                const TurnInstruction turn_instruction)
+        : location(location), name_id(name_id), duration(duration), length(length), bearing(0),
+          turn_instruction(turn_instruction), necessary(turn_instruction != TurnInstruction::NoTurn), is_via_location(false)
+    {
+    }
 };
 
-#endif /* SEGMENTINFORMATION_H_ */
+#endif /* SEGMENT_INFORMATION_H */
diff --git a/DataStructures/SharedMemoryFactory.h b/DataStructures/SharedMemoryFactory.h
new file mode 100644
index 0000000..a07e125
--- /dev/null
+++ b/DataStructures/SharedMemoryFactory.h
@@ -0,0 +1,370 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef SHARED_MEMORY_FACTORY_H
+#define SHARED_MEMORY_FACTORY_H
+
+#include "../Util/OSRMException.h"
+#include "../Util/SimpleLogger.h"
+
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <boost/interprocess/mapped_region.hpp>
+#ifndef WIN32
+#include <boost/interprocess/xsi_shared_memory.hpp>
+#else
+#include <boost/interprocess/shared_memory_object.hpp>
+#endif
+
+#ifdef __linux__
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif
+
+// #include <cstring>
+#include <cstdint>
+
+#include <algorithm>
+#include <exception>
+
+struct OSRMLockFile
+{
+    boost::filesystem::path operator()()
+    {
+        boost::filesystem::path temp_dir = boost::filesystem::temp_directory_path();
+        boost::filesystem::path lock_file = temp_dir / "osrm.lock";
+        return lock_file;
+    }
+};
+
+#ifndef WIN32
+class SharedMemory
+{
+
+    // Remove shared memory on destruction
+    class shm_remove
+    {
+      private:
+        int m_shmid;
+        bool m_initialized;
+
+      public:
+        void SetID(int shmid)
+        {
+            m_shmid = shmid;
+            m_initialized = true;
+        }
+
+        shm_remove() : m_shmid(INT_MIN), m_initialized(false) {}
+        shm_remove(const shm_remove &) = delete;
+        ~shm_remove()
+        {
+            if (m_initialized)
+            {
+                SimpleLogger().Write(logDEBUG) << "automatic memory deallocation";
+                if (!boost::interprocess::xsi_shared_memory::remove(m_shmid))
+                {
+                    SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
+                }
+            }
+        }
+    };
+
+  public:
+    void *Ptr() const { return region.get_address(); }
+
+    SharedMemory() = delete;
+    SharedMemory(const SharedMemory &) = delete;
+
+    template <typename IdentifierT>
+    SharedMemory(const boost::filesystem::path &lock_file,
+                 const IdentifierT id,
+                 const uint64_t size = 0,
+                 bool read_write = false,
+                 bool remove_prev = true)
+        : key(lock_file.string().c_str(), id)
+    {
+        if (0 == size)
+        { // read_only
+            shm = boost::interprocess::xsi_shared_memory(boost::interprocess::open_only, key);
+
+            region = boost::interprocess::mapped_region(
+                shm,
+                (read_write ? boost::interprocess::read_write : boost::interprocess::read_only));
+        }
+        else
+        { // writeable pointer
+            // remove previously allocated mem
+            if (remove_prev)
+            {
+                Remove(key);
+            }
+            shm = boost::interprocess::xsi_shared_memory(
+                boost::interprocess::open_or_create, key, size);
+#ifdef __linux__
+            if (-1 == shmctl(shm.get_shmid(), SHM_LOCK, 0))
+            {
+                if (ENOMEM == errno)
+                {
+                    SimpleLogger().Write(logWARNING) << "could not lock shared memory to RAM";
+                }
+            }
+#endif
+            region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write);
+
+            remover.SetID(shm.get_shmid());
+            SimpleLogger().Write(logDEBUG) << "writeable memory allocated " << size << " bytes";
+        }
+    }
+
+    template <typename IdentifierT> static bool RegionExists(const IdentifierT id)
+    {
+        bool result = true;
+        try
+        {
+            OSRMLockFile lock_file;
+            boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
+            result = RegionExists(key);
+        }
+        catch (...) { result = false; }
+        return result;
+    }
+
+    template <typename IdentifierT> static bool Remove(const IdentifierT id)
+    {
+        OSRMLockFile lock_file;
+        boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
+        return Remove(key);
+    }
+
+  private:
+    static bool RegionExists(const boost::interprocess::xsi_key &key)
+    {
+        bool result = true;
+        try { boost::interprocess::xsi_shared_memory shm(boost::interprocess::open_only, key); }
+        catch (...) { result = false; }
+        return result;
+    }
+
+    static bool Remove(const boost::interprocess::xsi_key &key)
+    {
+        bool ret = false;
+        try
+        {
+            SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
+            boost::interprocess::xsi_shared_memory xsi(boost::interprocess::open_only, key);
+            ret = boost::interprocess::xsi_shared_memory::remove(xsi.get_shmid());
+        }
+        catch (const boost::interprocess::interprocess_exception &e)
+        {
+            if (e.get_error_code() != boost::interprocess::not_found_error)
+            {
+                throw;
+            }
+        }
+        return ret;
+    }
+
+    boost::interprocess::xsi_key key;
+    boost::interprocess::xsi_shared_memory shm;
+    boost::interprocess::mapped_region region;
+    shm_remove remover;
+};
+#else
+// Windows - specific code
+class SharedMemory : boost::noncopyable
+{
+    // Remove shared memory on destruction
+    class shm_remove : boost::noncopyable
+    {
+      private:
+        char *m_shmid;
+        bool m_initialized;
+
+      public:
+        void SetID(char *shmid)
+        {
+            m_shmid = shmid;
+            m_initialized = true;
+        }
+
+        shm_remove() : m_shmid("undefined"), m_initialized(false) {}
+
+        ~shm_remove()
+        {
+            if (m_initialized)
+            {
+                SimpleLogger().Write(logDEBUG) << "automatic memory deallocation";
+                if (!boost::interprocess::shared_memory_object::remove(m_shmid))
+                {
+                    SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
+                }
+            }
+        }
+    };
+
+  public:
+    void *Ptr() const { return region.get_address(); }
+
+    SharedMemory(const boost::filesystem::path &lock_file,
+                 const int id,
+                 const uint64_t size = 0,
+                 bool read_write = false,
+                 bool remove_prev = true)
+    {
+        sprintf(key, "%s.%d", "osrm.lock", id);
+        if (0 == size)
+        { // read_only
+            shm = boost::interprocess::shared_memory_object(
+                boost::interprocess::open_only,
+                key,
+                read_write ? boost::interprocess::read_write : boost::interprocess::read_only);
+            region = boost::interprocess::mapped_region(
+                shm, read_write ? boost::interprocess::read_write : boost::interprocess::read_only);
+        }
+        else
+        { // writeable pointer
+            // remove previously allocated mem
+            if (remove_prev)
+            {
+                Remove(key);
+            }
+            shm = boost::interprocess::shared_memory_object(
+                boost::interprocess::open_or_create, key, boost::interprocess::read_write);
+            shm.truncate(size);
+            region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write);
+
+            remover.SetID(key);
+            SimpleLogger().Write(logDEBUG) << "writeable memory allocated " << size << " bytes";
+        }
+    }
+
+    static bool RegionExists(const int id)
+    {
+        bool result = true;
+        try
+        {
+            char k[500];
+            build_key(id, k);
+            result = RegionExists(k);
+        }
+        catch (...) { result = false; }
+        return result;
+    }
+
+    static bool Remove(const int id)
+    {
+        char k[500];
+        build_key(id, k);
+        return Remove(k);
+    }
+
+  private:
+    static void build_key(int id, char *key)
+    {
+        OSRMLockFile lock_file;
+        sprintf(key, "%s.%d", "osrm.lock", id);
+    }
+
+    static bool RegionExists(const char *key)
+    {
+        bool result = true;
+        try
+        {
+            boost::interprocess::shared_memory_object shm(
+                boost::interprocess::open_only, key, boost::interprocess::read_write);
+        }
+        catch (...) { result = false; }
+        return result;
+    }
+
+    static bool Remove(char *key)
+    {
+        bool ret = false;
+        try
+        {
+            SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
+            ret = boost::interprocess::shared_memory_object::remove(key);
+        }
+        catch (const boost::interprocess::interprocess_exception &e)
+        {
+            if (e.get_error_code() != boost::interprocess::not_found_error)
+            {
+                throw;
+            }
+        }
+        return ret;
+    }
+
+    char key[500];
+    boost::interprocess::shared_memory_object shm;
+    boost::interprocess::mapped_region region;
+    shm_remove remover;
+};
+#endif
+
+template <class LockFileT = OSRMLockFile> class SharedMemoryFactory_tmpl
+{
+  public:
+    template <typename IdentifierT>
+    static SharedMemory *Get(const IdentifierT &id,
+                             const uint64_t size = 0,
+                             bool read_write = false,
+                             bool remove_prev = true)
+    {
+        try
+        {
+            LockFileT lock_file;
+            if (!boost::filesystem::exists(lock_file()))
+            {
+                if (0 == size)
+                {
+                    throw OSRMException("lock file does not exist, exiting");
+                }
+                else
+                {
+                    boost::filesystem::ofstream ofs(lock_file());
+                    ofs.close();
+                }
+            }
+            return new SharedMemory(lock_file(), id, size, read_write, remove_prev);
+        }
+        catch (const boost::interprocess::interprocess_exception &e)
+        {
+            SimpleLogger().Write(logWARNING) << "caught exception: " << e.what() << ", code "
+                                             << e.get_error_code();
+            throw OSRMException(e.what());
+        }
+    }
+
+    SharedMemoryFactory_tmpl() = delete;
+    SharedMemoryFactory_tmpl(const SharedMemoryFactory_tmpl &) = delete;
+};
+
+typedef SharedMemoryFactory_tmpl<> SharedMemoryFactory;
+
+#endif /* SHARED_MEMORY_POINTER_FACTORY_H */
diff --git a/DataStructures/SharedMemoryVectorWrapper.h b/DataStructures/SharedMemoryVectorWrapper.h
new file mode 100644
index 0000000..fe4baf3
--- /dev/null
+++ b/DataStructures/SharedMemoryVectorWrapper.h
@@ -0,0 +1,156 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef SHARED_MEMORY_VECTOR_WRAPPER_H
+#define SHARED_MEMORY_VECTOR_WRAPPER_H
+
+#include "../Util/SimpleLogger.h"
+
+#include <boost/assert.hpp>
+
+#include <algorithm>
+#include <iterator>
+#include <type_traits>
+#include <vector>
+
+template <typename DataT> class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT>
+{
+    DataT *p;
+
+  public:
+    explicit ShMemIterator(DataT *x) : p(x) {}
+    ShMemIterator(const ShMemIterator &mit) : p(mit.p) {}
+    ShMemIterator &operator++()
+    {
+        ++p;
+        return *this;
+    }
+    ShMemIterator operator++(int)
+    {
+        ShMemIterator tmp(*this);
+        operator++();
+        return tmp;
+    }
+    ShMemIterator operator+(std::ptrdiff_t diff)
+    {
+        ShMemIterator tmp(p + diff);
+        return tmp;
+    }
+    bool operator==(const ShMemIterator &rhs) { return p == rhs.p; }
+    bool operator!=(const ShMemIterator &rhs) { return p != rhs.p; }
+    DataT &operator*() { return *p; }
+};
+
+template <typename DataT> class SharedMemoryWrapper
+{
+  private:
+    DataT *m_ptr;
+    std::size_t m_size;
+
+  public:
+    SharedMemoryWrapper() : m_ptr(nullptr), m_size(0) {}
+
+    SharedMemoryWrapper(DataT *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
+
+    void swap(SharedMemoryWrapper<DataT> &other)
+    {
+        BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
+        std::swap(m_size, other.m_size);
+        std::swap(m_ptr, other.m_ptr);
+    }
+
+    DataT &at(const std::size_t index) { return m_ptr[index]; }
+
+    const DataT &at(const std::size_t index) const { return m_ptr[index]; }
+
+    ShMemIterator<DataT> begin() const { return ShMemIterator<DataT>(m_ptr); }
+
+    ShMemIterator<DataT> end() const { return ShMemIterator<DataT>(m_ptr + m_size); }
+
+    std::size_t size() const { return m_size; }
+
+    bool empty() const { return 0 == size(); }
+
+    DataT &operator[](const unsigned index)
+    {
+        BOOST_ASSERT_MSG(index < m_size, "invalid size");
+        return m_ptr[index];
+    }
+
+    const DataT &operator[](const unsigned index) const
+    {
+        BOOST_ASSERT_MSG(index < m_size, "invalid size");
+        return m_ptr[index];
+    }
+};
+
+template <> class SharedMemoryWrapper<bool>
+{
+  private:
+    unsigned *m_ptr;
+    std::size_t m_size;
+
+  public:
+    SharedMemoryWrapper() : m_ptr(nullptr), m_size(0) {}
+
+    SharedMemoryWrapper(unsigned *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
+
+    void swap(SharedMemoryWrapper<bool> &other)
+    {
+        BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
+        std::swap(m_size, other.m_size);
+        std::swap(m_ptr, other.m_ptr);
+    }
+
+    bool at(const std::size_t index) const
+    {
+        const std::size_t bucket = index / 32;
+        const unsigned offset = static_cast<unsigned>(index % 32);
+        return m_ptr[bucket] & (1 << offset);
+    }
+
+    std::size_t size() const { return m_size; }
+
+    bool empty() const { return 0 == size(); }
+
+    bool operator[](const unsigned index)
+    {
+        BOOST_ASSERT_MSG(index < m_size, "invalid size");
+        const unsigned bucket = index / 32;
+        const unsigned offset = index % 32;
+        return m_ptr[bucket] & (1 << offset);
+    }
+};
+
+template <typename DataT, bool UseSharedMemory> struct ShM
+{
+    typedef typename std::conditional<UseSharedMemory,
+                                      SharedMemoryWrapper<DataT>,
+                                      std::vector<DataT>>::type vector;
+};
+
+#endif // SHARED_MEMORY_VECTOR_WRAPPER_H
diff --git a/DataStructures/SimpleStack.h b/DataStructures/SimpleStack.h
deleted file mode 100644
index 0335bcc..0000000
--- a/DataStructures/SimpleStack.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef SIMPLESTACK_H_
-#define SIMPLESTACK_H_
-
-#include <cassert>
-#include <vector>
-
-template<typename StackItemT, class ContainerT = std::vector<StackItemT> >
-class SimpleStack {
-
-private:
-	int last;
-	ContainerT arr;
-
-public:
-	SimpleStack() : last(-1) {
-	}
-
-	SimpleStack(std::size_t size_hint) : last(-1) {
-		hint(size_hint);
-	}
-
-	inline void hint(std::size_t size_hint) {
-		arr.reserve(size_hint);
-	}
-
-	inline void push(StackItemT t) {
-		++last;
-		arr.push_back(t);
-	}
-
-	inline void pop() {
-		arr.pop_back();
-		--last;
-	}
-
-	inline StackItemT top() {
-		assert (last >= 0);
-		return arr[last];
-	}
-
-	inline int size() {
-		return last+1;
-	}
-
-	inline bool empty() {
-		return (-1 == last);
-	}
-};
-
-
-#endif /* SIMPLESTACK_H_ */
diff --git a/DataStructures/StaticGraph.h b/DataStructures/StaticGraph.h
index eb41683..9210c87 100644
--- a/DataStructures/StaticGraph.h
+++ b/DataStructures/StaticGraph.h
@@ -1,113 +1,156 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef STATIC_GRAPH_H
+#define STATIC_GRAPH_H
+
+#include "../DataStructures/Percent.h"
+#include "../DataStructures/SharedMemoryVectorWrapper.h"
+#include "../Util/SimpleLogger.h"
+#include "../typedefs.h"
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+#include <boost/assert.hpp>
+#include <boost/range/irange.hpp>
 
-#ifndef STATICGRAPH_H_INCLUDED
-#define STATICGRAPH_H_INCLUDED
+#include <tbb/parallel_sort.h>
 
-#include <vector>
 #include <algorithm>
+#include <limits>
+#include <vector>
 
-#include "../typedefs.h"
-#include "ImportEdge.h"
-
-template< typename EdgeDataT>
-class StaticGraph {
-public:
+template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
+{
+  public:
+    typedef decltype(boost::irange(0u,0u)) EdgeRange;
     typedef NodeID NodeIterator;
     typedef NodeID EdgeIterator;
     typedef EdgeDataT EdgeData;
-    class InputEdge {
-    public:
+    class InputEdge
+    {
+      public:
         EdgeDataT data;
         NodeIterator source;
         NodeIterator target;
-        bool operator<( const InputEdge& right ) const {
-            if ( source != right.source )
+        bool operator<(const InputEdge &right) const
+        {
+            if (source != right.source)
+            {
                 return source < right.source;
+            }
             return target < right.target;
         }
     };
 
-    struct _StrNode {
-        //index of the first edge
-        EdgeIterator firstEdge;
+    struct NodeArrayEntry
+    {
+        // index of the first edge
+        EdgeIterator first_edge;
     };
 
-    struct _StrEdge {
+    struct EdgeArrayEntry
+    {
         NodeID target;
         EdgeDataT data;
     };
 
-    StaticGraph( const int nodes, std::vector< InputEdge > &graph ) {
-        std::sort( graph.begin(), graph.end() );
-        _numNodes = nodes;
-        _numEdges = ( EdgeIterator ) graph.size();
-        _nodes.resize( _numNodes + 1);
+    EdgeRange GetAdjacentEdgeRange(const NodeID node) const
+    {
+        return boost::irange(BeginEdges(node), EndEdges(node));
+    }
+
+    StaticGraph(const int nodes, std::vector<InputEdge> &graph)
+    {
+        tbb::parallel_sort(graph.begin(), graph.end());
+        number_of_nodes = nodes;
+        number_of_edges = (EdgeIterator)graph.size();
+        node_array.resize(number_of_nodes + 1);
         EdgeIterator edge = 0;
         EdgeIterator position = 0;
-        for ( NodeIterator node = 0; node <= _numNodes; ++node ) {
-            EdgeIterator lastEdge = edge;
-            while ( edge < _numEdges && graph[edge].source == node )
+        for (NodeIterator node = 0; node <= number_of_nodes; ++node)
+        {
+            EdgeIterator last_edge = edge;
+            while (edge < number_of_edges && graph[edge].source == node)
+            {
                 ++edge;
-            _nodes[node].firstEdge = position; //=edge
-            position += edge - lastEdge; //remove
+            }
+            node_array[node].first_edge = position; //=edge
+            position += edge - last_edge;           // remove
         }
-        _edges.resize( position ); //(edge)
+        edge_array.resize(position); //(edge)
         edge = 0;
-        for ( NodeIterator node = 0; node < _numNodes; ++node ) {
-            for ( EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) {
-                _edges[i].target = graph[edge].target;
-                _edges[i].data = graph[edge].data;
-                assert(_edges[i].data.distance > 0);
+        for (NodeIterator node = 0; node < number_of_nodes; ++node)
+        {
+            EdgeIterator e = node_array[node + 1].first_edge;
+            for (EdgeIterator i = node_array[node].first_edge; i != e; ++i)
+            {
+                edge_array[i].target = graph[edge].target;
+                edge_array[i].data = graph[edge].data;
+                BOOST_ASSERT(edge_array[i].data.distance > 0);
                 edge++;
             }
         }
     }
 
-    StaticGraph( std::vector<_StrNode> & nodes, std::vector<_StrEdge> & edges) {
-        _numNodes = nodes.size();
-        _numEdges = edges.size();
+    StaticGraph(typename ShM<NodeArrayEntry, UseSharedMemory>::vector &nodes,
+                typename ShM<EdgeArrayEntry, UseSharedMemory>::vector &edges)
+    {
+        number_of_nodes = nodes.size() - 1;
+        number_of_edges = edges.size();
 
-        _nodes.swap(nodes);
-        _edges.swap(edges);
-
-        //Add dummy node to end of _nodes array;
-        _nodes.push_back(_nodes.back());
+        node_array.swap(nodes);
+        edge_array.swap(edges);
 
 #ifndef NDEBUG
         Percent p(GetNumberOfNodes());
-        for(unsigned u = 0; u < GetNumberOfNodes(); ++u) {
-            for(unsigned eid = BeginEdges(u); eid < EndEdges(u); ++eid) {
-                unsigned v = GetTarget(eid);
-                EdgeData & data = GetEdgeData(eid);
-                if(data.shortcut) {
-                    unsigned eid2 = FindEdgeInEitherDirection(u, data.id);
-                    if(eid2 == UINT_MAX) {
-                        DEBUG("cannot find first segment of edge (" << u << "," << data.id << "," << v << ")");
-                        data.shortcut = false;
-                    }
-                    eid2 = FindEdgeInEitherDirection(data.id, v);
-                    if(eid2 == UINT_MAX) {
-                        DEBUG("cannot find second segment of edge (" << u << "," << data.id << "," << v << ")");
-                        data.shortcut = false;
-                    }
+        for (unsigned u = 0; u < GetNumberOfNodes(); ++u)
+        {
+            for (auto eid : GetAdjacentEdgeRange(u))
+            {
+                const EdgeData &data = GetEdgeData(eid);
+                if (!data.shortcut)
+                {
+                    continue;
+                }
+                const unsigned v = GetTarget(eid);
+                const EdgeID first_edge_id = FindEdgeInEitherDirection(u, data.id);
+                if (SPECIAL_EDGEID == first_edge_id)
+                {
+                    SimpleLogger().Write(logWARNING) << "cannot find first segment of edge ("
+                                                     << u << "," << data.id << "," << v
+                                                     << "), eid: " << eid;
+                    BOOST_ASSERT(false);
+                }
+                const EdgeID second_edge_id = FindEdgeInEitherDirection(data.id, v);
+                if (SPECIAL_EDGEID == second_edge_id)
+                {
+                    SimpleLogger().Write(logWARNING) << "cannot find second segment of edge ("
+                                                     << u << "," << data.id << "," << v
+                                                     << "), eid: " << eid;
+                    BOOST_ASSERT(false);
                 }
             }
             p.printIncrement();
@@ -115,74 +158,76 @@ public:
 #endif
     }
 
-    unsigned GetNumberOfNodes() const {
-        return _numNodes;
-    }
+    unsigned GetNumberOfNodes() const { return number_of_nodes -1; }
 
-    unsigned GetNumberOfEdges() const {
-        return _numEdges;
-    }
+    unsigned GetNumberOfEdges() const { return number_of_edges; }
 
-    unsigned GetOutDegree( const NodeIterator &n ) const {
-        return BeginEdges(n)-EndEdges(n) - 1;
-    }
+    unsigned GetOutDegree(const NodeIterator n) const { return BeginEdges(n) - EndEdges(n) - 1; }
 
-    inline NodeIterator GetTarget( const EdgeIterator &e ) const {
-        return NodeIterator( _edges[e].target );
+    inline NodeIterator GetTarget(const EdgeIterator e) const
+    {
+        return NodeIterator(edge_array[e].target);
     }
 
-    inline EdgeDataT &GetEdgeData( const EdgeIterator &e ) {
-        return _edges[e].data;
-    }
+    inline EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_array[e].data; }
 
-    const EdgeDataT &GetEdgeData( const EdgeIterator &e ) const {
-        return _edges[e].data;
-    }
+    const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return edge_array[e].data; }
 
-    EdgeIterator BeginEdges( const NodeIterator &n ) const {
-        return EdgeIterator( _nodes[n].firstEdge );
+    EdgeIterator BeginEdges(const NodeIterator n) const
+    {
+        return EdgeIterator(node_array.at(n).first_edge);
     }
 
-    EdgeIterator EndEdges( const NodeIterator &n ) const {
-        return EdgeIterator( _nodes[n+1].firstEdge );
+    EdgeIterator EndEdges(const NodeIterator n) const
+    {
+        return EdgeIterator(node_array.at(n + 1).first_edge);
     }
 
-    //searches for a specific edge
-    EdgeIterator FindEdge( const NodeIterator &from, const NodeIterator &to ) const {
-        EdgeIterator smallestEdge = SPECIAL_EDGEID;
-        EdgeWeight smallestWeight = UINT_MAX;
-        for ( EdgeIterator edge = BeginEdges( from ); edge < EndEdges(from); edge++ ) {
+    // searches for a specific edge
+    EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
+    {
+        EdgeIterator smallest_edge = SPECIAL_EDGEID;
+        EdgeWeight smallest_weight = INVALID_EDGE_WEIGHT;
+        for (auto edge : GetAdjacentEdgeRange(from))
+        {
             const NodeID target = GetTarget(edge);
             const EdgeWeight weight = GetEdgeData(edge).distance;
-            if(target == to && weight < smallestWeight) {
-                smallestEdge = edge; smallestWeight = weight;
+            if (target == to && weight < smallest_weight)
+            {
+                smallest_edge = edge;
+                smallest_weight = weight;
             }
         }
-        return smallestEdge;
+        return smallest_edge;
     }
 
-    EdgeIterator FindEdgeInEitherDirection( const NodeIterator &from, const NodeIterator &to ) const {
-        EdgeIterator tmp =  FindEdge( from, to );
-        return (UINT_MAX != tmp ? tmp : FindEdge( to, from ));
+    EdgeIterator FindEdgeInEitherDirection(const NodeIterator from, const NodeIterator to) const
+    {
+        EdgeIterator tmp = FindEdge(from, to);
+        return (SPECIAL_NODEID != tmp ? tmp : FindEdge(to, from));
     }
 
-    EdgeIterator FindEdgeIndicateIfReverse( const NodeIterator &from, const NodeIterator &to, bool & result ) const {
-        EdgeIterator tmp =  FindEdge( from, to );
-        if(UINT_MAX == tmp) {
-            tmp =  FindEdge( to, from );
-            if(UINT_MAX != tmp)
+    EdgeIterator
+    FindEdgeIndicateIfReverse(const NodeIterator from, const NodeIterator to, bool &result) const
+    {
+        EdgeIterator current_iterator = FindEdge(from, to);
+        if (SPECIAL_NODEID == current_iterator)
+        {
+            current_iterator = FindEdge(to, from);
+            if (SPECIAL_NODEID != current_iterator)
+            {
                 result = true;
+            }
         }
-        return tmp;
+        return current_iterator;
     }
 
-private:
-
-    NodeIterator _numNodes;
-    EdgeIterator _numEdges;
+  private:
+    NodeIterator number_of_nodes;
+    EdgeIterator number_of_edges;
 
-    std::vector< _StrNode > _nodes;
-    std::vector< _StrEdge > _edges;
+    typename ShM<NodeArrayEntry, UseSharedMemory>::vector node_array;
+    typename ShM<EdgeArrayEntry, UseSharedMemory>::vector edge_array;
 };
 
-#endif // STATICGRAPH_H_INCLUDED
+#endif // STATIC_GRAPH_H
diff --git a/DataStructures/StaticKDTree.h b/DataStructures/StaticKDTree.h
index 85ffb80..e36eee9 100644
--- a/DataStructures/StaticKDTree.h
+++ b/DataStructures/StaticKDTree.h
@@ -1,45 +1,55 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-KD Tree coded by Christian Vetter, Monav Project
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+// KD Tree coded by Christian Vetter, Monav Project
 
- */
 #ifndef STATICKDTREE_H_INCLUDED
 #define STATICKDTREE_H_INCLUDED
 
-#include <cassert>
+#include <boost/assert.hpp>
 #include <vector>
 #include <algorithm>
 #include <stack>
 #include <limits>
 
-namespace KDTree {
+namespace KDTree
+{
 
 #define KDTREE_BASESIZE (8)
 
-template< unsigned k, typename T >
-class BoundingBox {
-public:
-    BoundingBox() {
-        for ( unsigned dim = 0; dim < k; ++dim ) {
-            min[dim] = std::numeric_limits< T >::min();
-            max[dim] = std::numeric_limits< T >::max();
+template <unsigned k, typename T> class BoundingBox
+{
+  public:
+    BoundingBox()
+    {
+        for (unsigned dim = 0; dim < k; ++dim)
+        {
+            min[dim] = std::numeric_limits<T>::min();
+            max[dim] = std::numeric_limits<T>::max();
         }
     }
 
@@ -47,102 +57,118 @@ public:
     T max[k];
 };
 
-struct NoData {};
+struct NoData
+{
+};
 
-template< unsigned k, typename T >
-class EuclidianMetric {
-public:
-    double operator() ( const T left[k], const T right[k] ) {
+template <unsigned k, typename T> class EuclidianMetric
+{
+  public:
+    double operator()(const T left[k], const T right[k])
+    {
         double result = 0;
-        for ( unsigned i = 0; i < k; ++i ) {
+        for (unsigned i = 0; i < k; ++i)
+        {
             double temp = (double)left[i] - (double)right[i];
             result += temp * temp;
         }
         return result;
     }
 
-    double operator() ( const BoundingBox< k, T > &box, const T point[k] ) {
+    double operator()(const BoundingBox<k, T> &box, const T point[k])
+    {
         T nearest[k];
-        for ( unsigned dim = 0; dim < k; ++dim ) {
-            if ( point[dim] < box.min[dim] )
+        for (unsigned dim = 0; dim < k; ++dim)
+        {
+            if (point[dim] < box.min[dim])
                 nearest[dim] = box.min[dim];
-            else if ( point[dim] > box.max[dim] )
+            else if (point[dim] > box.max[dim])
                 nearest[dim] = box.max[dim];
             else
                 nearest[dim] = point[dim];
         }
-        return operator() ( point, nearest );
+        return operator()(point, nearest);
     }
 };
 
-template < unsigned k, typename T, typename Data = NoData, typename Metric = EuclidianMetric< k, T > >
-class StaticKDTree {
-public:
-
-    struct InputPoint {
+template <unsigned k, typename T, typename Data = NoData, typename Metric = EuclidianMetric<k, T>>
+class StaticKDTree
+{
+  public:
+    struct InputPoint
+    {
         T coordinates[k];
         Data data;
-        bool operator==( const InputPoint& right )
-		                {
-            for ( int i = 0; i < k; i++ ) {
-                if ( coordinates[i] != right.coordinates[i] )
+        bool operator==(const InputPoint &right)
+        {
+            for (int i = 0; i < k; i++)
+            {
+                if (coordinates[i] != right.coordinates[i])
                     return false;
             }
             return true;
-		                }
+        }
     };
 
-    StaticKDTree( std::vector< InputPoint > * points ){
-        assert( k > 0 );
-        assert ( points->size() > 0 );
+    explicit StaticKDTree(std::vector<InputPoint> *points)
+    {
+        BOOST_ASSERT(k > 0);
+        BOOST_ASSERT(points->size() > 0);
         size = points->size();
         kdtree = new InputPoint[size];
-        for ( Iterator i = 0; i != size; ++i ) {
+        for (Iterator i = 0; i != size; ++i)
+        {
             kdtree[i] = points->at(i);
-            for ( unsigned dim = 0; dim < k; ++dim ) {
-                if ( kdtree[i].coordinates[dim] < boundingBox.min[dim] )
+            for (unsigned dim = 0; dim < k; ++dim)
+            {
+                if (kdtree[i].coordinates[dim] < boundingBox.min[dim])
                     boundingBox.min[dim] = kdtree[i].coordinates[dim];
-                if ( kdtree[i].coordinates[dim] > boundingBox.max[dim] )
+                if (kdtree[i].coordinates[dim] > boundingBox.max[dim])
                     boundingBox.max[dim] = kdtree[i].coordinates[dim];
             }
         }
-        std::stack< Tree > s;
-        s.push ( Tree ( 0, size, 0 ) );
-        while ( !s.empty() ) {
+        std::stack<Tree> s;
+        s.push(Tree(0, size, 0));
+        while (!s.empty())
+        {
             Tree tree = s.top();
             s.pop();
 
-            if ( tree.right - tree.left < KDTREE_BASESIZE )
+            if (tree.right - tree.left < KDTREE_BASESIZE)
                 continue;
 
-            Iterator middle = tree.left + ( tree.right - tree.left ) / 2;
-            std::nth_element( kdtree + tree.left, kdtree + middle, kdtree + tree.right, Less( tree.dimension ) );
-            s.push( Tree( tree.left, middle, ( tree.dimension + 1 ) % k ) );
-            s.push( Tree( middle + 1, tree.right, ( tree.dimension + 1 ) % k ) );
+            Iterator middle = tree.left + (tree.right - tree.left) / 2;
+            std::nth_element(
+                kdtree + tree.left, kdtree + middle, kdtree + tree.right, Less(tree.dimension));
+            s.push(Tree(tree.left, middle, (tree.dimension + 1) % k));
+            s.push(Tree(middle + 1, tree.right, (tree.dimension + 1) % k));
         }
     }
 
-    ~StaticKDTree(){
-        delete[] kdtree;
-    }
+    ~StaticKDTree() { delete[] kdtree; }
 
-    bool NearestNeighbor( InputPoint* result, const InputPoint& point ) {
+    bool NearestNeighbor(InputPoint *result, const InputPoint &point)
+    {
         Metric distance;
         bool found = false;
-        double nearestDistance = std::numeric_limits< T >::max();
-        std::stack< NNTree > s;
-        s.push ( NNTree ( 0, size, 0, boundingBox ) );
-        while ( !s.empty() ) {
+        double nearestDistance = std::numeric_limits<T>::max();
+        std::stack<NNTree> s;
+        s.push(NNTree(0, size, 0, boundingBox));
+        while (!s.empty())
+        {
             NNTree tree = s.top();
             s.pop();
 
-            if ( distance( tree.box, point.coordinates ) >= nearestDistance )
+            if (distance(tree.box, point.coordinates) >= nearestDistance)
                 continue;
 
-            if ( tree.right - tree.left < KDTREE_BASESIZE ) {
-                for ( unsigned i = tree.left; i < tree.right; i++ ) {
-                    double newDistance = distance( kdtree[i].coordinates, point.coordinates );
-                    if ( newDistance < nearestDistance ) {
+            if (tree.right - tree.left < KDTREE_BASESIZE)
+            {
+                for (unsigned i = tree.left; i < tree.right; i++)
+                {
+                    double newDistance = distance(kdtree[i].coordinates, point.coordinates);
+                    if (newDistance < nearestDistance)
+                    {
                         nearestDistance = newDistance;
                         *result = kdtree[i];
                         found = true;
@@ -151,73 +177,84 @@ public:
                 continue;
             }
 
-            Iterator middle = tree.left + ( tree.right - tree.left ) / 2;
+            Iterator middle = tree.left + (tree.right - tree.left) / 2;
 
-            double newDistance = distance( kdtree[middle].coordinates, point.coordinates );
-            if ( newDistance < nearestDistance ) {
+            double newDistance = distance(kdtree[middle].coordinates, point.coordinates);
+            if (newDistance < nearestDistance)
+            {
                 nearestDistance = newDistance;
                 *result = kdtree[middle];
                 found = true;
             }
 
-            Less comperator( tree.dimension );
-            if ( !comperator( point, kdtree[middle] ) ) {
-                NNTree first( middle + 1, tree.right, ( tree.dimension + 1 ) % k, tree.box );
-                NNTree second( tree.left, middle, ( tree.dimension + 1 ) % k, tree.box );
+            Less comperator(tree.dimension);
+            if (!comperator(point, kdtree[middle]))
+            {
+                NNTree first(middle + 1, tree.right, (tree.dimension + 1) % k, tree.box);
+                NNTree second(tree.left, middle, (tree.dimension + 1) % k, tree.box);
                 first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
                 second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
-                s.push( second );
-                s.push( first );
+                s.push(second);
+                s.push(first);
             }
-            else {
-                NNTree first( middle + 1, tree.right, ( tree.dimension + 1 ) % k, tree.box );
-                NNTree second( tree.left, middle, ( tree.dimension + 1 ) % k, tree.box );
+            else
+            {
+                NNTree first(middle + 1, tree.right, (tree.dimension + 1) % k, tree.box);
+                NNTree second(tree.left, middle, (tree.dimension + 1) % k, tree.box);
                 first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
                 second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
-                s.push( first );
-                s.push( second );
+                s.push(first);
+                s.push(second);
             }
         }
         return found;
     }
 
-private:
+  private:
     typedef unsigned Iterator;
-    struct Tree {
+    struct Tree
+    {
         Iterator left;
         Iterator right;
         unsigned dimension;
         Tree() {}
-        Tree( Iterator l, Iterator r, unsigned d ): left( l ), right( r ), dimension( d ) {}
+        Tree(Iterator l, Iterator r, unsigned d) : left(l), right(r), dimension(d) {}
     };
-    struct NNTree {
+    struct NNTree
+    {
         Iterator left;
         Iterator right;
         unsigned dimension;
-        BoundingBox< k, T > box;
+        BoundingBox<k, T> box;
         NNTree() {}
-        NNTree( Iterator l, Iterator r, unsigned d, const BoundingBox< k, T >& b ): left( l ), right( r ), dimension( d ), box ( b ) {}
+        NNTree(Iterator l, Iterator r, unsigned d, const BoundingBox<k, T> &b)
+            : left(l), right(r), dimension(d), box(b)
+        {
+        }
     };
-    class Less {
-    public:
-        Less( unsigned d ) {
+    class Less
+    {
+      public:
+        explicit Less(unsigned d)
+        {
             dimension = d;
-            assert( dimension < k );
+            BOOST_ASSERT(dimension < k);
         }
 
-        bool operator() ( const InputPoint& left, const InputPoint& right ) {
-            assert( dimension < k );
+        bool operator()(const InputPoint &left, const InputPoint &right)
+        {
+            BOOST_ASSERT(dimension < k);
             return left.coordinates[dimension] < right.coordinates[dimension];
         }
-    private:
+
+      private:
         unsigned dimension;
     };
 
-    BoundingBox< k, T > boundingBox;
-    InputPoint* kdtree;
+    BoundingBox<k, T> boundingBox;
+    InputPoint *kdtree;
     Iterator size;
 };
-
 }
 
 #endif // STATICKDTREE_H_INCLUDED
diff --git a/DataStructures/StaticRTree.h b/DataStructures/StaticRTree.h
index b85516f..ce306ad 100644
--- a/DataStructures/StaticRTree.h
+++ b/DataStructures/StaticRTree.h
@@ -1,909 +1,1036 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef STATICRTREE_H_
-#define STATICRTREE_H_
-
-#include "MercatorUtil.h"
-#include "TimingUtil.h"
-#include "Coordinate.h"
-#include "PhantomNodes.h"
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef STATICRTREE_H
+#define STATICRTREE_H
+
 #include "DeallocatingVector.h"
 #include "HilbertValue.h"
+#include "PhantomNodes.h"
+#include "QueryNode.h"
+#include "SharedMemoryFactory.h"
+#include "SharedMemoryVectorWrapper.h"
+
+#include "../Util/MercatorUtil.h"
+#include "../Util/OSRMException.h"
+#include "../Util/SimpleLogger.h"
+#include "../Util/TimingUtil.h"
 #include "../typedefs.h"
 
+#include <osrm/Coordinate.h>
+
 #include <boost/assert.hpp>
-#include <boost/bind.hpp>
-#include <boost/foreach.hpp>
-#include <boost/algorithm/minmax.hpp>
-#include <boost/algorithm/minmax_element.hpp>
-#include <boost/range/algorithm_ext/erase.hpp>
-#include <boost/noncopyable.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
 #include <boost/thread.hpp>
+#include <boost/variant.hpp>
 
-#include <cassert>
-#include <cfloat>
-#include <climits>
+#include <tbb/parallel_for.h>
+#include <tbb/parallel_sort.h>
 
 #include <algorithm>
-#include <fstream>
+#include <array>
+#include <limits>
+#include <memory>
 #include <queue>
+#include <string>
 #include <vector>
 
-//tuning parameters
-const static uint32_t RTREE_BRANCHING_FACTOR = 50;
-const static uint32_t RTREE_LEAF_NODE_SIZE = 1170;
-
-// Implements a static, i.e. packed, R-tree
+// tuning parameters
+const static uint32_t RTREE_BRANCHING_FACTOR = 64;
+const static uint32_t RTREE_LEAF_NODE_SIZE = 1024;
 
-static boost::thread_specific_ptr<std::ifstream> thread_local_rtree_stream;
+static boost::thread_specific_ptr<boost::filesystem::ifstream> thread_local_rtree_stream;
 
-template<class DataT>
-class StaticRTree : boost::noncopyable {
-private:
-    struct RectangleInt2D {
-        RectangleInt2D() :
-            min_lon(INT_MAX),
-            max_lon(INT_MIN),
-            min_lat(INT_MAX),
-            max_lat(INT_MIN) {}
+// Implements a static, i.e. packed, R-tree
+template <class EdgeDataT,
+          class CoordinateListT = std::vector<FixedPointCoordinate>,
+          bool UseSharedMemory = false>
+class StaticRTree
+{
+  public:
+    struct RectangleInt2D
+    {
+        RectangleInt2D() : min_lon(INT_MAX), max_lon(INT_MIN), min_lat(INT_MAX), max_lat(INT_MIN) {}
 
         int32_t min_lon, max_lon;
         int32_t min_lat, max_lat;
 
-        inline void InitializeMBRectangle(
-                const DataT * objects,
-                const uint32_t element_count
-        ) {
-            for(uint32_t i = 0; i < element_count; ++i) {
-                min_lon = std::min(
-                        min_lon, std::min(objects[i].lon1, objects[i].lon2)
-                );
-                max_lon = std::max(
-                        max_lon, std::max(objects[i].lon1, objects[i].lon2)
-                );
-
-                min_lat = std::min(
-                        min_lat, std::min(objects[i].lat1, objects[i].lat2)
-                );
-                max_lat = std::max(
-                        max_lat, std::max(objects[i].lat1, objects[i].lat2)
-                );
+        inline void InitializeMBRectangle(const std::array<EdgeDataT, RTREE_LEAF_NODE_SIZE> &objects,
+                                          const uint32_t element_count,
+                                          const std::vector<NodeInfo> &coordinate_list)
+        {
+            for (uint32_t i = 0; i < element_count; ++i)
+            {
+                min_lon = std::min(min_lon,
+                                   std::min(coordinate_list.at(objects[i].u).lon,
+                                            coordinate_list.at(objects[i].v).lon));
+                max_lon = std::max(max_lon,
+                                   std::max(coordinate_list.at(objects[i].u).lon,
+                                            coordinate_list.at(objects[i].v).lon));
+
+                min_lat = std::min(min_lat,
+                                   std::min(coordinate_list.at(objects[i].u).lat,
+                                            coordinate_list.at(objects[i].v).lat));
+                max_lat = std::max(max_lat,
+                                   std::max(coordinate_list.at(objects[i].u).lat,
+                                            coordinate_list.at(objects[i].v).lat));
             }
+            BOOST_ASSERT(min_lat != std::numeric_limits<int>::min());
+            BOOST_ASSERT(min_lon != std::numeric_limits<int>::min());
+            BOOST_ASSERT(max_lat != std::numeric_limits<int>::min());
+            BOOST_ASSERT(max_lon != std::numeric_limits<int>::min());
         }
 
-        inline void AugmentMBRectangle(const RectangleInt2D & other) {
+        inline void MergeBoundingBoxes(const RectangleInt2D &other)
+        {
             min_lon = std::min(min_lon, other.min_lon);
             max_lon = std::max(max_lon, other.max_lon);
             min_lat = std::min(min_lat, other.min_lat);
             max_lat = std::max(max_lat, other.max_lat);
+            BOOST_ASSERT(min_lat != std::numeric_limits<int>::min());
+            BOOST_ASSERT(min_lon != std::numeric_limits<int>::min());
+            BOOST_ASSERT(max_lat != std::numeric_limits<int>::min());
+            BOOST_ASSERT(max_lon != std::numeric_limits<int>::min());
         }
 
-        inline _Coordinate Centroid() const {
-            _Coordinate centroid;
-            //The coordinates of the midpoints are given by:
-            //x = (x1 + x2) /2 and y = (y1 + y2) /2.
-            centroid.lon = (min_lon + max_lon)/2;
-            centroid.lat = (min_lat + max_lat)/2;
+        inline FixedPointCoordinate Centroid() const
+        {
+            FixedPointCoordinate centroid;
+            // The coordinates of the midpoints are given by:
+            // x = (x1 + x2) /2 and y = (y1 + y2) /2.
+            centroid.lon = (min_lon + max_lon) / 2;
+            centroid.lat = (min_lat + max_lat) / 2;
             return centroid;
         }
 
-        inline bool Intersects(const RectangleInt2D & other) const {
-            _Coordinate upper_left (other.max_lat, other.min_lon);
-            _Coordinate upper_right(other.max_lat, other.max_lon);
-            _Coordinate lower_right(other.min_lat, other.max_lon);
-            _Coordinate lower_left (other.min_lat, other.min_lon);
+        inline bool Intersects(const RectangleInt2D &other) const
+        {
+            FixedPointCoordinate upper_left(other.max_lat, other.min_lon);
+            FixedPointCoordinate upper_right(other.max_lat, other.max_lon);
+            FixedPointCoordinate lower_right(other.min_lat, other.max_lon);
+            FixedPointCoordinate lower_left(other.min_lat, other.min_lon);
 
-            return (
-                    Contains(upper_left)
-                    || Contains(upper_right)
-                    || Contains(lower_right)
-                    || Contains(lower_left)
-            );
+            return (Contains(upper_left) || Contains(upper_right) || Contains(lower_right) ||
+                    Contains(lower_left));
         }
 
-        inline double GetMinDist(const _Coordinate & location) const {
-            bool is_contained = Contains(location);
-            if (is_contained) {
-                return 0.0;
+        inline float GetMinDist(const FixedPointCoordinate &location) const
+        {
+            const bool is_contained = Contains(location);
+            if (is_contained)
+            {
+                return 0.;
             }
 
-            double min_dist = DBL_MAX;
-            min_dist = std::min(
-                    min_dist,
-                    ApproximateDistance(
-                            location.lat,
-                            location.lon,
-                            max_lat,
-                            min_lon
-                    )
-            );
-            min_dist = std::min(
-                    min_dist,
-                    ApproximateDistance(
-                            location.lat,
-                            location.lon,
-                            max_lat,
-                            max_lon
-                    )
-            );
-            min_dist = std::min(
-                    min_dist,
-                    ApproximateDistance(
-                            location.lat,
-                            location.lon,
-                            min_lat,
-                            max_lon
-                    )
-            );
-            min_dist = std::min(
-                    min_dist,
-                    ApproximateDistance(
-                            location.lat,
-                            location.lon,
-                            min_lat,
-                            min_lon
-                    )
-            );
+            float min_dist = std::numeric_limits<float>::max();
+            min_dist = std::min(min_dist,
+                                FixedPointCoordinate::ApproximateEuclideanDistance(
+                                    location.lat, location.lon, max_lat, min_lon));
+            min_dist = std::min(min_dist,
+                                FixedPointCoordinate::ApproximateEuclideanDistance(
+                                    location.lat, location.lon, max_lat, max_lon));
+            min_dist = std::min(min_dist,
+                                FixedPointCoordinate::ApproximateEuclideanDistance(
+                                    location.lat, location.lon, min_lat, max_lon));
+            min_dist = std::min(min_dist,
+                                FixedPointCoordinate::ApproximateEuclideanDistance(
+                                    location.lat, location.lon, min_lat, min_lon));
             return min_dist;
         }
 
-        inline double GetMinMaxDist(const _Coordinate & location) const {
-            double min_max_dist = DBL_MAX;
-            //Get minmax distance to each of the four sides
-            _Coordinate upper_left (max_lat, min_lon);
-            _Coordinate upper_right(max_lat, max_lon);
-            _Coordinate lower_right(min_lat, max_lon);
-            _Coordinate lower_left (min_lat, min_lon);
+        inline float GetMinMaxDist(const FixedPointCoordinate &location) const
+        {
+            float min_max_dist = std::numeric_limits<float>::max();
+            // Get minmax distance to each of the four sides
+            FixedPointCoordinate upper_left(max_lat, min_lon);
+            FixedPointCoordinate upper_right(max_lat, max_lon);
+            FixedPointCoordinate lower_right(min_lat, max_lon);
+            FixedPointCoordinate lower_left(min_lat, min_lon);
 
             min_max_dist = std::min(
-                    min_max_dist,
-                    std::max(
-                            ApproximateDistance(location, upper_left ),
-                            ApproximateDistance(location, upper_right)
-                    )
-            );
+                min_max_dist,
+                std::max(
+                    FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left),
+                    FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right)));
 
             min_max_dist = std::min(
-                    min_max_dist,
-                    std::max(
-                            ApproximateDistance(location, upper_right),
-                            ApproximateDistance(location, lower_right)
-                    )
-            );
+                min_max_dist,
+                std::max(
+                    FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right),
+                    FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right)));
 
             min_max_dist = std::min(
-                    min_max_dist,
-                    std::max(
-                            ApproximateDistance(location, lower_right),
-                            ApproximateDistance(location, lower_left )
-                    )
-            );
+                min_max_dist,
+                std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right),
+                         FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left)));
 
             min_max_dist = std::min(
-                    min_max_dist,
-                    std::max(
-                            ApproximateDistance(location, lower_left ),
-                            ApproximateDistance(location, upper_left )
-                    )
-            );
+                min_max_dist,
+                std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left),
+                         FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left)));
             return min_max_dist;
         }
 
-        inline bool Contains(const _Coordinate & location) const {
-            bool lats_contained =
-                    (location.lat > min_lat) && (location.lat < max_lat);
-            bool lons_contained =
-                    (location.lon > min_lon) && (location.lon < max_lon);
+        inline bool Contains(const FixedPointCoordinate &location) const
+        {
+            const bool lats_contained = (location.lat > min_lat) && (location.lat < max_lat);
+            const bool lons_contained = (location.lon > min_lon) && (location.lon < max_lon);
             return lats_contained && lons_contained;
         }
 
-        inline friend std::ostream & operator<< ( std::ostream & out, const RectangleInt2D & rect ) {
-            out << rect.min_lat/100000. << "," << rect.min_lon/100000. << " " << rect.max_lat/100000. << "," << rect.max_lon/100000.;
+        inline friend std::ostream &operator<<(std::ostream &out, const RectangleInt2D &rect)
+        {
+            out << rect.min_lat / COORDINATE_PRECISION << "," << rect.min_lon / COORDINATE_PRECISION
+                << " " << rect.max_lat / COORDINATE_PRECISION << ","
+                << rect.max_lon / COORDINATE_PRECISION;
             return out;
         }
     };
 
     typedef RectangleInt2D RectangleT;
 
-    struct WrappedInputElement {
-        explicit WrappedInputElement(const uint32_t _array_index, const uint64_t _hilbert_value) :
-			        m_array_index(_array_index), m_hilbert_value(_hilbert_value) {}
-        WrappedInputElement() : m_array_index(UINT_MAX), m_hilbert_value(0) {}
+    struct TreeNode
+    {
+        TreeNode() : child_count(0), child_is_on_disk(false) {}
+        RectangleT minimum_bounding_rectangle;
+        uint32_t child_count : 31;
+        bool child_is_on_disk : 1;
+        uint32_t children[RTREE_BRANCHING_FACTOR];
+    };
+
+  private:
+    struct WrappedInputElement
+    {
+        explicit WrappedInputElement(const uint64_t _hilbert_value, const uint32_t _array_index)
+            : m_hilbert_value(_hilbert_value), m_array_index(_array_index)
+        {
+        }
+
+        WrappedInputElement() : m_hilbert_value(0), m_array_index(UINT_MAX) {}
 
-        uint32_t m_array_index;
         uint64_t m_hilbert_value;
+        uint32_t m_array_index;
 
-        inline bool operator<(const WrappedInputElement & other) const {
+        inline bool operator<(const WrappedInputElement &other) const
+        {
             return m_hilbert_value < other.m_hilbert_value;
         }
     };
 
-    struct LeafNode {
+    struct LeafNode
+    {
         LeafNode() : object_count(0) {}
         uint32_t object_count;
-        DataT objects[RTREE_LEAF_NODE_SIZE];
+        std::array<EdgeDataT, RTREE_LEAF_NODE_SIZE> objects;
     };
 
-    struct TreeNode {
-        TreeNode() : child_count(0), child_is_on_disk(false) {}
-        RectangleT minimum_bounding_rectangle;
-        uint32_t child_count:31;
-        bool child_is_on_disk:1;
-        uint32_t children[RTREE_BRANCHING_FACTOR];
+    struct QueryCandidate
+    {
+        explicit QueryCandidate(const float dist, const uint32_t n_id)
+            : min_dist(dist), node_id(n_id)
+        {
+        }
+        QueryCandidate() : min_dist(std::numeric_limits<float>::max()), node_id(UINT_MAX) {}
+        float min_dist;
+        uint32_t node_id;
+        inline bool operator<(const QueryCandidate &other) const
+        {
+            // Attn: this is reversed order. std::pq is a max pq!
+            return other.min_dist < min_dist;
+        }
     };
 
-    struct QueryCandidate {
-        explicit QueryCandidate(const uint32_t n_id, const double dist) : node_id(n_id), min_dist(dist)/*, minmax_dist(DBL_MAX)*/ {}
-        QueryCandidate() : node_id(UINT_MAX), min_dist(DBL_MAX)/*, minmax_dist(DBL_MAX)*/ {}
-        uint32_t node_id;
-        double min_dist;
-        //		double minmax_dist;
-        inline bool operator<(const QueryCandidate & other) const {
-            return min_dist < other.min_dist;
+    typedef boost::variant<TreeNode, EdgeDataT> IncrementalQueryNodeType;
+    struct IncrementalQueryCandidate
+    {
+        explicit IncrementalQueryCandidate(const float dist, const IncrementalQueryNodeType &node)
+            : min_dist(dist), node(node)
+        {
+        }
+
+        IncrementalQueryCandidate() : min_dist(std::numeric_limits<float>::max()) {}
+
+        inline bool operator<(const IncrementalQueryCandidate &other) const
+        {
+            // Attn: this is reversed order. std::pq is a max pq!
+            return other.min_dist < min_dist;
         }
+
+        inline bool RepresentsTreeNode() const
+        {
+            return boost::apply_visitor(decide_type_visitor(), node);
+        }
+
+        float min_dist;
+        IncrementalQueryNodeType node;
+
+      private:
+        class decide_type_visitor : public boost::static_visitor<bool>
+        {
+          public:
+            bool operator()(const TreeNode &) const { return true; }
+
+            template<typename AnotherType>
+            bool operator()(const AnotherType &) const { return false; }
+        };
     };
 
-    std::vector<TreeNode> m_search_tree;
+    typename ShM<TreeNode, UseSharedMemory>::vector m_search_tree;
     uint64_t m_element_count;
+    const std::string m_leaf_node_filename;
+    std::shared_ptr<CoordinateListT> m_coordinate_list;
+
+  public:
+    StaticRTree() = delete;
+    StaticRTree(const StaticRTree &) = delete;
+
+    // Construct a packed Hilbert-R-Tree with Kamel-Faloutsos algorithm [1]
+    explicit StaticRTree(std::vector<EdgeDataT> &input_data_vector,
+                         const std::string tree_node_filename,
+                         const std::string leaf_node_filename,
+                         const std::vector<NodeInfo> &coordinate_list)
+        : m_element_count(input_data_vector.size()), m_leaf_node_filename(leaf_node_filename)
+    {
+        SimpleLogger().Write() << "constructing r-tree of " << m_element_count
+                               << " edge elements build on-top of " << coordinate_list.size()
+                               << " coordinates";
+
+        TIMER_START(construction);
+        std::vector<WrappedInputElement> input_wrapper_vector(m_element_count);
+
+        HilbertCode get_hilbert_number;
+
+        // generate auxiliary vector of hilbert-values
+        tbb::parallel_for(
+            tbb::blocked_range<uint64_t>(0, m_element_count),
+            [&input_data_vector, &input_wrapper_vector, &get_hilbert_number, &coordinate_list](
+                const tbb::blocked_range<uint64_t> &range)
+            {
+                for (uint64_t element_counter = range.begin(); element_counter != range.end();
+                     ++element_counter)
+                {
+                    WrappedInputElement &current_wrapper = input_wrapper_vector[element_counter];
+                    current_wrapper.m_array_index = element_counter;
+
+                    EdgeDataT const &current_element = input_data_vector[element_counter];
+
+                    // Get Hilbert-Value for centroid in mercartor projection
+                    FixedPointCoordinate current_centroid = EdgeDataT::Centroid(
+                        FixedPointCoordinate(coordinate_list.at(current_element.u).lat,
+                                             coordinate_list.at(current_element.u).lon),
+                        FixedPointCoordinate(coordinate_list.at(current_element.v).lat,
+                                             coordinate_list.at(current_element.v).lon));
+                    current_centroid.lat =
+                        COORDINATE_PRECISION * lat2y(current_centroid.lat / COORDINATE_PRECISION);
+
+                    current_wrapper.m_hilbert_value = get_hilbert_number(current_centroid);
+                }
+            });
+
+        // open leaf file
+        boost::filesystem::ofstream leaf_node_file(leaf_node_filename, std::ios::binary);
+        leaf_node_file.write((char *)&m_element_count, sizeof(uint64_t));
 
-    std::string m_leaf_node_filename;
-public:
-    //Construct a pack R-Tree from the input-list with Kamel-Faloutsos algorithm [1]
-    explicit StaticRTree(std::vector<DataT> & input_data_vector, const char * tree_node_filename, const char * leaf_node_filename) :
-    m_leaf_node_filename(leaf_node_filename) {
-        m_element_count = input_data_vector.size();
-        //remove elements that are flagged to be ignored
-//        boost::remove_erase_if(input_data_vector, boost::bind(&DataT::isIgnored, _1 ));
-
-        INFO("constructing r-tree of " << m_element_count << " elements");
-//        INFO("sizeof(LeafNode)=" << sizeof(LeafNode));
-//        INFO("sizeof(TreeNode)=" << sizeof(TreeNode));
-//        INFO("sizeof(WrappedInputElement)=" << sizeof(WrappedInputElement));
-        double time1 = get_timestamp();
-        std::vector<WrappedInputElement> input_wrapper_vector(input_data_vector.size());
-
-        //generate auxiliary vector of hilbert-values
-#pragma omp parallel for schedule(guided)
-        for(uint64_t element_counter = 0; element_counter < m_element_count; ++element_counter) {
-            //INFO("ID: " << input_data_vector[element_counter].id);
-            input_wrapper_vector[element_counter].m_array_index = element_counter;
-            //Get Hilbert-Value for centroid in mercartor projection
-            DataT & current_element = input_data_vector[element_counter];
-            _Coordinate current_centroid = current_element.Centroid();
-            current_centroid.lat = 100000*lat2y(current_centroid.lat/100000.);
-
-            uint64_t current_hilbert_value = HilbertCode::GetHilbertNumberForCoordinate(current_centroid);
-            input_wrapper_vector[element_counter].m_hilbert_value = current_hilbert_value;
-
-        }
-        //INFO("finished wrapper setup");
-
-        //open leaf file
-        std::ofstream leaf_node_file(leaf_node_filename, std::ios::binary);
-        leaf_node_file.write((char*) &m_element_count, sizeof(uint64_t));
-
-        //sort the hilbert-value representatives
-        std::sort(input_wrapper_vector.begin(), input_wrapper_vector.end());
-        //		INFO("finished sorting");
+        // sort the hilbert-value representatives
+        tbb::parallel_sort(input_wrapper_vector.begin(), input_wrapper_vector.end());
         std::vector<TreeNode> tree_nodes_in_level;
 
-        //pack M elements into leaf node and write to leaf file
+        // pack M elements into leaf node and write to leaf file
         uint64_t processed_objects_count = 0;
-        while(processed_objects_count < m_element_count) {
+        while (processed_objects_count < m_element_count)
+        {
 
             LeafNode current_leaf;
             TreeNode current_node;
-            for(uint32_t current_element_index = 0; RTREE_LEAF_NODE_SIZE > current_element_index; ++current_element_index) {
-                if(m_element_count > (processed_objects_count + current_element_index)) {
-                    //					INFO("Checking element " << (processed_objects_count + current_element_index));
-                    uint32_t index_of_next_object = input_wrapper_vector[processed_objects_count + current_element_index].m_array_index;
-                    current_leaf.objects[current_element_index] = input_data_vector[index_of_next_object];
+            // SimpleLogger().Write() << "reading " << tree_size << " tree nodes in " <<
+            // (sizeof(TreeNode)*tree_size) << " bytes";
+            for (uint32_t current_element_index = 0; RTREE_LEAF_NODE_SIZE > current_element_index;
+                 ++current_element_index)
+            {
+                if (m_element_count > (processed_objects_count + current_element_index))
+                {
+                    uint32_t index_of_next_object =
+                        input_wrapper_vector[processed_objects_count + current_element_index]
+                            .m_array_index;
+                    current_leaf.objects[current_element_index] =
+                        input_data_vector[index_of_next_object];
                     ++current_leaf.object_count;
                 }
             }
 
-            if(0 == processed_objects_count) {
-                for(uint32_t i = 0; i < current_leaf.object_count; ++i) {
-                    					//INFO("[" << i << "] id: " << current_leaf.objects[i].id << ", weight: " << current_leaf.objects[i].weight << ", " << current_leaf.objects[i].lat1/100000. << "," << current_leaf.objects[i].lon1/100000. << ";" << current_leaf.objects[i].lat2/100000. << "," << current_leaf.objects[i].lon2/100000.);
-                }
-            }
-
-            //generate tree node that resemble the objects in leaf and store it for next level
-            current_node.minimum_bounding_rectangle.InitializeMBRectangle(current_leaf.objects, current_leaf.object_count);
+            // generate tree node that resemble the objects in leaf and store it for next level
+            current_node.minimum_bounding_rectangle.InitializeMBRectangle(
+                current_leaf.objects, current_leaf.object_count, coordinate_list);
             current_node.child_is_on_disk = true;
             current_node.children[0] = tree_nodes_in_level.size();
-            tree_nodes_in_level.push_back(current_node);
+            tree_nodes_in_level.emplace_back(current_node);
 
-            //write leaf_node to leaf node file
-            leaf_node_file.write((char*)&current_leaf, sizeof(current_leaf));
+            // write leaf_node to leaf node file
+            leaf_node_file.write((char *)&current_leaf, sizeof(current_leaf));
             processed_objects_count += current_leaf.object_count;
         }
 
-        //		INFO("wrote " << processed_objects_count << " leaf objects");
-
-        //close leaf file
+        // close leaf file
         leaf_node_file.close();
 
         uint32_t processing_level = 0;
-        while(1 < tree_nodes_in_level.size()) {
-            //			INFO("processing " << (uint32_t)tree_nodes_in_level.size() << " tree nodes in level " << processing_level);
+        while (1 < tree_nodes_in_level.size())
+        {
             std::vector<TreeNode> tree_nodes_in_next_level;
             uint32_t processed_tree_nodes_in_level = 0;
-            while(processed_tree_nodes_in_level < tree_nodes_in_level.size()) {
+            while (processed_tree_nodes_in_level < tree_nodes_in_level.size())
+            {
                 TreeNode parent_node;
-                //pack RTREE_BRANCHING_FACTOR elements into tree_nodes each
-                for(uint32_t current_child_node_index = 0; RTREE_BRANCHING_FACTOR > current_child_node_index; ++current_child_node_index) {
-                    if(processed_tree_nodes_in_level < tree_nodes_in_level.size()) {
-                        TreeNode & current_child_node = tree_nodes_in_level[processed_tree_nodes_in_level];
-                        //add tree node to parent entry
+                // pack RTREE_BRANCHING_FACTOR elements into tree_nodes each
+                for (uint32_t current_child_node_index = 0;
+                     RTREE_BRANCHING_FACTOR > current_child_node_index;
+                     ++current_child_node_index)
+                {
+                    if (processed_tree_nodes_in_level < tree_nodes_in_level.size())
+                    {
+                        TreeNode &current_child_node =
+                            tree_nodes_in_level[processed_tree_nodes_in_level];
+                        // add tree node to parent entry
                         parent_node.children[current_child_node_index] = m_search_tree.size();
-                        m_search_tree.push_back(current_child_node);
-                        //augment MBR of parent
-                        parent_node.minimum_bounding_rectangle.AugmentMBRectangle(current_child_node.minimum_bounding_rectangle);
-                        //increase counters
+                        m_search_tree.emplace_back(current_child_node);
+                        // merge MBRs
+                        parent_node.minimum_bounding_rectangle.MergeBoundingBoxes(
+                            current_child_node.minimum_bounding_rectangle);
+                        // increase counters
                         ++parent_node.child_count;
                         ++processed_tree_nodes_in_level;
                     }
                 }
-                tree_nodes_in_next_level.push_back(parent_node);
-                //				INFO("processed: " << processed_tree_nodes_in_level << ", generating " << (uint32_t)tree_nodes_in_next_level.size() << " parents");
+                tree_nodes_in_next_level.emplace_back(parent_node);
             }
             tree_nodes_in_level.swap(tree_nodes_in_next_level);
             ++processing_level;
         }
         BOOST_ASSERT_MSG(1 == tree_nodes_in_level.size(), "tree broken, more than one root node");
-        //last remaining entry is the root node;
-        //		INFO("root node has " << (uint32_t)tree_nodes_in_level[0].child_count << " children");
-        //store root node
-        m_search_tree.push_back(tree_nodes_in_level[0]);
+        // last remaining entry is the root node, store it
+        m_search_tree.emplace_back(tree_nodes_in_level[0]);
 
-        //reverse and renumber tree to have root at index 0
+        // reverse and renumber tree to have root at index 0
         std::reverse(m_search_tree.begin(), m_search_tree.end());
-#pragma omp parallel for schedule(guided)
-        for(uint32_t i = 0; i < m_search_tree.size(); ++i) {
-            TreeNode & current_tree_node = m_search_tree[i];
-            for(uint32_t j = 0; j < current_tree_node.child_count; ++j) {
-                const uint32_t old_id = current_tree_node.children[j];
-                const uint32_t new_id = m_search_tree.size() - old_id - 1;
-                current_tree_node.children[j] = new_id;
+
+        uint32_t search_tree_size = m_search_tree.size();
+        tbb::parallel_for(tbb::blocked_range<uint32_t>(0, search_tree_size),
+                          [this, &search_tree_size](const tbb::blocked_range<uint32_t> &range)
+                          {
+            for (uint32_t i = range.begin(); i != range.end(); ++i)
+            {
+                TreeNode &current_tree_node = this->m_search_tree[i];
+                for (uint32_t j = 0; j < current_tree_node.child_count; ++j)
+                {
+                    const uint32_t old_id = current_tree_node.children[j];
+                    const uint32_t new_id = search_tree_size - old_id - 1;
+                    current_tree_node.children[j] = new_id;
+                }
             }
-        }
+        });
+
+        // open tree file
+        boost::filesystem::ofstream tree_node_file(tree_node_filename, std::ios::binary);
 
-        //open tree file
-        std::ofstream tree_node_file(tree_node_filename, std::ios::binary);
         uint32_t size_of_tree = m_search_tree.size();
         BOOST_ASSERT_MSG(0 < size_of_tree, "tree empty");
         tree_node_file.write((char *)&size_of_tree, sizeof(uint32_t));
-        tree_node_file.write((char *)&m_search_tree[0], sizeof(TreeNode)*size_of_tree);
-        //close tree node file.
+        tree_node_file.write((char *)&m_search_tree[0], sizeof(TreeNode) * size_of_tree);
+        // close tree node file.
         tree_node_file.close();
-        double time2 = get_timestamp();
-//        INFO("written " << processed_objects_count << " leafs in " << sizeof(LeafNode)*(1+(unsigned)std::ceil(processed_objects_count/RTREE_LEAF_NODE_SIZE) )+sizeof(uint64_t) << " bytes");
-//        INFO("written search tree of " << size_of_tree << " tree nodes in " << sizeof(TreeNode)*size_of_tree+sizeof(uint32_t) << " bytes");
-        INFO("finished r-tree construction in " << (time2-time1) << " seconds");
-
-        //todo: test queries
-/*        INFO("first MBR:" << m_search_tree[0].minimum_bounding_rectangle);
-
-        DataT result;
-        time1 = get_timestamp();
-        bool found_nearest = NearestNeighbor(_Coordinate(50.191085,8.466479), result);
-        time2 = get_timestamp();
-        INFO("found nearest element to (50.191085,8.466479): " << (found_nearest ? "yes" : "no")  << " in " << (time2-time1) << "s at (" << result.lat1/100000. << "," << result.lon1/100000. << " " << result.lat2/100000. << "," << result.lon2/100000. << ")");
-        time1 = get_timestamp();
-        found_nearest = NearestNeighbor(_Coordinate(50.23979, 8.51882), result);
-        time2 = get_timestamp();
-        INFO("found nearest element to (50.23979, 8.51882): " << (found_nearest ? "yes" : "no")  << " in " << (time2-time1) << "s at (" << result.lat1/100000. << "," << result.lon1/100000. << " " << result.lat2/100000. << "," << result.lon2/100000. << ")");
-        time1 = get_timestamp();
-        found_nearest = NearestNeighbor(_Coordinate(49.0316,2.6937), result);
-        time2 = get_timestamp();
-        INFO("found nearest element to (49.0316,2.6937): " << (found_nearest ? "yes" : "no")  << " in " << (time2-time1) << "s at (" << result.lat1/100000. << "," << result.lon1/100000. << " " << result.lat2/100000. << "," << result.lon2/100000. << ")");
-*/
+
+        TIMER_STOP(construction);
+        SimpleLogger().Write() << "finished r-tree construction in " << TIMER_SEC(construction)
+                               << " seconds";
     }
 
-    //Read-only operation for queries
-    explicit StaticRTree(
-            const char * node_filename,
-            const char * leaf_filename
-    ) : m_leaf_node_filename(leaf_filename) {
-        //INFO("Loading nodes: " << node_filename);
-        //INFO("opening leafs: " << leaf_filename);
-        //open tree node file and load into RAM.
-        std::ifstream tree_node_file(node_filename, std::ios::binary);
+    // Read-only operation for queries
+    explicit StaticRTree(const boost::filesystem::path &node_file,
+                         const boost::filesystem::path &leaf_file,
+                         const std::shared_ptr<CoordinateListT> coordinate_list)
+        : m_leaf_node_filename(leaf_file.string())
+    {
+        // open tree node file and load into RAM.
+        m_coordinate_list = coordinate_list;
+
+        if (!boost::filesystem::exists(node_file))
+        {
+            throw OSRMException("ram index file does not exist");
+        }
+        if (0 == boost::filesystem::file_size(node_file))
+        {
+            throw OSRMException("ram index file is empty");
+        }
+        boost::filesystem::ifstream tree_node_file(node_file, std::ios::binary);
+
         uint32_t tree_size = 0;
-        tree_node_file.read((char*)&tree_size, sizeof(uint32_t));
-        //INFO("reading " << tree_size << " tree nodes in " << (sizeof(TreeNode)*tree_size) << " bytes");
+        tree_node_file.read((char *)&tree_size, sizeof(uint32_t));
+
         m_search_tree.resize(tree_size);
-        tree_node_file.read((char*)&m_search_tree[0], sizeof(TreeNode)*tree_size);
+        if (tree_size > 0)
+        {
+            tree_node_file.read((char *)&m_search_tree[0], sizeof(TreeNode) * tree_size);
+        }
         tree_node_file.close();
+        // open leaf node file and store thread specific pointer
+        if (!boost::filesystem::exists(leaf_file))
+        {
+            throw OSRMException("mem index file does not exist");
+        }
+        if (0 == boost::filesystem::file_size(leaf_file))
+        {
+            throw OSRMException("mem index file is empty");
+        }
 
-        //open leaf node file and store thread specific pointer
-        std::ifstream leaf_node_file(leaf_filename, std::ios::binary);
-        leaf_node_file.read((char*)&m_element_count, sizeof(uint64_t));
+        boost::filesystem::ifstream leaf_node_file(leaf_file, std::ios::binary);
+        leaf_node_file.read((char *)&m_element_count, sizeof(uint64_t));
         leaf_node_file.close();
 
-        //INFO( tree_size << " nodes in search tree");
-        //INFO( m_element_count << " elements in leafs");
+        // SimpleLogger().Write() << tree_size << " nodes in search tree";
+        // SimpleLogger().Write() << m_element_count << " elements in leafs";
     }
-/*
-    inline void FindKNearestPhantomNodesForCoordinate(
-        const _Coordinate & location,
-        const unsigned zoom_level,
-        const unsigned candidate_count,
-        std::vector<std::pair<PhantomNode, double> > & result_vector
-    ) const {
 
-        bool ignore_tiny_components = (zoom_level <= 14);
-        DataT nearest_edge;
+    explicit StaticRTree(TreeNode *tree_node_ptr,
+                         const uint32_t number_of_nodes,
+                         const boost::filesystem::path &leaf_file,
+                         std::shared_ptr<CoordinateListT> coordinate_list)
+        : m_search_tree(tree_node_ptr, number_of_nodes), m_leaf_node_filename(leaf_file.string()),
+          m_coordinate_list(coordinate_list)
+    {
+        // open leaf node file and store thread specific pointer
+        if (!boost::filesystem::exists(leaf_file))
+        {
+            throw OSRMException("mem index file does not exist");
+        }
+        if (0 == boost::filesystem::file_size(leaf_file))
+        {
+            throw OSRMException("mem index file is empty");
+        }
 
-        uint32_t io_count = 0;
-        uint32_t explored_tree_nodes_count = 0;
-        INFO("searching for coordinate " << input_coordinate);
-        double min_dist = DBL_MAX;
-        double min_max_dist = DBL_MAX;
-        bool found_a_nearest_edge = false;
+        boost::filesystem::ifstream leaf_node_file(leaf_file, std::ios::binary);
+        leaf_node_file.read((char *)&m_element_count, sizeof(uint64_t));
+        leaf_node_file.close();
+
+        if (thread_local_rtree_stream.get())
+        {
+            thread_local_rtree_stream->close();
+        }
+
+        // SimpleLogger().Write() << tree_size << " nodes in search tree";
+        // SimpleLogger().Write() << m_element_count << " elements in leafs";
+    }
+    // Read-only operation for queries
+
+    bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
+                                            FixedPointCoordinate &result_coordinate,
+                                            const unsigned zoom_level)
+    {
+        bool ignore_tiny_components = (zoom_level <= 14);
 
-        _Coordinate nearest, current_start_coordinate, current_end_coordinate;
+        float min_dist = std::numeric_limits<float>::max();
+        float min_max_dist = std::numeric_limits<float>::max();
 
-        //initialize queue with root element
+        // initialize queue with root element
         std::priority_queue<QueryCandidate> traversal_queue;
-        traversal_queue.push(QueryCandidate(0, m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate)));
-        BOOST_ASSERT_MSG(FLT_EPSILON > (0. - traversal_queue.top().min_dist), "Root element in NN Search has min dist != 0.");
-
-        while(!traversal_queue.empty()) {
-            const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
-
-            ++explored_tree_nodes_count;
-            bool prune_downward = (current_query_node.min_dist >= min_max_dist);
-            bool prune_upward    = (current_query_node.min_dist >= min_dist);
-            if( !prune_downward && !prune_upward ) { //downward pruning
-                TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
-                if (current_tree_node.child_is_on_disk) {
+        traversal_queue.emplace(0.f, 0);
+
+        while (!traversal_queue.empty())
+        {
+            const QueryCandidate current_query_node = traversal_queue.top();
+            traversal_queue.pop();
+
+            const bool prune_downward = (current_query_node.min_dist >= min_max_dist);
+            const bool prune_upward = (current_query_node.min_dist >= min_dist);
+            if (!prune_downward && !prune_upward)
+            { // downward pruning
+                TreeNode &current_tree_node = m_search_tree[current_query_node.node_id];
+                if (current_tree_node.child_is_on_disk)
+                {
                     LeafNode current_leaf_node;
                     LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
-                    ++io_count;
-                    for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
-                        DataT & current_edge = current_leaf_node.objects[i];
-                        if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
+                    for (uint32_t i = 0; i < current_leaf_node.object_count; ++i)
+                    {
+                        EdgeDataT const &current_edge = current_leaf_node.objects[i];
+                        if (ignore_tiny_components && current_edge.is_in_tiny_cc)
+                        {
                             continue;
                         }
 
-                        double current_ratio = 0.;
-                        double current_perpendicular_distance = ComputePerpendicularDistance(
-                                                                                             input_coordinate,
-                                                                                             _Coordinate(current_edge.lat1, current_edge.lon1),
-                                                                                             _Coordinate(current_edge.lat2, current_edge.lon2),
-                                                                                             nearest,
-                                                                                             &current_ratio
-                                                                                             );
-
-                        if(
-                           current_perpendicular_distance < min_dist
-                           && !DoubleEpsilonCompare(
-                                                    current_perpendicular_distance,
-                                                    min_dist
-                                                    )
-                           ) { //found a new minimum
-                            min_dist = current_perpendicular_distance;
-                            result_phantom_node.edgeBasedNode = current_edge.id;
-                            result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
-                            result_phantom_node.weight1 = current_edge.weight;
-                            result_phantom_node.weight2 = INT_MAX;
-                            result_phantom_node.location = nearest;
-                            current_start_coordinate.lat = current_edge.lat1;
-                            current_start_coordinate.lon = current_edge.lon1;
-                            current_end_coordinate.lat = current_edge.lat2;
-                            current_end_coordinate.lon = current_edge.lon2;
-                            nearest_edge = current_edge;
-                            found_a_nearest_edge = true;
-                        } else if(
-                                  DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
-                                  1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
-                                  && CoordinatesAreEquivalent(
-                                                              current_start_coordinate,
-                                                              _Coordinate(
-                                                                          current_edge.lat1,
-                                                                          current_edge.lon1
-                                                                          ),
-                                                              _Coordinate(
-                                                                          current_edge.lat2,
-                                                                          current_edge.lon2
-                                                                          ),
-                                                              current_end_coordinate
-                                                              )
-                                  ) {
-                            result_phantom_node.edgeBasedNode = std::min(current_edge.id, result_phantom_node.edgeBasedNode);
-                            result_phantom_node.weight2 = current_edge.weight;
+                        float current_minimum_distance =
+                            FixedPointCoordinate::ApproximateEuclideanDistance(
+                                input_coordinate.lat,
+                                input_coordinate.lon,
+                                m_coordinate_list->at(current_edge.u).lat,
+                                m_coordinate_list->at(current_edge.u).lon);
+                        if (current_minimum_distance < min_dist)
+                        {
+                            // found a new minimum
+                            min_dist = current_minimum_distance;
+                            result_coordinate = m_coordinate_list->at(current_edge.u);
+                        }
+
+                        current_minimum_distance =
+                            FixedPointCoordinate::ApproximateEuclideanDistance(
+                                input_coordinate.lat,
+                                input_coordinate.lon,
+                                m_coordinate_list->at(current_edge.v).lat,
+                                m_coordinate_list->at(current_edge.v).lon);
+
+                        if (current_minimum_distance < min_dist)
+                        {
+                            // found a new minimum
+                            min_dist = current_minimum_distance;
+                            result_coordinate = m_coordinate_list->at(current_edge.v);
                         }
                     }
-                } else {
-                    //traverse children, prune if global mindist is smaller than local one
-                    for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
-                        const int32_t child_id = current_tree_node.children[i];
-                        TreeNode & child_tree_node = m_search_tree[child_id];
-                        RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
-                        const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
-                        const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
-                        if( current_min_max_dist < min_max_dist ) {
-                            min_max_dist = current_min_max_dist;
+                }
+                else
+                {
+                    min_max_dist = ExploreTreeNode(current_tree_node,
+                                                   input_coordinate,
+                                                   min_dist,
+                                                   min_max_dist,
+                                                   traversal_queue);
+                }
+            }
+        }
+        return result_coordinate.isValid();
+    }
+
+    // implementation of the Hjaltason/Samet query [3], a BFS traversal of the tree
+    bool
+    IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
+                                            std::vector<PhantomNode> &result_phantom_node_vector,
+                                            const unsigned zoom_level,
+                                            const unsigned number_of_results,
+                                            const unsigned max_checked_segments = 4*RTREE_LEAF_NODE_SIZE)
+    {
+        // TIMER_START(samet);
+        // SimpleLogger().Write(logDEBUG) << "searching for " << number_of_results << " results";
+        std::vector<float> min_found_distances(number_of_results, std::numeric_limits<float>::max());
+
+        unsigned dequeues = 0;
+        unsigned inspected_mbrs = 0;
+        unsigned loaded_leafs = 0;
+        unsigned inspected_segments = 0;
+        unsigned pruned_elements = 0;
+        unsigned ignored_segments = 0;
+        unsigned ignored_mbrs = 0;
+
+        unsigned number_of_results_found_in_big_cc = 0;
+        unsigned number_of_results_found_in_tiny_cc = 0;
+
+        // initialize queue with root element
+        std::priority_queue<IncrementalQueryCandidate> traversal_queue;
+        traversal_queue.emplace(0.f, m_search_tree[0]);
+
+        while (!traversal_queue.empty())
+        {
+            const IncrementalQueryCandidate current_query_node = traversal_queue.top();
+            traversal_queue.pop();
+
+            ++dequeues;
+
+            const float current_min_dist = min_found_distances[number_of_results-1];
+
+            if (current_query_node.min_dist > current_min_dist)
+            {
+                ++pruned_elements;
+                continue;
+            }
+
+            if (current_query_node.RepresentsTreeNode())
+            {
+                const TreeNode & current_tree_node = boost::get<TreeNode>(current_query_node.node);
+                if (current_tree_node.child_is_on_disk)
+                {
+                    ++loaded_leafs;
+                    // SimpleLogger().Write(logDEBUG) << "loading leaf: " << current_tree_node.children[0] << " w/ mbr [" <<
+                    //     current_tree_node.minimum_bounding_rectangle.min_lat/COORDINATE_PRECISION << "," <<
+                    //     current_tree_node.minimum_bounding_rectangle.min_lon/COORDINATE_PRECISION << "," <<
+                    //     current_tree_node.minimum_bounding_rectangle.max_lat/COORDINATE_PRECISION << "-" <<
+                    //     current_tree_node.minimum_bounding_rectangle.max_lon/COORDINATE_PRECISION << "]";
+
+                    LeafNode current_leaf_node;
+                    LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
+                    // Add all objects from leaf into queue
+                    for (uint32_t i = 0; i < current_leaf_node.object_count; ++i)
+                    {
+                        const auto &current_edge = current_leaf_node.objects[i];
+                        const float current_perpendicular_distance =
+                            FixedPointCoordinate::ComputePerpendicularDistance(
+                                m_coordinate_list->at(current_edge.u),
+                                m_coordinate_list->at(current_edge.v),
+                                input_coordinate);
+                        // distance must be non-negative
+                        BOOST_ASSERT(0. <= current_perpendicular_distance);
+
+                        if (current_perpendicular_distance < current_min_dist)
+                        {
+                            traversal_queue.emplace(current_perpendicular_distance, current_edge);
                         }
-                        if (current_min_dist > min_max_dist) {
-                            continue;
+                        else
+                        {
+                            ++ignored_segments;
                         }
-                        if (current_min_dist > min_dist) { //upward pruning
-                            continue;
+                    }
+                    // SimpleLogger().Write(logDEBUG) << "added " << current_leaf_node.object_count << " roads into queue of " << traversal_queue.size();
+                }
+                else
+                {
+                    ++inspected_mbrs;
+                    // explore inner node
+                    // SimpleLogger().Write(logDEBUG) << "explore inner node w/ mbr [" <<
+                    //     current_tree_node.minimum_bounding_rectangle.min_lat/COORDINATE_PRECISION << "," <<
+                    //     current_tree_node.minimum_bounding_rectangle.min_lon/COORDINATE_PRECISION << "," <<
+                    //     current_tree_node.minimum_bounding_rectangle.max_lat/COORDINATE_PRECISION << "-" <<
+                    //     current_tree_node.minimum_bounding_rectangle.max_lon/COORDINATE_PRECISION << "," << "]";
+
+                    // for each child mbr
+                    for (uint32_t i = 0; i < current_tree_node.child_count; ++i)
+                    {
+                        const int32_t child_id = current_tree_node.children[i];
+                        const TreeNode &child_tree_node = m_search_tree[child_id];
+                        const RectangleT &child_rectangle = child_tree_node.minimum_bounding_rectangle;
+                        const float lower_bound_to_element = child_rectangle.GetMinDist(input_coordinate);
+
+                        // TODO - enough elements found, i.e. nearest distance > maximum distance?
+                        //        ie. some measure of 'confidence of accuracy'
+
+                        // check if it needs to be explored by mindist
+                        if (lower_bound_to_element < current_min_dist)
+                        {
+                            traversal_queue.emplace(lower_bound_to_element, child_tree_node);
+                        }
+                        else
+                        {
+                            ++ignored_mbrs;
                         }
-                        traversal_queue.push(QueryCandidate(child_id, current_min_dist));
                     }
+                    // SimpleLogger().Write(logDEBUG) << "added " << current_tree_node.child_count << " mbrs into queue of " << traversal_queue.size();
                 }
             }
-        }
+            else
+            {
+                ++inspected_segments;
+                // inspecting an actual road segment
+                const EdgeDataT & current_segment = boost::get<EdgeDataT>(current_query_node.node);
+
+                // don't collect too many results from small components
+                if (number_of_results_found_in_big_cc == number_of_results && !current_segment.is_in_tiny_cc)
+                {
+                    continue;
+                }
 
-        const double ratio = (found_a_nearest_edge ?
-                              std::min(1., ApproximateDistance(_Coordinate(nearest_edge.lat1, nearest_edge.lon1),
-                                                               result_phantom_node.location)/ApproximateDistance(_Coordinate(nearest_edge.lat1, nearest_edge.lon1), _Coordinate(nearest_edge.lat2, nearest_edge.lon2))
-                                       ) : 0
-                              );
-        result_phantom_node.weight1 *= ratio;
-        if(INT_MAX != result_phantom_node.weight2) {
-            result_phantom_node.weight2 *= (1.-ratio);
-        }
-        result_phantom_node.ratio = ratio;
+                // don't collect too many results from big components
+                if (number_of_results_found_in_tiny_cc == number_of_results && current_segment.is_in_tiny_cc)
+                {
+                    continue;
+                }
 
-        //Hack to fix rounding errors and wandering via nodes.
-        if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) {
-            result_phantom_node.location.lon = input_coordinate.lon;
-        }
-        if(std::abs(input_coordinate.lat - result_phantom_node.location.lat) == 1) {
-            result_phantom_node.location.lat = input_coordinate.lat;
-        }
+                // check if it is smaller than what we had before
+                float current_ratio = 0.;
+                FixedPointCoordinate foot_point_coordinate_on_segment;
+                const float current_perpendicular_distance =
+                    FixedPointCoordinate::ComputePerpendicularDistance(
+                        m_coordinate_list->at(current_segment.u),
+                        m_coordinate_list->at(current_segment.v),
+                        input_coordinate,
+                        foot_point_coordinate_on_segment,
+                        current_ratio);
+
+                BOOST_ASSERT(0. <= current_perpendicular_distance);
+
+                if ((current_perpendicular_distance < current_min_dist) &&
+                    !EpsilonCompare(current_perpendicular_distance, current_min_dist))
+                {
+                    // store phantom node in result vector
+                    result_phantom_node_vector.emplace_back(
+                        current_segment.forward_edge_based_node_id,
+                         current_segment.reverse_edge_based_node_id,
+                         current_segment.name_id,
+                         current_segment.forward_weight,
+                         current_segment.reverse_weight,
+                         current_segment.forward_offset,
+                         current_segment.reverse_offset,
+                         current_segment.packed_geometry_id,
+                         foot_point_coordinate_on_segment,
+                         current_segment.fwd_segment_position);
+
+                    // Hack to fix rounding errors and wandering via nodes.
+                    FixUpRoundingIssue(input_coordinate, result_phantom_node_vector.back());
+
+                    // set forward and reverse weights on the phantom node
+                    SetForwardAndReverseWeightsOnPhantomNode(current_segment,
+                                                             result_phantom_node_vector.back());
+
+                    // do we have results only in a small scc
+                    if (current_segment.is_in_tiny_cc)
+                    {
+                        ++number_of_results_found_in_tiny_cc;
+                    }
+                    else
+                    {
+                        // found an element in a large component
+                        min_found_distances[number_of_results_found_in_big_cc] = current_perpendicular_distance;
+                        ++number_of_results_found_in_big_cc;
+                        // SimpleLogger().Write(logDEBUG) << std::setprecision(8) << foot_point_coordinate_on_segment << " at " << current_perpendicular_distance;
+                    }
+                }
+            }
 
-        INFO("mindist: " << min_dist << ", io's: " << io_count << ", nodes: " << explored_tree_nodes_count << ", loc: " << result_phantom_node.location << ", ratio: " << ratio << ", id: " << result_phantom_node.edgeBasedNode);
-        INFO("bidirected: " << (result_phantom_node.isBidirected() ? "yes" : "no") );
-        return found_a_nearest_edge;
+            // TODO add indicator to prune if maxdist > threshold
+            if (number_of_results == number_of_results_found_in_big_cc || inspected_segments >= max_checked_segments)
+            {
+                // SimpleLogger().Write(logDEBUG) << "flushing queue of " << traversal_queue.size() << " elements";
+                // work-around for traversal_queue.clear();
+                traversal_queue = std::priority_queue<IncrementalQueryCandidate>{};
+            }
+        }
 
+        // for (const PhantomNode& result_node : result_phantom_node_vector)
+        // {
+        //     SimpleLogger().Write(logDEBUG) << std::setprecision(8) << "found location " << result_node.forward_node_id << " at " << result_node.location;
+        // }
+        // SimpleLogger().Write(logDEBUG) << "dequeues: " << dequeues;
+        // SimpleLogger().Write(logDEBUG) << "inspected_mbrs: " << inspected_mbrs;
+        // SimpleLogger().Write(logDEBUG) << "loaded_leafs: " << loaded_leafs;
+        // SimpleLogger().Write(logDEBUG) << "inspected_segments: " << inspected_segments;
+        // SimpleLogger().Write(logDEBUG) << "pruned_elements: " << pruned_elements;
+        // SimpleLogger().Write(logDEBUG) << "ignored_segments: " << ignored_segments;
+        // SimpleLogger().Write(logDEBUG) << "ignored_mbrs: " << ignored_mbrs;
+
+        // SimpleLogger().Write(logDEBUG) << "number_of_results_found_in_big_cc: " << number_of_results_found_in_big_cc;
+        // SimpleLogger().Write(logDEBUG) << "number_of_results_found_in_tiny_cc: " << number_of_results_found_in_tiny_cc;
+        // TIMER_STOP(samet);
+        // SimpleLogger().Write() << "query took " << TIMER_MSEC(samet) << "ms";
+
+        // if we found an element in either category, then we are good
+        return !result_phantom_node_vector.empty();
     }
 
-  */
-    bool FindPhantomNodeForCoordinate(
-            const _Coordinate & input_coordinate,
-            PhantomNode & result_phantom_node,
-            const unsigned zoom_level
-    ) {
+    bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
+                                      PhantomNode &result_phantom_node,
+                                      const unsigned zoom_level)
+    {
 
-        bool ignore_tiny_components = (zoom_level <= 14);
-        DataT nearest_edge;
+        std::vector<PhantomNode> result_phantom_node_vector;
+        IncrementalFindPhantomNodeForCoordinate(input_coordinate, result_phantom_node_vector, zoom_level, 2);
+        // if (!result_phantom_node_vector.empty())
+        // {
+        //     result_phantom_node = result_phantom_node_vector.front();
+        // }
+        // return !result_phantom_node_vector.empty();
 
-        uint32_t io_count = 0;
-        uint32_t explored_tree_nodes_count = 0;
-        //INFO("searching for coordinate " << input_coordinate);
-        double min_dist = DBL_MAX;
-        double min_max_dist = DBL_MAX;
-        bool found_a_nearest_edge = false;
+        const bool ignore_tiny_components = (zoom_level <= 14);
+        EdgeDataT nearest_edge;
 
-        _Coordinate nearest, current_start_coordinate, current_end_coordinate;
+        float min_dist = std::numeric_limits<float>::max();
+        float min_max_dist = std::numeric_limits<float>::max();
 
-        //initialize queue with root element
         std::priority_queue<QueryCandidate> traversal_queue;
-        double current_min_dist = m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate);
-        traversal_queue.push(
-                             QueryCandidate(0, current_min_dist)
-        );
-
-        BOOST_ASSERT_MSG(
-                         FLT_EPSILON > (0. - traversal_queue.top().min_dist),
-                         "Root element in NN Search has min dist != 0."
-        );
-
-        while(!traversal_queue.empty()) {
-            const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
-
-            ++explored_tree_nodes_count;
-            bool prune_downward = (current_query_node.min_dist >= min_max_dist);
-            bool prune_upward    = (current_query_node.min_dist >= min_dist);
-            if( !prune_downward && !prune_upward ) { //downward pruning
-                TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
-                if (current_tree_node.child_is_on_disk) {
+        traversal_queue.emplace(0.f, 0);
+
+        while (!traversal_queue.empty())
+        {
+            const QueryCandidate current_query_node = traversal_queue.top();
+            traversal_queue.pop();
+
+            const bool prune_downward = (current_query_node.min_dist > min_max_dist);
+            const bool prune_upward = (current_query_node.min_dist > min_dist);
+            if (!prune_downward && !prune_upward)
+            { // downward pruning
+                const TreeNode &current_tree_node = m_search_tree[current_query_node.node_id];
+                if (current_tree_node.child_is_on_disk)
+                {
                     LeafNode current_leaf_node;
                     LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
-                    ++io_count;
-                    //INFO("checking " << current_leaf_node.object_count << " elements");
-                    for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
-                        DataT & current_edge = current_leaf_node.objects[i];
-                        if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
-                            continue;
-                        }
-                        if(current_edge.isIgnored()) {
+                    for (uint32_t i = 0; i < current_leaf_node.object_count; ++i)
+                    {
+                        const EdgeDataT &current_edge = current_leaf_node.objects[i];
+                        if (ignore_tiny_components && current_edge.is_in_tiny_cc)
+                        {
                             continue;
                         }
 
-                       double current_ratio = 0.;
-                       double current_perpendicular_distance = ComputePerpendicularDistance(
+                        float current_ratio = 0.;
+                        FixedPointCoordinate nearest;
+                        const float current_perpendicular_distance =
+                            FixedPointCoordinate::ComputePerpendicularDistance(
+                                m_coordinate_list->at(current_edge.u),
+                                m_coordinate_list->at(current_edge.v),
                                 input_coordinate,
-                                _Coordinate(current_edge.lat1, current_edge.lon1),
-                                _Coordinate(current_edge.lat2, current_edge.lon2),
                                 nearest,
-                                &current_ratio
-                        );
-
-                        //INFO("[" << current_edge.id << "] (" << current_edge.lat1/100000. << "," << current_edge.lon1/100000. << ")==(" << current_edge.lat2/100000. << "," << current_edge.lon2/100000. << ") at distance " << current_perpendicular_distance << " min dist: " << min_dist
-                        //     << ", ratio " << current_ratio
-                        //     );
-
-                        if(
-                                current_perpendicular_distance < min_dist
-                                && !DoubleEpsilonCompare(
-                                        current_perpendicular_distance,
-                                        min_dist
-                                )
-                        ) { //found a new minimum
+                                current_ratio);
+
+                        BOOST_ASSERT(0. <= current_perpendicular_distance);
+
+                        if ((current_perpendicular_distance < min_dist) &&
+                            !EpsilonCompare(current_perpendicular_distance, min_dist))
+                        { // found a new minimum
                             min_dist = current_perpendicular_distance;
-                            result_phantom_node.edgeBasedNode = current_edge.id;
-                            result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
-                            result_phantom_node.weight1 = current_edge.weight;
-                            result_phantom_node.weight2 = INT_MAX;
-                            result_phantom_node.location = nearest;
-                            current_start_coordinate.lat = current_edge.lat1;
-                            current_start_coordinate.lon = current_edge.lon1;
-                            current_end_coordinate.lat = current_edge.lat2;
-                            current_end_coordinate.lon = current_edge.lon2;
+                            result_phantom_node = {current_edge.forward_edge_based_node_id,
+                                                   current_edge.reverse_edge_based_node_id,
+                                                   current_edge.name_id,
+                                                   current_edge.forward_weight,
+                                                   current_edge.reverse_weight,
+                                                   current_edge.forward_offset,
+                                                   current_edge.reverse_offset,
+                                                   current_edge.packed_geometry_id,
+                                                   nearest,
+                                                   current_edge.fwd_segment_position};
                             nearest_edge = current_edge;
-                            found_a_nearest_edge = true;
-                        } else if(
-                                DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
-                                1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
-                        && CoordinatesAreEquivalent(
-                                current_start_coordinate,
-                                _Coordinate(
-                                        current_edge.lat1,
-                                        current_edge.lon1
-                                ),
-                                _Coordinate(
-                                        current_edge.lat2,
-                                        current_edge.lon2
-                                ),
-                                current_end_coordinate
-                            )
-                        ) {
-                            BOOST_ASSERT_MSG(current_edge.id != result_phantom_node.edgeBasedNode, "IDs not different");
-                            //INFO("found bidirected edge on nodes " << current_edge.id << " and " << result_phantom_node.edgeBasedNode);
-                            result_phantom_node.weight2 = current_edge.weight;
-                            if(current_edge.id < result_phantom_node.edgeBasedNode) {
-                                result_phantom_node.edgeBasedNode = current_edge.id;
-                                std::swap(result_phantom_node.weight1, result_phantom_node.weight2);
-                                std::swap(current_end_coordinate, current_start_coordinate);
-                            //    INFO("case 2");
-                            }
-                            //INFO("w1: " << result_phantom_node.weight1 << ", w2: " << result_phantom_node.weight2);
                         }
                     }
-                } else {
-                    //traverse children, prune if global mindist is smaller than local one
-                    for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
-                        const int32_t child_id = current_tree_node.children[i];
-                        TreeNode & child_tree_node = m_search_tree[child_id];
-                        RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
-                        const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
-                        const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
-                        if( current_min_max_dist < min_max_dist ) {
-                            min_max_dist = current_min_max_dist;
-                        }
-                        if (current_min_dist > min_max_dist) {
-                            continue;
-                        }
-                        if (current_min_dist > min_dist) { //upward pruning
-                            continue;
-                        }
-                        traversal_queue.push(QueryCandidate(child_id, current_min_dist));
-                    }
+                }
+                else
+                {
+                    min_max_dist = ExploreTreeNode(current_tree_node,
+                                                   input_coordinate,
+                                                   min_dist,
+                                                   min_max_dist,
+                                                   traversal_queue);
                 }
             }
         }
 
-        const double ratio = (found_a_nearest_edge ?
-            std::min(1., ApproximateDistance(current_start_coordinate,
-                result_phantom_node.location)/ApproximateDistance(current_start_coordinate, current_end_coordinate)
-                ) : 0
-            );
-        result_phantom_node.weight1 *= ratio;
-        if(INT_MAX != result_phantom_node.weight2) {
-            result_phantom_node.weight2 *= (1.-ratio);
+        if (result_phantom_node.location.isValid())
+        {
+            // Hack to fix rounding errors and wandering via nodes.
+            FixUpRoundingIssue(input_coordinate, result_phantom_node);
+
+            // set forward and reverse weights on the phantom node
+            SetForwardAndReverseWeightsOnPhantomNode(nearest_edge, result_phantom_node);
         }
-        result_phantom_node.ratio = ratio;
+        return result_phantom_node.location.isValid();
+    }
 
-        //Hack to fix rounding errors and wandering via nodes.
-        if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) {
-            result_phantom_node.location.lon = input_coordinate.lon;
+  private:
+
+    inline void SetForwardAndReverseWeightsOnPhantomNode(const EdgeDataT & nearest_edge,
+                                                         PhantomNode &result_phantom_node) const
+    {
+        const float distance_1 = FixedPointCoordinate::ApproximateEuclideanDistance(
+            m_coordinate_list->at(nearest_edge.u), result_phantom_node.location);
+        const float distance_2 = FixedPointCoordinate::ApproximateEuclideanDistance(
+            m_coordinate_list->at(nearest_edge.u), m_coordinate_list->at(nearest_edge.v));
+        const float ratio = std::min(1.f, distance_1 / distance_2);
+
+        if (SPECIAL_NODEID != result_phantom_node.forward_node_id)
+        {
+            result_phantom_node.forward_weight *= ratio;
         }
-        if(std::abs(input_coordinate.lat - result_phantom_node.location.lat) == 1) {
-            result_phantom_node.location.lat = input_coordinate.lat;
+        if (SPECIAL_NODEID != result_phantom_node.reverse_node_id)
+        {
+            result_phantom_node.reverse_weight *= (1.f - ratio);
         }
+    }
 
-//        INFO("start: (" << nearest_edge.lat1 << "," << nearest_edge.lon1 << "), end: (" << nearest_edge.lat2 << "," << nearest_edge.lon2 << ")" );
-//        INFO("mindist: " << min_dist << ", io's: " << io_count << ", nodes: " << explored_tree_nodes_count << ", loc: " << result_phantom_node.location << ", ratio: " << ratio << ", id: " << result_phantom_node.edgeBasedNode);
-//        INFO("weight1: " << result_phantom_node.weight1 << ", weight2: " << result_phantom_node.weight2);
-//        INFO("bidirected: " << (result_phantom_node.isBidirected() ? "yes" : "no") );
-//        INFO("NameID: " << result_phantom_node.nodeBasedEdgeNameID);
-        return found_a_nearest_edge;
-
+    // fixup locations if too close to inputs
+    inline void FixUpRoundingIssue(const FixedPointCoordinate &input_coordinate,
+                                  PhantomNode &result_phantom_node) const
+    {
+            if (1 == std::abs(input_coordinate.lon - result_phantom_node.location.lon))
+            {
+                result_phantom_node.location.lon = input_coordinate.lon;
+            }
+            if (1 == std::abs(input_coordinate.lat - result_phantom_node.location.lat))
+            {
+                result_phantom_node.location.lat = input_coordinate.lat;
+            }
     }
-/*
-    //Nearest-Neighbor query with the Roussopoulos et al. algorithm [2]
-    inline bool NearestNeighbor(const _Coordinate & input_coordinate, DataT & result_element) {
-        uint32_t io_count = 0;
-        uint32_t explored_tree_nodes_count = 0;
-        INFO("searching for coordinate " << input_coordinate);
-        double min_dist = DBL_MAX;
-        double min_max_dist = DBL_MAX;
-        bool found_return_value = false;
-
-        //initialize queue with root element
-        std::priority_queue<QueryCandidate> traversal_queue;
-        traversal_queue.push(QueryCandidate(0, m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate)));
-        BOOST_ASSERT_MSG(FLT_EPSILON > (0. - traversal_queue.top().min_dist), "Root element in NN Search has min dist != 0.");
-
-        while(!traversal_queue.empty()) {
-            const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
-
-            ++explored_tree_nodes_count;
-
-            //			INFO("popped node " << current_query_node.node_id << " at distance " << current_query_node.min_dist);
-            bool prune_downward = (current_query_node.min_dist >= min_max_dist);
-            bool prune_upward    = (current_query_node.min_dist >= min_dist);
-            //			INFO(" up prune:   " << (prune_upward ? "y" : "n" ));
-            //			INFO(" down prune: " << (prune_downward ? "y" : "n" ));
-            if( prune_downward || prune_upward ) { //downward pruning
-                //				INFO("  pruned node " << current_query_node.node_id << " because " << current_query_node.min_dist << "<" << min_max_dist);
-            } else {
-                TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
-                if (current_tree_node.child_is_on_disk) {
-                    //					INFO("  Fetching child from disk for id: " << current_query_node.node_id);
-                    LeafNode current_leaf_node;
-                    LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
-                    ++io_count;
-                    double ratio = 0.;
-                    _Coordinate nearest;
-                    for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
-                        DataT & current_object = current_leaf_node.objects[i];
-                        double current_perpendicular_distance = ComputePerpendicularDistance(
-                                input_coordinate,
-                                _Coordinate(current_object.lat1, current_object.lon1),
-                                _Coordinate(current_object.lat2, current_object.lon2),
-                                nearest,
-                                &ratio
-                        );
 
-                        if(current_perpendicular_distance < min_dist && !DoubleEpsilonCompare(current_perpendicular_distance, min_dist)) { //found a new minimum
-                            min_dist = current_perpendicular_distance;
-                            result_element = current_object;
-                            found_return_value = true;
-                        }
-                    }
-                } else {
-                    //traverse children, prune if global mindist is smaller than local one
-                    //					INFO("  Checking " << current_tree_node.child_count << " children of node " << current_query_node.node_id);
-                    for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
-                        const int32_t child_id = current_tree_node.children[i];
-                        TreeNode & child_tree_node = m_search_tree[child_id];
-                        RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
-                        const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
-                        const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
-                        if( current_min_max_dist < min_max_dist ) {
-                            min_max_dist = current_min_max_dist;
-                        }
-                        if (current_min_dist > min_max_dist) {
-                            continue;
-                        }
-                        if (current_min_dist > min_dist) { //upward pruning
-                            continue;
-                        }
-                        //						INFO("   pushing node " << child_id << " at distance " << current_min_dist);
-                        traversal_queue.push(QueryCandidate(child_id, current_min_dist));
-                    }
-                }
+    template <class QueueT>
+    inline float ExploreTreeNode(const TreeNode &parent,
+                                 const FixedPointCoordinate &input_coordinate,
+                                 const float min_dist,
+                                 const float min_max_dist,
+                                 QueueT &traversal_queue)
+    {
+        float new_min_max_dist = min_max_dist;
+        // traverse children, prune if global mindist is smaller than local one
+        for (uint32_t i = 0; i < parent.child_count; ++i)
+        {
+            const int32_t child_id = parent.children[i];
+            const TreeNode &child_tree_node = m_search_tree[child_id];
+            const RectangleT &child_rectangle = child_tree_node.minimum_bounding_rectangle;
+            const float lower_bound_to_element = child_rectangle.GetMinDist(input_coordinate);
+            const float upper_bound_to_element = child_rectangle.GetMinMaxDist(input_coordinate);
+            new_min_max_dist = std::min(new_min_max_dist, upper_bound_to_element);
+            if (lower_bound_to_element > new_min_max_dist)
+            {
+                continue;
+            }
+            if (lower_bound_to_element > min_dist)
+            {
+                continue;
             }
+            traversal_queue.emplace(lower_bound_to_element, child_id);
         }
-        INFO("mindist: " << min_dist << ", io's: " << io_count << ",  touched nodes: " << explored_tree_nodes_count);
-        return found_return_value;
+        return new_min_max_dist;
     }
- */
-private:
-    inline void LoadLeafFromDisk(const uint32_t leaf_id, LeafNode& result_node) {
-        if(!thread_local_rtree_stream.get() || !thread_local_rtree_stream->is_open()) {
-            thread_local_rtree_stream.reset(
-                new std::ifstream(
-                        m_leaf_node_filename.c_str(),
-                        std::ios::in | std::ios::binary
-                )
-            );
-        }
-        if(!thread_local_rtree_stream->good()) {
+
+    inline void LoadLeafFromDisk(const uint32_t leaf_id, LeafNode &result_node)
+    {
+        if (!thread_local_rtree_stream.get() || !thread_local_rtree_stream->is_open())
+        {
+            thread_local_rtree_stream.reset(new boost::filesystem::ifstream(
+                m_leaf_node_filename, std::ios::in | std::ios::binary));
+        }
+        if (!thread_local_rtree_stream->good())
+        {
             thread_local_rtree_stream->clear(std::ios::goodbit);
-            DEBUG("Resetting stale filestream");
+            SimpleLogger().Write(logDEBUG) << "Resetting stale filestream";
         }
-        uint64_t seek_pos = sizeof(uint64_t) + leaf_id*sizeof(LeafNode);
+        const uint64_t seek_pos = sizeof(uint64_t) + leaf_id * sizeof(LeafNode);
         thread_local_rtree_stream->seekg(seek_pos);
+        BOOST_ASSERT_MSG(thread_local_rtree_stream->good(),
+                         "Seeking to position in leaf file failed.");
         thread_local_rtree_stream->read((char *)&result_node, sizeof(LeafNode));
+        BOOST_ASSERT_MSG(thread_local_rtree_stream->good(), "Reading from leaf file failed.");
     }
 
-    inline double ComputePerpendicularDistance(
-            const _Coordinate& inputPoint,
-            const _Coordinate& source,
-            const _Coordinate& target,
-            _Coordinate& nearest, double *r) const {
-        const double x = static_cast<double>(inputPoint.lat);
-        const double y = static_cast<double>(inputPoint.lon);
-        const double a = static_cast<double>(source.lat);
-        const double b = static_cast<double>(source.lon);
-        const double c = static_cast<double>(target.lat);
-        const double d = static_cast<double>(target.lon);
-        double p,q,mX,nY;
-        if(fabs(a-c) > FLT_EPSILON){
-            const double m = (d-b)/(c-a); // slope
-            // Projection of (x,y) on line joining (a,b) and (c,d)
-            p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
-            q = b + m*(p - a);
-        } else {
-            p = c;
-            q = y;
-        }
-        nY = (d*p - c*q)/(a*d - b*c);
-        mX = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we need
-        // not calculate the explicit values of m an n as we
-        // are just interested in the ratio
-        if(std::isnan(mX)) {
-            *r = (target == inputPoint) ? 1. : 0.;
-        } else {
-            *r = mX;
-        }
-        if(*r<=0.){
-            nearest.lat = source.lat;
-            nearest.lon = source.lon;
-            return ((b - y)*(b - y) + (a - x)*(a - x));
-//            return std::sqrt(((b - y)*(b - y) + (a - x)*(a - x)));
-        } else if(*r >= 1.){
-            nearest.lat = target.lat;
-            nearest.lon = target.lon;
-            return ((d - y)*(d - y) + (c - x)*(c - x));
-//            return std::sqrt(((d - y)*(d - y) + (c - x)*(c - x)));
-        }
-        // point lies in between
-        nearest.lat = p;
-        nearest.lon = q;
-//        return std::sqrt((p-x)*(p-x) + (q-y)*(q-y));
-        return (p-x)*(p-x) + (q-y)*(q-y);
-    }
-
-    inline bool CoordinatesAreEquivalent(const _Coordinate & a, const _Coordinate & b, const _Coordinate & c, const _Coordinate & d) const {
+    inline bool EdgesAreEquivalent(const FixedPointCoordinate &a,
+                                   const FixedPointCoordinate &b,
+                                   const FixedPointCoordinate &c,
+                                   const FixedPointCoordinate &d) const
+    {
         return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
     }
 
-    inline bool DoubleEpsilonCompare(const double d1, const double d2) const {
-        return (std::fabs(d1 - d2) < FLT_EPSILON);
+    template <typename FloatT> inline bool EpsilonCompare(const FloatT d1, const FloatT d2) const
+    {
+        return (std::abs(d1 - d2) < std::numeric_limits<FloatT>::epsilon());
     }
-
 };
 
 //[1] "On Packing R-Trees"; I. Kamel, C. Faloutsos; 1993; DOI: 10.1145/170088.170403
 //[2] "Nearest Neighbor Queries", N. Roussopulos et al; 1995; DOI: 10.1145/223784.223794
-
-
-#endif /* STATICRTREE_H_ */
+//[3] "Distance Browsing in Spatial Databases"; G. Hjaltason, H. Samet; 1999; ACM Trans. DB Sys
+// Vol.24 No.2, pp.265-318
+#endif // STATICRTREE_H
diff --git a/DataStructures/TimingUtil.h b/DataStructures/TimingUtil.h
deleted file mode 100644
index 6e980e2..0000000
--- a/DataStructures/TimingUtil.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
-*/
-
-#ifndef TIMINGUTIL_H_
-#define TIMINGUTIL_H_
-
-#include <climits>
-#include <cstdlib>
-
-
-#ifdef _WIN32
- #include <sys/timeb.h>
- #include <sys/types.h>
- #include <winsock.h>
- void gettimeofday(struct timeval* t,void* timezone)
- {       struct _timeb timebuffer;
-        _ftime( &timebuffer );
-        t->tv_sec=timebuffer.time;
-        t->tv_usec=1000*timebuffer.millitm;
- }
-#else
- #include <sys/time.h>
-#endif
-
-/** Returns a timestamp (now) in seconds (incl. a fractional part). */
-static inline double get_timestamp() {
-    struct timeval tp;
-    gettimeofday(&tp, NULL);
-    return double(tp.tv_sec) + tp.tv_usec / 1000000.;
-}
-
-
-#endif /* TIMINGUTIL_H_ */
diff --git a/DataStructures/TurnInstructions.h b/DataStructures/TurnInstructions.h
index 3284d9b..61de3b1 100644
--- a/DataStructures/TurnInstructions.h
+++ b/DataStructures/TurnInstructions.h
@@ -1,90 +1,90 @@
 /*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
 
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
- 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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef TURNINSTRUCTIONS_H_
-#define TURNINSTRUCTIONS_H_
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <boost/noncopyable.hpp>
+*/
 
-typedef unsigned char TurnInstruction;
+#ifndef TURN_INSTRUCTIONS_H
+#define TURN_INSTRUCTIONS_H
 
-//This is a hack until c++0x is available enough to use scoped enums
-struct TurnInstructionsClass : boost::noncopyable {
-
-    const static TurnInstruction NoTurn = 0;          //Give no instruction at all
-    const static TurnInstruction GoStraight = 1;      //Tell user to go straight!
-    const static TurnInstruction TurnSlightRight = 2;
-    const static TurnInstruction TurnRight = 3;
-    const static TurnInstruction TurnSharpRight = 4;
-    const static TurnInstruction UTurn = 5;
-    const static TurnInstruction TurnSharpLeft = 6;
-    const static TurnInstruction TurnLeft = 7;
-    const static TurnInstruction TurnSlightLeft = 8;
-    const static TurnInstruction ReachViaPoint = 9;
-    const static TurnInstruction HeadOn = 10;
-    const static TurnInstruction EnterRoundAbout = 11;
-    const static TurnInstruction LeaveRoundAbout = 12;
-    const static TurnInstruction StayOnRoundAbout = 13;
-    const static TurnInstruction StartAtEndOfStreet = 14;
-    const static TurnInstruction ReachedYourDestination = 15;
-    const static TurnInstruction EnterAgainstAllowedDirection = 16;
-    const static TurnInstruction LeaveAgainstAllowedDirection = 17;
-
-    const static TurnInstruction AccessRestrictionFlag = 128;
-    const static TurnInstruction InverseAccessRestrictionFlag = 0x7f; // ~128 does not work without a warning.
+enum class TurnInstruction : unsigned char
+{
+    NoTurn = 0, GoStraight, TurnSlightRight, TurnRight, TurnSharpRight, UTurn,
+    TurnSharpLeft, TurnLeft, TurnSlightLeft, ReachViaPoint, HeadOn, EnterRoundAbout,
+    LeaveRoundAbout, StayOnRoundAbout, StartAtEndOfStreet, ReachedYourDestination,
+    EnterAgainstAllowedDirection, LeaveAgainstAllowedDirection,
+    InverseAccessRestrictionFlag = 127,
+    AccessRestrictionFlag = 128,
+    AccessRestrictionPenalty = 129
+};
 
-    const static int AccessRestrictionPenalty = 1 << 15; //unrelated to the bit set in the restriction flag
+struct TurnInstructionsClass
+{
+    TurnInstructionsClass() = delete;
+    TurnInstructionsClass(const TurnInstructionsClass&) = delete;
 
-    static inline TurnInstruction GetTurnDirectionOfInstruction( const double angle ) {
-        if(angle >= 23 && angle < 67) {
-            return TurnSharpRight;
+    static inline TurnInstruction GetTurnDirectionOfInstruction(const double angle)
+    {
+        if (angle >= 23 && angle < 67)
+        {
+            return TurnInstruction::TurnSharpRight;
         }
-        if (angle >= 67 && angle < 113) {
-            return TurnRight;
+        if (angle >= 67 && angle < 113)
+        {
+            return TurnInstruction::TurnRight;
         }
-        if (angle >= 113 && angle < 158) {
-            return TurnSlightRight;
+        if (angle >= 113 && angle < 158)
+        {
+            return TurnInstruction::TurnSlightRight;
         }
-        if (angle >= 158 && angle < 202) {
-            return GoStraight;
+        if (angle >= 158 && angle < 202)
+        {
+            return TurnInstruction::GoStraight;
         }
-        if (angle >= 202 && angle < 248) {
-            return TurnSlightLeft;
+        if (angle >= 202 && angle < 248)
+        {
+            return TurnInstruction::TurnSlightLeft;
         }
-        if (angle >= 248 && angle < 292) {
-            return TurnLeft;
+        if (angle >= 248 && angle < 292)
+        {
+            return TurnInstruction::TurnLeft;
         }
-        if (angle >= 292 && angle < 336) {
-            return TurnSharpLeft;
+        if (angle >= 292 && angle < 336)
+        {
+            return TurnInstruction::TurnSharpLeft;
         }
-        return UTurn;
+        return TurnInstruction::UTurn;
     }
 
-    static inline bool TurnIsNecessary ( const short turnInstruction ) {
-        if(NoTurn == turnInstruction || StayOnRoundAbout == turnInstruction)
+    static inline bool TurnIsNecessary(const TurnInstruction turn_instruction)
+    {
+        if (TurnInstruction::NoTurn == turn_instruction || TurnInstruction::StayOnRoundAbout == turn_instruction)
+        {
             return false;
+        }
         return true;
     }
-
 };
 
-static TurnInstructionsClass TurnInstructions;
-
-#endif /* TURNINSTRUCTIONS_H_ */
+#endif /* TURN_INSTRUCTIONS_H */
diff --git a/DataStructures/XORFastHash.h b/DataStructures/XORFastHash.h
index c3c1470..ee36830 100644
--- a/DataStructures/XORFastHash.h
+++ b/DataStructures/XORFastHash.h
@@ -1,31 +1,39 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef FASTXORHASH_H_
-#define FASTXORHASH_H_
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef XOR_FAST_HASH_H
+#define XOR_FAST_HASH_H
 
 #include <algorithm>
 #include <vector>
 
 /*
-    This is an implementation of Tabulation hashing, which has suprising properties like universality.
+    This is an implementation of Tabulation hashing, which has suprising properties like
+   universality.
     The space requirement is 2*2^16 = 256 kb of memory, which fits into L2 cache.
     Evaluation boils down to 10 or less assembly instruction on any recent X86 CPU:
 
@@ -41,49 +49,61 @@ or see http://www.gnu.org/licenses/agpl.txt.
     10: ret
 
 */
-class XORFastHash { //65k entries
+class XORFastHash
+{ // 65k entries
     std::vector<unsigned short> table1;
     std::vector<unsigned short> table2;
-public:
-    XORFastHash() {
+
+  public:
+    XORFastHash()
+    {
         table1.resize(2 << 16);
         table2.resize(2 << 16);
-        for(unsigned i = 0; i < (2 << 16); ++i) {
-            table1[i] = i; table2[i] = i;
+        for (unsigned i = 0; i < (2 << 16); ++i)
+        {
+            table1[i] = i;
+            table2[i] = i;
         }
         std::random_shuffle(table1.begin(), table1.end());
         std::random_shuffle(table2.begin(), table2.end());
     }
 
-    inline unsigned short operator()(const unsigned originalValue) const {
+    inline unsigned short operator()(const unsigned originalValue) const
+    {
         unsigned short lsb = ((originalValue) & 0xffff);
         unsigned short msb = (((originalValue) >> 16) & 0xffff);
         return table1[lsb] ^ table2[msb];
     }
 };
 
-class XORMiniHash { //256 entries
+class XORMiniHash
+{ // 256 entries
     std::vector<unsigned char> table1;
     std::vector<unsigned char> table2;
     std::vector<unsigned char> table3;
     std::vector<unsigned char> table4;
 
-public:
-    XORMiniHash() {
+  public:
+    XORMiniHash()
+    {
         table1.resize(1 << 8);
         table2.resize(1 << 8);
         table3.resize(1 << 8);
         table4.resize(1 << 8);
-        for(unsigned i = 0; i < (1 << 8); ++i) {
-            table1[i] = i; table2[i] = i;
-            table3[i] = i; table4[i] = i;
+        for (unsigned i = 0; i < (1 << 8); ++i)
+        {
+            table1[i] = i;
+            table2[i] = i;
+            table3[i] = i;
+            table4[i] = i;
         }
         std::random_shuffle(table1.begin(), table1.end());
         std::random_shuffle(table2.begin(), table2.end());
         std::random_shuffle(table3.begin(), table3.end());
         std::random_shuffle(table4.begin(), table4.end());
     }
-    unsigned char operator()(const unsigned originalValue) const {
+    unsigned char operator()(const unsigned originalValue) const
+    {
         unsigned char byte1 = ((originalValue) & 0xff);
         unsigned char byte2 = ((originalValue >> 8) & 0xff);
         unsigned char byte3 = ((originalValue >> 16) & 0xff);
@@ -92,4 +112,4 @@ public:
     }
 };
 
-#endif /* FASTXORHASH_H_ */
+#endif // XOR_FAST_HASH_H
diff --git a/DataStructures/XORFastHashStorage.h b/DataStructures/XORFastHashStorage.h
index 91820e1..abdb9ac 100644
--- a/DataStructures/XORFastHashStorage.h
+++ b/DataStructures/XORFastHashStorage.h
@@ -1,80 +1,89 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef XORFASTHASHSTORAGE_H_
-#define XORFASTHASHSTORAGE_H_
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <climits>
-#include <vector>
-#include <bitset>
+*/
+
+#ifndef XOR_FAST_HASH_STORAGE_H
+#define XOR_FAST_HASH_STORAGE_H
 
 #include "XORFastHash.h"
 
-template< typename NodeID, typename Key >
-class XORFastHashStorage {
-public:
-    struct HashCell{
+#include <limits>
+#include <vector>
+
+template <typename NodeID, typename Key> class XORFastHashStorage
+{
+  public:
+    struct HashCell
+    {
         Key key;
         NodeID id;
         unsigned time;
-        HashCell() : key(UINT_MAX), id(UINT_MAX), time(UINT_MAX) {}
+        HashCell()
+            : key(std::numeric_limits<unsigned>::max()), id(std::numeric_limits<unsigned>::max()),
+              time(std::numeric_limits<unsigned>::max())
+        {
+        }
 
-        HashCell(const HashCell & other) : key(other.key), id(other.id), time(other.time) { }
+        HashCell(const HashCell &other) : key(other.key), id(other.id), time(other.time) {}
 
-        inline operator Key() const {
-            return key;
-        }
+        inline operator Key() const { return key; }
 
-        inline void operator=(const Key & keyToInsert) {
-            key = keyToInsert;
-        }
+        inline void operator=(const Key &key_to_insert) { key = key_to_insert; }
     };
 
-    XORFastHashStorage( size_t ) : positions(2<<16), currentTimestamp(0) { }
+    explicit XORFastHashStorage(size_t) : positions(2 << 16), current_timestamp(0) {}
 
-    inline HashCell& operator[]( const NodeID node ) {
-        unsigned short position = fastHash(node);
-        while((positions[position].time == currentTimestamp) && (positions[position].id != node)){
-            ++position %= (2<<16);
+    inline HashCell &operator[](const NodeID node)
+    {
+        unsigned short position = fast_hasher(node);
+        while ((positions[position].time == current_timestamp) && (positions[position].id != node))
+        {
+            ++position %= (2 << 16);
         }
 
         positions[position].id = node;
-        positions[position].time = currentTimestamp;
+        positions[position].time = current_timestamp;
         return positions[position];
     }
 
-    inline void Clear() {
-        ++currentTimestamp;
-        if(UINT_MAX == currentTimestamp) {
+    inline void Clear()
+    {
+        ++current_timestamp;
+        if (std::numeric_limits<unsigned>::max() == current_timestamp)
+        {
             positions.clear();
-            positions.resize((2<<16));
+            positions.resize((2 << 16));
         }
     }
 
-private:
-    XORFastHashStorage() : positions(2<<16), currentTimestamp(0) {}
+  private:
+    XORFastHashStorage() : positions(2 << 16), current_timestamp(0) {}
     std::vector<HashCell> positions;
-    XORFastHash fastHash;
-    unsigned currentTimestamp;
+    XORFastHash fast_hasher;
+    unsigned current_timestamp;
 };
 
-
-#endif /* XORFASTHASHSTORAGE_H_ */
-
+#endif // XOR_FAST_HASH_STORAGE_H
diff --git a/Descriptors/BaseDescriptor.h b/Descriptors/BaseDescriptor.h
index 2ead8bd..d06b9b6 100644
--- a/Descriptors/BaseDescriptor.h
+++ b/Descriptors/BaseDescriptor.h
@@ -1,55 +1,61 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef BASE_DESCRIPTOR_H_
-#define BASE_DESCRIPTOR_H_
-
-#include <cassert>
-#include <cmath>
-#include <cstdio>
-#include <string>
-#include <vector>
 
-#include "../typedefs.h"
-#include "../DataStructures/HashTable.h"
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef BASE_DESCRIPTOR_H
+#define BASE_DESCRIPTOR_H
+
 #include "../DataStructures/PhantomNodes.h"
-#include "../DataStructures/SearchEngine.h"
-#include "../Util/StringUtil.h"
+#include "../DataStructures/RawRouteData.h"
+#include "../typedefs.h"
 
-#include "../Plugins/RawRouteData.h"
+#include <osrm/Reply.h>
+
+#include <string>
+#include <vector>
 
-struct _DescriptorConfig {
-    _DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(true), z(18) {}
+struct DescriptorConfig
+{
+    DescriptorConfig() : instructions(true), geometry(true), encode_geometry(true), zoom_level(18)
+    {
+    }
     bool instructions;
     bool geometry;
-    bool encodeGeometry;
-    unsigned short z;
+    bool encode_geometry;
+    unsigned short zoom_level;
 };
 
-class BaseDescriptor {
-public:
-    BaseDescriptor() { }
-    //Maybe someone can explain the pure virtual destructor thing to me (dennis)
-    virtual ~BaseDescriptor() { }
-    virtual void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) = 0;
-    virtual void SetConfig(const _DescriptorConfig & config) = 0;
+template <class DataFacadeT> class BaseDescriptor
+{
+  public:
+    BaseDescriptor() {}
+    // Maybe someone can explain the pure virtual destructor thing to me (dennis)
+    virtual ~BaseDescriptor() {}
+    virtual void Run(const RawRouteData &raw_route, http::Reply &reply) = 0;
+    virtual void SetConfig(const DescriptorConfig &config) = 0;
 };
 
-#endif /* BASE_DESCRIPTOR_H_ */
+#endif // BASE_DESCRIPTOR_H
diff --git a/Descriptors/DescriptionFactory.cpp b/Descriptors/DescriptionFactory.cpp
index b1f2f85..5c9cbef 100644
--- a/Descriptors/DescriptionFactory.cpp
+++ b/Descriptors/DescriptionFactory.cpp
@@ -1,210 +1,93 @@
 /*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
 
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
- 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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#include "DescriptionFactory.h"
-
-DescriptionFactory::DescriptionFactory() : entireLength(0) { }
-
-DescriptionFactory::~DescriptionFactory() { }
-
-inline double DescriptionFactory::DegreeToRadian(const double degree) const {
-        return degree * (M_PI/180);
-}
-
-inline double DescriptionFactory::RadianToDegree(const double radian) const {
-        return radian * (180/M_PI);
-}
-
-double DescriptionFactory::GetBearing(const _Coordinate& A, const _Coordinate& B) const {
-    double deltaLong = DegreeToRadian(B.lon/100000. - A.lon/100000.);
-
-    double lat1 = DegreeToRadian(A.lat/100000.);
-    double lat2 = DegreeToRadian(B.lat/100000.);
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-    double y = sin(deltaLong) * cos(lat2);
-    double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(deltaLong);
-    double result = RadianToDegree(atan2(y, x));
-    while(result <= 0.)
-        result += 360.;
-    while(result >= 360.)
-        result -= 360.;
+*/
 
-    return result;
-}
+#include "DescriptionFactory.h"
 
-void DescriptionFactory::SetStartSegment(const PhantomNode & _startPhantom) {
-    startPhantom = _startPhantom;
-    AppendSegment(_startPhantom.location, _PathData(0, _startPhantom.nodeBasedEdgeNameID, 10, _startPhantom.weight1));
-}
+#include <osrm/Coordinate.h>
 
-void DescriptionFactory::SetEndSegment(const PhantomNode & _targetPhantom) {
-    targetPhantom = _targetPhantom;
-    pathDescription.push_back(SegmentInformation(_targetPhantom.location, _targetPhantom.nodeBasedEdgeNameID, 0, _targetPhantom.weight1, 0, true) );
-}
+#include "../typedefs.h"
+#include "../Algorithms/PolylineCompressor.h"
+#include "../DataStructures/PhantomNodes.h"
+#include "../DataStructures/RawRouteData.h"
+#include "../DataStructures/SegmentInformation.h"
+#include "../DataStructures/TurnInstructions.h"
 
-void DescriptionFactory::AppendSegment(const _Coordinate & coordinate, const _PathData & data ) {
-    if(1 == pathDescription.size() && pathDescription.back().location == coordinate) {
-        pathDescription.back().nameID = data.nameID;
-    } else {
-        pathDescription.push_back(SegmentInformation(coordinate, data.nameID, 0, data.durationOfSegment, data.turnInstruction) );
-    }
-}
+DescriptionFactory::DescriptionFactory() : entireLength(0) { via_indices.push_back(0); }
 
-void DescriptionFactory::AppendEncodedPolylineString(std::string & output, bool isEncoded) {
-    if(isEncoded)
-        pc.printEncodedString(pathDescription, output);
-    else
-        pc.printUnencodedString(pathDescription, output);
-}
+std::vector<unsigned> const &DescriptionFactory::GetViaIndices() const { return via_indices; }
 
-void DescriptionFactory::AppendEncodedPolylineString(std::string &output) {
-    pc.printEncodedString(pathDescription, output);
+void DescriptionFactory::SetStartSegment(const PhantomNode &source, const bool traversed_in_reverse)
+{
+    start_phantom = source;
+    const EdgeWeight segment_duration =
+        (traversed_in_reverse ? source.reverse_weight : source.forward_weight);
+    AppendSegment(source.location,
+                  PathData(0, source.name_id, TurnInstruction::HeadOn, segment_duration));
+    BOOST_ASSERT(path_description.back().duration == segment_duration);
 }
 
-void DescriptionFactory::AppendUnencodedPolylineString(std::string &output) {
-    pc.printUnencodedString(pathDescription, output);
+void DescriptionFactory::SetEndSegment(const PhantomNode &target, const bool traversed_in_reverse)
+{
+    target_phantom = target;
+    const EdgeWeight segment_duration =
+        (traversed_in_reverse ? target.reverse_weight : target.forward_weight);
+    path_description.emplace_back(
+        target.location, target.name_id, segment_duration, 0.f, TurnInstruction::NoTurn, true, true);
+    BOOST_ASSERT(path_description.back().duration == segment_duration);
 }
 
-void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLevel) {
-
-    if(0 == pathDescription.size())
+void DescriptionFactory::AppendSegment(const FixedPointCoordinate &coordinate,
+                                       const PathData &path_point)
+{
+    if ((1 == path_description.size()) && (path_description.back().location == coordinate))
+    {
+        path_description.back().name_id = path_point.name_id;
         return;
-
-//    unsigned entireLength = 0;
-    /** starts at index 1 */
-    pathDescription[0].length = 0;
-    for(unsigned i = 1; i < pathDescription.size(); ++i) {
-        pathDescription[i].length = ApproximateDistanceByEuclid(pathDescription[i-1].location, pathDescription[i].location);
     }
 
-    double lengthOfSegment = 0;
-    unsigned durationOfSegment = 0;
-    unsigned indexOfSegmentBegin = 0;
-
-    std::string string0 = sEngine.GetEscapedNameForNameID(pathDescription[0].nameID);
-    std::string string1;
-
-
-    /*Simplify turn instructions
-    Input :
-    10. Turn left on B 36 for 20 km
-    11. Continue on B 35; B 36 for 2 km
-    12. Continue on B 36 for 13 km
-
-    becomes:
-    10. Turn left on B 36 for 35 km
-    */
-//TODO: rework to check only end and start of string.
-//		stl string is way to expensive
-
-//    unsigned lastTurn = 0;
-//    for(unsigned i = 1; i < pathDescription.size(); ++i) {
-//        string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
-//        if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
-//            if(std::string::npos != string0.find(string1+";")
-//            		|| std::string::npos != string0.find(";"+string1)
-//            		|| std::string::npos != string0.find(string1+" ;")
-//                    || std::string::npos != string0.find("; "+string1)
-//                    ){
-//                INFO("->next correct: " << string0 << " contains " << string1);
-//                for(; lastTurn != i; ++lastTurn)
-//                    pathDescription[lastTurn].nameID = pathDescription[i].nameID;
-//                pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
-//            } else if(std::string::npos != string1.find(string0+";")
-//            		|| std::string::npos != string1.find(";"+string0)
-//                    || std::string::npos != string1.find(string0+" ;")
-//                    || std::string::npos != string1.find("; "+string0)
-//                    ){
-//                INFO("->prev correct: " << string1 << " contains " << string0);
-//                pathDescription[i].nameID = pathDescription[i-1].nameID;
-//                pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
-//            }
-//        }
-//        if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
-//            lastTurn = i;
-//        }
-//        string0 = string1;
-//    }
-
-
-    for(unsigned i = 1; i < pathDescription.size(); ++i) {
-        entireLength += pathDescription[i].length;
-        lengthOfSegment += pathDescription[i].length;
-        durationOfSegment += pathDescription[i].duration;
-        pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
-        pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
-
-
-        if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
-            //INFO("Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID);
-            assert(pathDescription[i].necessary);
-            lengthOfSegment = 0;
-            durationOfSegment = 0;
-            indexOfSegmentBegin = i;
-        }
-    }
-    //    INFO("#segs: " << pathDescription.size());
-
-    //Post-processing to remove empty or nearly empty path segments
-    if(FLT_EPSILON > pathDescription.back().length) {
-        //        INFO("#segs: " << pathDescription.size() << ", last ratio: " << targetPhantom.ratio << ", length: " << pathDescription.back().length);
-        if(pathDescription.size() > 2){
-            pathDescription.pop_back();
-            pathDescription.back().necessary = true;
-            pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
-            targetPhantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
-            //            INFO("Deleting last turn instruction");
-        }
-    } else {
-        pathDescription[indexOfSegmentBegin].duration *= (1.-targetPhantom.ratio);
-    }
-    if(FLT_EPSILON > pathDescription[0].length) {
-        //TODO: this is never called actually?
-        if(pathDescription.size() > 2) {
-            pathDescription.erase(pathDescription.begin());
-            pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
-            pathDescription[0].necessary = true;
-            startPhantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
-            //            INFO("Deleting first turn instruction, ratio: " << startPhantom.ratio << ", length: " << pathDescription[0].length);
-        }
-    } else {
-        pathDescription[0].duration *= startPhantom.ratio;
-    }
-
-    //Generalize poly line
-    dp.Run(pathDescription, zoomLevel);
+    path_description.emplace_back(coordinate,
+                                  path_point.name_id,
+                                  path_point.segment_duration,
+                                  0,
+                                  path_point.turn_instruction);
+}
 
-    //fix what needs to be fixed else
-    for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
-        if(pathDescription[i].necessary) {
-            double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
-            pathDescription[i].bearing = angle;
-        }
+JSON::Value DescriptionFactory::AppendEncodedPolylineString(const bool return_encoded)
+{
+    if (return_encoded)
+    {
+        return polyline_compressor.printEncodedString(path_description);
     }
-
-//    BuildRouteSummary(entireLength, duration);
-    return;
+    return polyline_compressor.printUnencodedString(path_description);
 }
 
-void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time) {
-    summary.startName = startPhantom.nodeBasedEdgeNameID;
-    summary.destName = targetPhantom.nodeBasedEdgeNameID;
+void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time)
+{
+    summary.source_name_id = start_phantom.name_id;
+    summary.target_name_id = target_phantom.name_id;
     summary.BuildDurationAndLengthStrings(distance, time);
 }
diff --git a/Descriptors/DescriptionFactory.h b/Descriptors/DescriptionFactory.h
index 911aae7..d081bae 100644
--- a/Descriptors/DescriptionFactory.h
+++ b/Descriptors/DescriptionFactory.h
@@ -1,76 +1,215 @@
 /*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
 
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
- 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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef DESCRIPTIONFACTORY_H_
 #define DESCRIPTIONFACTORY_H_
 
-#include <vector>
-
-#include "../typedefs.h"
 #include "../Algorithms/DouglasPeucker.h"
 #include "../Algorithms/PolylineCompressor.h"
-#include "../DataStructures/Coordinate.h"
-#include "../DataStructures/SearchEngine.h"
+#include "../DataStructures/PhantomNodes.h"
 #include "../DataStructures/SegmentInformation.h"
 #include "../DataStructures/TurnInstructions.h"
+#include "../typedefs.h"
 
+#include <osrm/Coordinate.h>
+
+#include <limits>
+#include <vector>
+
+struct PathData;
 /* This class is fed with all way segments in consecutive order
  *  and produces the description plus the encoded polyline */
 
-class DescriptionFactory {
-    DouglasPeucker<SegmentInformation> dp;
-    PolylineCompressor pc;
-    PhantomNode startPhantom, targetPhantom;
+class DescriptionFactory
+{
+    DouglasPeucker polyline_generalizer;
+    PolylineCompressor polyline_compressor;
+    PhantomNode start_phantom, target_phantom;
 
     double DegreeToRadian(const double degree) const;
     double RadianToDegree(const double degree) const;
-public:
-    struct _RouteSummary {
-        std::string lengthString;
-        std::string durationString;
-        unsigned startName;
-        unsigned destName;
-        _RouteSummary() : lengthString("0"), durationString("0"), startName(0), destName(0) {}
-        void BuildDurationAndLengthStrings(const double distance, const unsigned time) {
-            //compute distance/duration for route summary
-            intToString(round(distance), lengthString);
-            int travelTime = time/10 + 1;
-            intToString(travelTime, durationString);
+
+    std::vector<unsigned> via_indices;
+
+  public:
+    struct RouteSummary
+    {
+        unsigned distance;
+        EdgeWeight duration;
+        unsigned source_name_id;
+        unsigned target_name_id;
+        RouteSummary() : distance(0), duration(0), source_name_id(0), target_name_id(0) {}
+
+        void BuildDurationAndLengthStrings(const double raw_distance, const unsigned raw_duration)
+        {
+            // compute distance/duration for route summary
+            distance = static_cast<unsigned>(round(raw_distance));
+            duration = static_cast<unsigned>(round(raw_duration / 10.));
         }
     } summary;
 
     double entireLength;
 
-    //I know, declaring this public is considered bad. I'm lazy
-    std::vector <SegmentInformation> pathDescription;
+    // I know, declaring this public is considered bad. I'm lazy
+    std::vector<SegmentInformation> path_description;
     DescriptionFactory();
-    virtual ~DescriptionFactory();
-    double GetBearing(const _Coordinate& C, const _Coordinate& B) const;
-    void AppendEncodedPolylineString(std::string &output);
-    void AppendUnencodedPolylineString(std::string &output);
-    void AppendSegment(const _Coordinate & coordinate, const _PathData & data);
+    void AppendSegment(const FixedPointCoordinate &coordinate, const PathData &data);
     void BuildRouteSummary(const double distance, const unsigned time);
-    void SetStartSegment(const PhantomNode & startPhantom);
-    void SetEndSegment(const PhantomNode & startPhantom);
-    void AppendEncodedPolylineString(std::string & output, bool isEncoded);
-    void Run(const SearchEngine &sEngine, const unsigned zoomLevel);
+    void SetStartSegment(const PhantomNode &start_phantom, const bool traversed_in_reverse);
+    void SetEndSegment(const PhantomNode &start_phantom, const bool traversed_in_reverse);
+    JSON::Value AppendEncodedPolylineString(const bool return_encoded);
+    std::vector<unsigned> const & GetViaIndices() const;
+
+    template <class DataFacadeT> void Run(const DataFacadeT *facade, const unsigned zoomLevel)
+    {
+        if (path_description.empty())
+        {
+            return;
+        }
+
+        /** starts at index 1 */
+        path_description[0].length = 0;
+        for (unsigned i = 1; i < path_description.size(); ++i)
+        {
+            // move down names by one, q&d hack
+            path_description[i - 1].name_id = path_description[i].name_id;
+            path_description[i].length = FixedPointCoordinate::ApproximateEuclideanDistance(
+                path_description[i - 1].location, path_description[i].location);
+        }
+
+        /*Simplify turn instructions
+        Input :
+        10. Turn left on B 36 for 20 km
+        11. Continue on B 35; B 36 for 2 km
+        12. Continue on B 36 for 13 km
+
+        becomes:
+        10. Turn left on B 36 for 35 km
+        */
+        // TODO: rework to check only end and start of string.
+        //      stl string is way to expensive
+
+        //    unsigned lastTurn = 0;
+        //    for(unsigned i = 1; i < path_description.size(); ++i) {
+        //        string1 = sEngine.GetEscapedNameForNameID(path_description[i].name_id);
+        //        if(TurnInstruction::GoStraight == path_description[i].turn_instruction) {
+        //            if(std::string::npos != string0.find(string1+";")
+        //                  || std::string::npos != string0.find(";"+string1)
+        //                  || std::string::npos != string0.find(string1+" ;")
+        //                    || std::string::npos != string0.find("; "+string1)
+        //                    ){
+        //                SimpleLogger().Write() << "->next correct: " << string0 << " contains " <<
+        //                string1;
+        //                for(; lastTurn != i; ++lastTurn)
+        //                    path_description[lastTurn].name_id = path_description[i].name_id;
+        //                path_description[i].turn_instruction = TurnInstruction::NoTurn;
+        //            } else if(std::string::npos != string1.find(string0+";")
+        //                  || std::string::npos != string1.find(";"+string0)
+        //                    || std::string::npos != string1.find(string0+" ;")
+        //                    || std::string::npos != string1.find("; "+string0)
+        //                    ){
+        //                SimpleLogger().Write() << "->prev correct: " << string1 << " contains " <<
+        //                string0;
+        //                path_description[i].name_id = path_description[i-1].name_id;
+        //                path_description[i].turn_instruction = TurnInstruction::NoTurn;
+        //            }
+        //        }
+        //        if (TurnInstruction::NoTurn != path_description[i].turn_instruction) {
+        //            lastTurn = i;
+        //        }
+        //        string0 = string1;
+        //    }
+
+        float segment_length = 0.;
+        unsigned segment_duration = 0;
+        unsigned segment_start_index = 0;
+
+        for (unsigned i = 1; i < path_description.size(); ++i)
+        {
+            entireLength += path_description[i].length;
+            segment_length += path_description[i].length;
+            segment_duration += path_description[i].duration;
+            path_description[segment_start_index].length = segment_length;
+            path_description[segment_start_index].duration = segment_duration;
+
+            if (TurnInstruction::NoTurn != path_description[i].turn_instruction)
+            {
+                BOOST_ASSERT(path_description[i].necessary);
+                segment_length = 0;
+                segment_duration = 0;
+                segment_start_index = i;
+            }
+        }
+
+        // Post-processing to remove empty or nearly empty path segments
+        if (std::numeric_limits<double>::epsilon() > path_description.back().length)
+        {
+            if (path_description.size() > 2)
+            {
+                path_description.pop_back();
+                path_description.back().necessary = true;
+                path_description.back().turn_instruction = TurnInstruction::NoTurn;
+                target_phantom.name_id = (path_description.end() - 2)->name_id;
+            }
+        }
+        if (std::numeric_limits<double>::epsilon() > path_description.front().length)
+        {
+            if (path_description.size() > 2)
+            {
+                path_description.erase(path_description.begin());
+                path_description.front().turn_instruction = TurnInstruction::HeadOn;
+                path_description.front().necessary = true;
+                start_phantom.name_id = path_description.front().name_id;
+            }
+        }
+
+        // Generalize poly line
+        polyline_generalizer.Run(path_description, zoomLevel);
+
+        // fix what needs to be fixed else
+        unsigned necessary_pieces = 0; // a running index that counts the necessary pieces
+        for (unsigned i = 0; i < path_description.size() - 1 && path_description.size() >= 2; ++i)
+        {
+            if (path_description[i].necessary)
+            {
+                ++necessary_pieces;
+                if (path_description[i].is_via_location)
+                {   //mark the end of a leg
+                    via_indices.push_back(necessary_pieces);
+                }
+                const double angle = path_description[i+1].location.GetBearing(path_description[i].location);
+                path_description[i].bearing = static_cast<unsigned>(angle * 10);
+            }
+        }
+        via_indices.push_back(necessary_pieces+1);
+        BOOST_ASSERT(via_indices.size() >= 2);
+        // BOOST_ASSERT(0 != necessary_pieces || path_description.empty());
+        return;
+    }
 };
 
 #endif /* DESCRIPTIONFACTORY_H_ */
diff --git a/Descriptors/GPXDescriptor.h b/Descriptors/GPXDescriptor.h
index 1d3389a..50efd9a 100644
--- a/Descriptors/GPXDescriptor.h
+++ b/Descriptors/GPXDescriptor.h
@@ -1,65 +1,100 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef GPX_DESCRIPTOR_H_
-#define GPX_DESCRIPTOR_H_
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef GPX_DESCRIPTOR_H
+#define GPX_DESCRIPTOR_H
 
-#include <boost/foreach.hpp>
 #include "BaseDescriptor.h"
 
-class GPXDescriptor : public BaseDescriptor{
-private:
-    _DescriptorConfig config;
-    _Coordinate current;
-
-    std::string tmp;
-public:
-    void SetConfig(const _DescriptorConfig& c) { config = c; }
-    void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
-        reply.content += ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
-        reply.content += "<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" xmlns=\"http://www.topografix.com/GPX/1/1\" "
-                "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
-                "xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
-                "\">";
-        reply.content += "<metadata><copyright author=\"Project OSRM\"><license>Data (c) OpenStreetMap contributors (ODbL)</license></copyright></metadata>";
-        reply.content += "<rte>";
-        if(rawRoute.lengthOfShortestPath != INT_MAX && rawRoute.computedShortestPath.size()) {
-            convertInternalLatLonToString(phantomNodes.startPhantom.location.lat, tmp);
-            reply.content += "<rtept lat=\"" + tmp + "\" ";
-            convertInternalLatLonToString(phantomNodes.startPhantom.location.lon, tmp);
-            reply.content += "lon=\"" + tmp + "\"></rtept>";
-
-            BOOST_FOREACH(const _PathData & pathData, rawRoute.computedShortestPath) {
-                sEngine.GetCoordinatesForNodeID(pathData.node, current);
-
-                convertInternalLatLonToString(current.lat, tmp);
-                reply.content += "<rtept lat=\"" + tmp + "\" ";
-                convertInternalLatLonToString(current.lon, tmp);
-                reply.content += "lon=\"" + tmp + "\"></rtept>";
+template <class DataFacadeT> class GPXDescriptor : public BaseDescriptor<DataFacadeT>
+{
+  private:
+    DescriptorConfig config;
+    FixedPointCoordinate current;
+    DataFacadeT * facade;
+
+    void AddRoutePoint(const FixedPointCoordinate & coordinate, std::vector<char> & output)
+    {
+        const std::string route_point_head = "<rtept lat=\"";
+        const std::string route_point_middle = " lon=\"";
+        const std::string route_point_tail = "\"></rtept>";
+
+        std::string tmp;
+
+        FixedPointCoordinate::convertInternalLatLonToString(coordinate.lat, tmp);
+        output.insert(output.end(), route_point_head.begin(), route_point_head.end());
+        output.insert(output.end(), tmp.begin(), tmp.end());
+        output.push_back('\"');
+
+        FixedPointCoordinate::convertInternalLatLonToString(coordinate.lon, tmp);
+        output.insert(output.end(), route_point_middle.begin(), route_point_middle.end());
+        output.insert(output.end(), tmp.begin(), tmp.end());
+        output.insert(output.end(), route_point_tail.begin(), route_point_tail.end());
+    }
+
+  public:
+    GPXDescriptor(DataFacadeT *facade) : facade(facade) {}
+
+    void SetConfig(const DescriptorConfig &c) { config = c; }
+
+    // TODO: reorder parameters
+    void Run(const RawRouteData &raw_route, http::Reply &reply)
+    {
+        std::string header("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+                           "<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
+                           "xmlns=\"http://www.topografix.com/GPX/1/1\" "
+                           "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
+                           "xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
+                           "\">"
+                           "<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
+                           " OpenStreetMap contributors (ODbL)</license></copyright>"
+                           "</metadata>"
+                           "<rte>");
+        reply.content.insert(reply.content.end(), header.begin(), header.end());
+        const bool found_route = (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT) &&
+                                 (!raw_route.unpacked_path_segments.front().empty());
+        if (found_route)
+        {
+            AddRoutePoint(raw_route.segment_end_coordinates.front().source_phantom.location, reply.content);
+
+            for (const std::vector<PathData> &path_data_vector : raw_route.unpacked_path_segments)
+            {
+                for (const PathData &path_data : path_data_vector)
+                {
+                    const FixedPointCoordinate current_coordinate =
+                        facade->GetCoordinateOfNode(path_data.node);
+                    AddRoutePoint(current_coordinate, reply.content);
+                }
             }
-            convertInternalLatLonToString(phantomNodes.targetPhantom.location.lat, tmp);
-            reply.content += "<rtept lat=\"" + tmp + "\" ";
-            convertInternalLatLonToString(phantomNodes.targetPhantom.location.lon, tmp);
-            reply.content += "lon=\"" + tmp + "\"></rtept>";
+            AddRoutePoint(raw_route.segment_end_coordinates.back().target_phantom.location, reply.content);
+
         }
-        reply.content += "</rte></gpx>";
+        std::string footer("</rte></gpx>");
+        reply.content.insert(reply.content.end(), footer.begin(), footer.end());
     }
 };
-#endif /* GPX_DESCRIPTOR_H_ */
+#endif // GPX_DESCRIPTOR_H
diff --git a/Descriptors/JSONDescriptor.h b/Descriptors/JSONDescriptor.h
index 1db2c68..938e4ef 100644
--- a/Descriptors/JSONDescriptor.h
+++ b/Descriptors/JSONDescriptor.h
@@ -1,392 +1,385 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef JSON_DESCRIPTOR_H_
-#define JSON_DESCRIPTOR_H_
-
-#include <algorithm>
-
-#include <boost/lambda/lambda.hpp>
-#include <boost/bind.hpp>
-
-#include "BaseDescriptor.h"
-#include "DescriptionFactory.h"
-#include "../Algorithms/ObjectToBase64.h"
-#include "../DataStructures/SegmentInformation.h"
-#include "../DataStructures/TurnInstructions.h"
-#include "../Util/Azimuth.h"
-#include "../Util/StringUtil.h"
-
-class JSONDescriptor : public BaseDescriptor{
-private:
-    _DescriptorConfig config;
-    DescriptionFactory descriptionFactory;
-    DescriptionFactory alternateDescriptionFactory;
-    _Coordinate current;
-    unsigned numberOfEnteredRestrictedAreas;
-    struct {
-        int startIndex;
-        int nameID;
-        int leaveAtExit;
-    } roundAbout;
-
-    struct Segment {
-        Segment() : nameID(-1), length(-1), position(-1) {}
-        Segment(int n, int l, int p) : nameID(n), length(l), position(p) {}
-        int nameID;
-        int length;
-        int position;
-    };
-    std::vector<Segment> shortestSegments, alternativeSegments;
-
-    struct RouteNames {
-        std::string shortestPathName1;
-        std::string shortestPathName2;
-        std::string alternativePathName1;
-        std::string alternativePathName2;
-    };
-
-public:
-    JSONDescriptor() : numberOfEnteredRestrictedAreas(0) {}
-    void SetConfig(const _DescriptorConfig & c) { config = c; }
-
-    void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
-
-        WriteHeaderToOutput(reply.content);
-
-        if(rawRoute.lengthOfShortestPath != INT_MAX) {
-            descriptionFactory.SetStartSegment(phantomNodes.startPhantom);
-            reply.content += "0,"
-                    "\"status_message\": \"Found route between points\",";
-
-            //Get all the coordinates for the computed route
-            BOOST_FOREACH(const _PathData & pathData, rawRoute.computedShortestPath) {
-                sEngine.GetCoordinatesForNodeID(pathData.node, current);
-                descriptionFactory.AppendSegment(current, pathData );
-            }
-            descriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
-        } else {
-            //We do not need to do much, if there is no route ;-)
-            reply.content += "207,"
-                    "\"status_message\": \"Cannot find route between points\",";
-        }
-
-        descriptionFactory.Run(sEngine, config.z);
-        reply.content += "\"route_geometry\": ";
-        if(config.geometry) {
-            descriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
-        } else {
-            reply.content += "[]";
-        }
-
-        reply.content += ","
-                "\"route_instructions\": [";
-        numberOfEnteredRestrictedAreas = 0;
-        if(config.instructions) {
-            BuildTextualDescription(descriptionFactory, reply, rawRoute.lengthOfShortestPath, sEngine, shortestSegments);
-        } else {
-            BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
-                TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
-                numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
-            }
-        }
-        reply.content += "],";
-        descriptionFactory.BuildRouteSummary(descriptionFactory.entireLength, rawRoute.lengthOfShortestPath - ( numberOfEnteredRestrictedAreas*TurnInstructions.AccessRestrictionPenalty));
-
-        reply.content += "\"route_summary\":";
-        reply.content += "{";
-        reply.content += "\"total_distance\":";
-        reply.content += descriptionFactory.summary.lengthString;
-        reply.content += ","
-                "\"total_time\":";
-        reply.content += descriptionFactory.summary.durationString;
-        reply.content += ","
-                "\"start_point\":\"";
-        reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.startName);
-        reply.content += "\","
-                "\"end_point\":\"";
-        reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.destName);
-        reply.content += "\"";
-        reply.content += "}";
-        reply.content +=",";
-
-        //only one alternative route is computed at this time, so this is hardcoded
-
-        if(rawRoute.lengthOfAlternativePath != INT_MAX) {
-            alternateDescriptionFactory.SetStartSegment(phantomNodes.startPhantom);
-            //Get all the coordinates for the computed route
-            BOOST_FOREACH(const _PathData & pathData, rawRoute.computedAlternativePath) {
-                sEngine.GetCoordinatesForNodeID(pathData.node, current);
-                alternateDescriptionFactory.AppendSegment(current, pathData );
-            }
-            alternateDescriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
-        }
-        alternateDescriptionFactory.Run(sEngine, config.z);
-
-        //give an array of alternative routes
-        reply.content += "\"alternative_geometries\": [";
-        if(config.geometry && INT_MAX != rawRoute.lengthOfAlternativePath) {
-            //Generate the linestrings for each alternative
-            alternateDescriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
-        }
-        reply.content += "],";
-        reply.content += "\"alternative_instructions\":[";
-        numberOfEnteredRestrictedAreas = 0;
-        if(INT_MAX != rawRoute.lengthOfAlternativePath) {
-            reply.content += "[";
-            //Generate instructions for each alternative
-            if(config.instructions) {
-                BuildTextualDescription(alternateDescriptionFactory, reply, rawRoute.lengthOfAlternativePath, sEngine, alternativeSegments);
-            } else {
-                BOOST_FOREACH(const SegmentInformation & segment, alternateDescriptionFactory.pathDescription) {
-                	TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
-                    numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
-                }
-            }
-            reply.content += "]";
-        }
-        reply.content += "],";
-        reply.content += "\"alternative_summaries\":[";
-        if(INT_MAX != rawRoute.lengthOfAlternativePath) {
-            //Generate route summary (length, duration) for each alternative
-            alternateDescriptionFactory.BuildRouteSummary(alternateDescriptionFactory.entireLength, rawRoute.lengthOfAlternativePath - ( numberOfEnteredRestrictedAreas*TurnInstructions.AccessRestrictionPenalty));
-            reply.content += "{";
-            reply.content += "\"total_distance\":";
-            reply.content += alternateDescriptionFactory.summary.lengthString;
-            reply.content += ","
-                    "\"total_time\":";
-            reply.content += alternateDescriptionFactory.summary.durationString;
-            reply.content += ","
-                    "\"start_point\":\"";
-            reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.startName);
-            reply.content += "\","
-                    "\"end_point\":\"";
-            reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.destName);
-            reply.content += "\"";
-            reply.content += "}";
-        }
-        reply.content += "],";
-
-        //Get Names for both routes
-        RouteNames routeNames;
-        GetRouteNames(shortestSegments, alternativeSegments, sEngine, routeNames);
-
-        reply.content += "\"route_name\":[\"";
-        reply.content += routeNames.shortestPathName1;
-        reply.content += "\",\"";
-        reply.content += routeNames.shortestPathName2;
-        reply.content += "\"],"
-                "\"alternative_names\":[";
-        reply.content += "[\"";
-        reply.content += routeNames.alternativePathName1;
-        reply.content += "\",\"";
-        reply.content += routeNames.alternativePathName2;
-        reply.content += "\"]";
-        reply.content += "],";
-        //list all viapoints so that the client may display it
-        reply.content += "\"via_points\":[";
-        std::string tmp;
-        if(config.geometry && INT_MAX != rawRoute.lengthOfShortestPath) {
-            for(unsigned i = 0; i < rawRoute.segmentEndCoordinates.size(); ++i) {
-                reply.content += "[";
-                if(rawRoute.segmentEndCoordinates[i].startPhantom.location.isSet())
-                    convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates[i].startPhantom.location, tmp);
-                else
-                    convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates[i], tmp);
-
-                reply.content += tmp;
-                reply.content += "],";
-            }
-            reply.content += "[";
-            if(rawRoute.segmentEndCoordinates.back().startPhantom.location.isSet())
-                convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates.back().targetPhantom.location, tmp);
-            else
-                convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates.back(), tmp);
-            reply.content += tmp;
-            reply.content += "]";
-        }
-        reply.content += "],";
-        reply.content += "\"hint_data\": {";
-        reply.content += "\"checksum\":";
-        intToString(rawRoute.checkSum, tmp);
-        reply.content += tmp;
-        reply.content += ", \"locations\": [";
-
-        std::string hint;
-        for(unsigned i = 0; i < rawRoute.segmentEndCoordinates.size(); ++i) {
-            reply.content += "\"";
-            EncodeObjectToBase64(rawRoute.segmentEndCoordinates[i].startPhantom, hint);
-            reply.content += hint;
-            reply.content += "\", ";
-        }
-        EncodeObjectToBase64(rawRoute.segmentEndCoordinates.back().targetPhantom, hint);
-        reply.content += "\"";
-        reply.content += hint;
-        reply.content += "\"]";
-        reply.content += "},";
-        reply.content += "\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.3)\"";
-        reply.content += "}";
-    }
-
-    void GetRouteNames(std::vector<Segment> & shortestSegments, std::vector<Segment> & alternativeSegments, const SearchEngine &sEngine, RouteNames & routeNames) {
-        /*** extract names for both alternatives ***/
-
-        Segment shortestSegment1, shortestSegment2;
-        Segment alternativeSegment1, alternativeSegment2;
-
-        if(0 < shortestSegments.size()) {
-            sort(shortestSegments.begin(), shortestSegments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
-            shortestSegment1 = shortestSegments[0];
-            if(0 < alternativeSegments.size()) {
-                sort(alternativeSegments.begin(), alternativeSegments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
-                alternativeSegment1 = alternativeSegments[0];
-            }
-            std::vector<Segment> shortestDifference(shortestSegments.size());
-            std::vector<Segment> alternativeDifference(alternativeSegments.size());
-            std::set_difference(shortestSegments.begin(), shortestSegments.end(), alternativeSegments.begin(), alternativeSegments.end(), shortestDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) );
-            int size_of_difference = shortestDifference.size();
-            if(0 < size_of_difference ) {
-                int i = 0;
-                while( i < size_of_difference && shortestDifference[i].nameID == shortestSegments[0].nameID) {
-                    ++i;
-                }
-                if(i < size_of_difference ) {
-                    shortestSegment2 = shortestDifference[i];
-                }
-            }
-
-            std::set_difference(alternativeSegments.begin(), alternativeSegments.end(), shortestSegments.begin(), shortestSegments.end(), alternativeDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) );
-            size_of_difference = alternativeDifference.size();
-            if(0 < size_of_difference ) {
-                int i = 0;
-                while( i < size_of_difference && alternativeDifference[i].nameID == alternativeSegments[0].nameID) {
-                    ++i;
-                }
-                if(i < size_of_difference ) {
-                    alternativeSegment2 = alternativeDifference[i];
-                }
-            }
-            if(shortestSegment1.position > shortestSegment2.position)
-                std::swap(shortestSegment1, shortestSegment2);
-
-            if(alternativeSegment1.position >  alternativeSegment2.position)
-                std::swap(alternativeSegment1, alternativeSegment2);
-
-            routeNames.shortestPathName1 = sEngine.GetEscapedNameForNameID(shortestSegment1.nameID);
-            routeNames.shortestPathName2 = sEngine.GetEscapedNameForNameID(shortestSegment2.nameID);
-
-            routeNames.alternativePathName1 = sEngine.GetEscapedNameForNameID(alternativeSegment1.nameID);
-            routeNames.alternativePathName2 = sEngine.GetEscapedNameForNameID(alternativeSegment2.nameID);
-        }
-    }
-
-    inline void WriteHeaderToOutput(std::string & output) {
-        output += "{"
-                "\"version\": 0.3,"
-                "\"status\":";
-    }
-
-    inline void BuildTextualDescription(DescriptionFactory & descriptionFactory, http::Reply & reply, const int lengthOfRoute, const SearchEngine &sEngine, std::vector<Segment> & segmentVector) {
-        //Segment information has following format:
-        //["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
-        //Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
-        //See also: http://developers.cloudmade.com/wiki/navengine/JSON_format
-        unsigned prefixSumOfNecessarySegments = 0;
-        roundAbout.leaveAtExit = 0;
-        roundAbout.nameID = 0;
-        std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction;
-        //Fetch data from Factory and generate a string from it.
-        BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
-        	TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
-            numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
-            if(TurnInstructions.TurnIsNecessary( currentInstruction) ) {
-                if(TurnInstructions.EnterRoundAbout == currentInstruction) {
-                    roundAbout.nameID = segment.nameID;
-                    roundAbout.startIndex = prefixSumOfNecessarySegments;
-                } else {
-                    if(0 != prefixSumOfNecessarySegments){
-                        reply.content += ",";
-                    }
-                    reply.content += "[\"";
-                    if(TurnInstructions.LeaveRoundAbout == currentInstruction) {
-                        intToString(TurnInstructions.EnterRoundAbout, tmpInstruction);
-                        reply.content += tmpInstruction;
-                        reply.content += "-";
-                        intToString(roundAbout.leaveAtExit+1, tmpInstruction);
-                        reply.content += tmpInstruction;
-                        roundAbout.leaveAtExit = 0;
-                    } else {
-                        intToString(currentInstruction, tmpInstruction);
-                        reply.content += tmpInstruction;
-                    }
-
-
-                    reply.content += "\",\"";
-                    reply.content += sEngine.GetEscapedNameForNameID(segment.nameID);
-                    reply.content += "\",";
-                    intToString(segment.length, tmpDist);
-                    reply.content += tmpDist;
-                    reply.content += ",";
-                    intToString(prefixSumOfNecessarySegments, tmpLength);
-                    reply.content += tmpLength;
-                    reply.content += ",";
-                    intToString(segment.duration/10, tmpDuration);
-                    reply.content += tmpDuration;
-                    reply.content += ",\"";
-                    intToString(segment.length, tmpLength);
-                    reply.content += tmpLength;
-                    reply.content += "m\",\"";
-                    reply.content += Azimuth::Get(segment.bearing);
-                    reply.content += "\",";
-                    intToString(round(segment.bearing), tmpBearing);
-                    reply.content += tmpBearing;
-                    reply.content += "]";
-
-                    segmentVector.push_back( Segment(segment.nameID, segment.length, segmentVector.size() ));
-                }
-            } else if(TurnInstructions.StayOnRoundAbout == currentInstruction) {
-                ++roundAbout.leaveAtExit;
-            }
-            if(segment.necessary)
-                ++prefixSumOfNecessarySegments;
-        }
-        if(INT_MAX != lengthOfRoute) {
-            reply.content += ",[\"";
-            intToString(TurnInstructions.ReachedYourDestination, tmpInstruction);
-            reply.content += tmpInstruction;
-            reply.content += "\",\"";
-            reply.content += "\",";
-            reply.content += "0";
-            reply.content += ",";
-            intToString(prefixSumOfNecessarySegments-1, tmpLength);
-            reply.content += tmpLength;
-            reply.content += ",";
-            reply.content += "0";
-            reply.content += ",\"";
-            reply.content += "\",\"";
-            reply.content += Azimuth::Get(0.0);
-            reply.content += "\",";
-            reply.content += "0.0";
-            reply.content += "]";
-        }
-    }
-
-};
-#endif /* JSON_DESCRIPTOR_H_ */
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef JSON_DESCRIPTOR_H_
+#define JSON_DESCRIPTOR_H_
+
+#include "BaseDescriptor.h"
+#include "DescriptionFactory.h"
+#include "../Algorithms/ObjectToBase64.h"
+#include "../Algorithms/ExtractRouteNames.h"
+#include "../DataStructures/JSONContainer.h"
+#include "../DataStructures/SegmentInformation.h"
+#include "../DataStructures/TurnInstructions.h"
+#include "../Util/Azimuth.h"
+#include "../Util/StringUtil.h"
+#include "../Util/TimingUtil.h"
+
+#include <algorithm>
+
+template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFacadeT>
+{
+  private:
+    DataFacadeT *facade;
+    DescriptorConfig config;
+    DescriptionFactory description_factory, alternate_description_factory;
+    FixedPointCoordinate current;
+    unsigned entered_restricted_area_count;
+    struct RoundAbout
+    {
+        RoundAbout() : start_index(INT_MAX), name_id(INVALID_NAMEID), leave_at_exit(INT_MAX) {}
+        int start_index;
+        unsigned name_id;
+        int leave_at_exit;
+    } round_about;
+
+    struct Segment
+    {
+        Segment() : name_id(INVALID_NAMEID), length(-1), position(0) {}
+        Segment(unsigned n, int l, unsigned p) : name_id(n), length(l), position(p) {}
+        unsigned name_id;
+        int length;
+        unsigned position;
+    };
+    std::vector<Segment> shortest_path_segments, alternative_path_segments;
+    ExtractRouteNames<DataFacadeT, Segment> GenerateRouteNames;
+
+  public:
+    JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0) {}
+
+    void SetConfig(const DescriptorConfig &c) { config = c; }
+
+    unsigned DescribeLeg(const std::vector<PathData> route_leg,
+                         const PhantomNodes &leg_phantoms,
+                         const bool target_traversed_in_reverse)
+    {
+        unsigned added_element_count = 0;
+        // Get all the coordinates for the computed route
+        FixedPointCoordinate current_coordinate;
+        for (const PathData &path_data : route_leg)
+        {
+            current_coordinate = facade->GetCoordinateOfNode(path_data.node);
+            description_factory.AppendSegment(current_coordinate, path_data);
+            ++added_element_count;
+        }
+        description_factory.SetEndSegment(leg_phantoms.target_phantom, target_traversed_in_reverse);
+        ++added_element_count;
+        BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
+        return added_element_count;
+    }
+
+    void Run(const RawRouteData &raw_route, http::Reply &reply)
+    {
+        JSON::Object json_result;
+        if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
+        {
+            // We do not need to do much, if there is no route ;-)
+            json_result.values["status"] = 207;
+            json_result.values["status_message"] = "Cannot find route between points";
+            JSON::render(reply.content, json_result);
+            return;
+        }
+
+        // check if first segment is non-zero
+        std::string road_name = facade->GetEscapedNameForNameID(
+            raw_route.segment_end_coordinates.front().source_phantom.name_id);
+
+        BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
+                     raw_route.segment_end_coordinates.size());
+
+        description_factory.SetStartSegment(
+            raw_route.segment_end_coordinates.front().source_phantom,
+            raw_route.source_traversed_in_reverse.front());
+        json_result.values["status"] = 0;
+        json_result.values["status_message"] = "Found route between points";
+
+        // for each unpacked segment add the leg to the description
+        for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
+        {
+#ifndef NDEBUG
+            const int added_segments =
+#endif
+                DescribeLeg(raw_route.unpacked_path_segments[i],
+                            raw_route.segment_end_coordinates[i],
+                            raw_route.target_traversed_in_reverse[i]);
+            BOOST_ASSERT(0 < added_segments);
+        }
+        description_factory.Run(facade, config.zoom_level);
+
+        if (config.geometry)
+        {
+            JSON::Value route_geometry =
+                description_factory.AppendEncodedPolylineString(config.encode_geometry);
+            json_result.values["route_geometry"] = route_geometry;
+        }
+        if (config.instructions)
+        {
+            JSON::Array json_route_instructions;
+            BuildTextualDescription(description_factory,
+                                    json_route_instructions,
+                                    raw_route.shortest_path_length,
+                                    shortest_path_segments);
+            json_result.values["route_instructions"] = json_route_instructions;
+        }
+        description_factory.BuildRouteSummary(description_factory.entireLength,
+                                              raw_route.shortest_path_length);
+        JSON::Object json_route_summary;
+        json_route_summary.values["total_distance"] = description_factory.summary.distance;
+        json_route_summary.values["total_time"] = description_factory.summary.duration;
+        json_route_summary.values["start_point"] =
+            facade->GetEscapedNameForNameID(description_factory.summary.source_name_id);
+        json_route_summary.values["end_point"] =
+            facade->GetEscapedNameForNameID(description_factory.summary.target_name_id);
+        json_result.values["route_summary"] = json_route_summary;
+
+        BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
+
+        JSON::Array json_via_points_array;
+        JSON::Array json_first_coordinate;
+        json_first_coordinate.values.push_back(
+            raw_route.segment_end_coordinates.front().source_phantom.location.lat /
+            COORDINATE_PRECISION);
+        json_first_coordinate.values.push_back(
+            raw_route.segment_end_coordinates.front().source_phantom.location.lon /
+            COORDINATE_PRECISION);
+        json_via_points_array.values.push_back(json_first_coordinate);
+        for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
+        {
+            std::string tmp;
+            JSON::Array json_coordinate;
+            json_coordinate.values.push_back(nodes.target_phantom.location.lat /
+                                             COORDINATE_PRECISION);
+            json_coordinate.values.push_back(nodes.target_phantom.location.lon /
+                                             COORDINATE_PRECISION);
+            json_via_points_array.values.push_back(json_coordinate);
+        }
+        json_result.values["via_points"] = json_via_points_array;
+
+        JSON::Array json_via_indices_array;
+
+        std::vector<unsigned> const &shortest_leg_end_indices = description_factory.GetViaIndices();
+        json_via_indices_array.values.insert(json_via_indices_array.values.end(),
+                                             shortest_leg_end_indices.begin(),
+                                             shortest_leg_end_indices.end());
+        json_result.values["via_indices"] = json_via_indices_array;
+
+        // only one alternative route is computed at this time, so this is hardcoded
+        if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
+        {
+            json_result.values["found_alternative"] = JSON::True();
+            BOOST_ASSERT(!raw_route.alt_source_traversed_in_reverse.empty());
+            alternate_description_factory.SetStartSegment(
+                raw_route.segment_end_coordinates.front().source_phantom,
+                raw_route.alt_source_traversed_in_reverse.front());
+            // Get all the coordinates for the computed route
+            for (const PathData &path_data : raw_route.unpacked_alternative)
+            {
+                current = facade->GetCoordinateOfNode(path_data.node);
+                alternate_description_factory.AppendSegment(current, path_data);
+            }
+            alternate_description_factory.Run(facade, config.zoom_level);
+
+            if (config.geometry)
+            {
+                JSON::Value alternate_geometry_string =
+                    alternate_description_factory.AppendEncodedPolylineString(
+                        config.encode_geometry);
+                JSON::Array json_alternate_geometries_array;
+                json_alternate_geometries_array.values.push_back(alternate_geometry_string);
+                json_result.values["alternative_geometries"] = json_alternate_geometries_array;
+            }
+            // Generate instructions for each alternative (simulated here)
+            JSON::Array json_alt_instructions;
+            JSON::Array json_current_alt_instructions;
+            if (config.instructions)
+            {
+                BuildTextualDescription(alternate_description_factory,
+                                        json_current_alt_instructions,
+                                        raw_route.alternative_path_length,
+                                        alternative_path_segments);
+                json_alt_instructions.values.push_back(json_current_alt_instructions);
+                json_result.values["alternative_instructions"] = json_alt_instructions;
+            }
+            alternate_description_factory.BuildRouteSummary(
+                alternate_description_factory.entireLength, raw_route.alternative_path_length);
+
+            JSON::Object json_alternate_route_summary;
+            JSON::Array json_alternate_route_summary_array;
+            json_alternate_route_summary.values["total_distance"] =
+                alternate_description_factory.summary.distance;
+            json_alternate_route_summary.values["total_time"] =
+                alternate_description_factory.summary.duration;
+            json_alternate_route_summary.values["start_point"] = facade->GetEscapedNameForNameID(
+                alternate_description_factory.summary.source_name_id);
+            json_alternate_route_summary.values["end_point"] = facade->GetEscapedNameForNameID(
+                alternate_description_factory.summary.target_name_id);
+            json_alternate_route_summary_array.values.push_back(json_alternate_route_summary);
+            json_result.values["alternative_summaries"] = json_alternate_route_summary_array;
+
+            std::vector<unsigned> const &alternate_leg_end_indices =
+                alternate_description_factory.GetViaIndices();
+            JSON::Array json_altenative_indices_array;
+            json_altenative_indices_array.values.insert(json_altenative_indices_array.values.end(),
+                                                        alternate_leg_end_indices.begin(),
+                                                        alternate_leg_end_indices.end());
+            json_result.values["alternative_indices"] = json_altenative_indices_array;
+        }
+        else
+        {
+            json_result.values["found_alternative"] = JSON::False();
+        }
+
+        // Get Names for both routes
+        RouteNames route_names =
+            GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade);
+        JSON::Array json_route_names;
+        json_route_names.values.push_back(route_names.shortest_path_name_1);
+        json_route_names.values.push_back(route_names.shortest_path_name_2);
+        json_result.values["route_name"] = json_route_names;
+
+        if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
+        {
+            JSON::Array json_alternate_names_array;
+            JSON::Array json_alternate_names;
+            json_alternate_names.values.push_back(route_names.alternative_path_name_1);
+            json_alternate_names.values.push_back(route_names.alternative_path_name_2);
+            json_alternate_names_array.values.push_back(json_alternate_names);
+            json_result.values["alternative_names"] = json_alternate_names_array;
+        }
+
+        JSON::Object json_hint_object;
+        json_hint_object.values["checksum"] = raw_route.check_sum;
+        JSON::Array json_location_hint_array;
+        std::string hint;
+        for (unsigned i = 0; i < raw_route.segment_end_coordinates.size(); ++i)
+        {
+            EncodeObjectToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint);
+            json_location_hint_array.values.push_back(hint);
+        }
+        EncodeObjectToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint);
+        json_location_hint_array.values.push_back(hint);
+        json_hint_object.values["locations"] = json_location_hint_array;
+        json_result.values["hint_data"] = json_hint_object;
+
+        // render the content to the output array
+        TIMER_START(route_render);
+        JSON::render(reply.content, json_result);
+        TIMER_STOP(route_render);
+        SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render);
+    }
+
+    // TODO: reorder parameters
+    inline void BuildTextualDescription(DescriptionFactory &description_factory,
+                                        JSON::Array &json_instruction_array,
+                                        const int route_length,
+                                        std::vector<Segment> &route_segments_list)
+    {
+        // Segment information has following format:
+        //["instruction id","streetname",length,position,time,"length","earth_direction",azimuth]
+        unsigned necessary_segments_running_index = 1;
+        round_about.leave_at_exit = 0;
+        round_about.name_id = 0;
+        std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
+
+        // Fetch data from Factory and generate a string from it.
+        for (const SegmentInformation &segment : description_factory.path_description)
+        {
+            JSON::Array json_instruction_row;
+            TurnInstruction current_instruction = segment.turn_instruction;
+            entered_restricted_area_count += (current_instruction != segment.turn_instruction);
+            if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
+            {
+                if (TurnInstruction::EnterRoundAbout == current_instruction)
+                {
+                    round_about.name_id = segment.name_id;
+                    round_about.start_index = necessary_segments_running_index;
+                }
+                else
+                {
+                    std::string current_turn_instruction;
+                    if (TurnInstruction::LeaveRoundAbout == current_instruction)
+                    {
+                        temp_instruction =
+                            IntToString(as_integer(TurnInstruction::EnterRoundAbout));
+                        current_turn_instruction += temp_instruction;
+                        current_turn_instruction += "-";
+                        temp_instruction = IntToString(round_about.leave_at_exit + 1);
+                        current_turn_instruction += temp_instruction;
+                        round_about.leave_at_exit = 0;
+                    }
+                    else
+                    {
+                        temp_instruction = IntToString(as_integer(current_instruction));
+                        current_turn_instruction += temp_instruction;
+                    }
+                    json_instruction_row.values.push_back(current_turn_instruction);
+
+                    json_instruction_row.values.push_back(
+                        facade->GetEscapedNameForNameID(segment.name_id));
+                    json_instruction_row.values.push_back(std::round(segment.length));
+                    json_instruction_row.values.push_back(necessary_segments_running_index);
+                    json_instruction_row.values.push_back(round(segment.duration / 10));
+                    json_instruction_row.values.push_back(
+                        UintToString(static_cast<unsigned>(segment.length)) + "m");
+                    const double bearing_value = (segment.bearing / 10.) ;
+                    json_instruction_row.values.push_back(Azimuth::Get(bearing_value));
+                    json_instruction_row.values.push_back(static_cast<unsigned>(round(bearing_value)));
+
+                    route_segments_list.emplace_back(
+                        segment.name_id, segment.length, route_segments_list.size());
+                    json_instruction_array.values.push_back(json_instruction_row);
+                }
+            }
+            else if (TurnInstruction::StayOnRoundAbout == current_instruction)
+            {
+                ++round_about.leave_at_exit;
+            }
+            if (segment.necessary)
+            {
+                ++necessary_segments_running_index;
+            }
+        }
+
+        // TODO: check if this in an invariant
+        if (INVALID_EDGE_WEIGHT != route_length)
+        {
+            JSON::Array json_last_instruction_row;
+            temp_instruction = IntToString(as_integer(TurnInstruction::ReachedYourDestination));
+            json_last_instruction_row.values.push_back(temp_instruction);
+            json_last_instruction_row.values.push_back("");
+            json_last_instruction_row.values.push_back(0);
+            json_last_instruction_row.values.push_back(necessary_segments_running_index - 1);
+            json_last_instruction_row.values.push_back(0);
+            json_last_instruction_row.values.push_back("0m");
+            json_last_instruction_row.values.push_back(Azimuth::Get(0.0));
+            json_last_instruction_row.values.push_back(0.);
+            json_instruction_array.values.push_back(json_last_instruction_row);
+        }
+    }
+};
+
+#endif /* JSON_DESCRIPTOR_H_ */
diff --git a/Extractor/BaseParser.cpp b/Extractor/BaseParser.cpp
index 6981e95..4ab090f 100644
--- a/Extractor/BaseParser.cpp
+++ b/Extractor/BaseParser.cpp
@@ -1,114 +1,137 @@
 /*
-open source routing machine
-Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
 */
 
 #include "BaseParser.h"
+#include "ExtractionWay.h"
+#include "ScriptingEnvironment.h"
+
+#include "../DataStructures/ImportNode.h"
+#include "../Util/LuaUtil.h"
+#include "../Util/OSRMException.h"
+#include "../Util/SimpleLogger.h"
+
+#include <boost/algorithm/string.hpp>
+#include <boost/algorithm/string/regex.hpp>
+#include <boost/ref.hpp>
+#include <boost/regex.hpp>
 
-BaseParser::BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se) :
-extractor_callbacks(ec), scriptingEnvironment(se), luaState(NULL), use_turn_restrictions(true) {
-    luaState = se.getLuaStateForThreadID(0);
+BaseParser::BaseParser(ExtractorCallbacks *extractor_callbacks,
+                       ScriptingEnvironment &scripting_environment)
+    : extractor_callbacks(extractor_callbacks),
+      lua_state(scripting_environment.getLuaState()),
+      scripting_environment(scripting_environment), use_turn_restrictions(true)
+{
     ReadUseRestrictionsSetting();
     ReadRestrictionExceptions();
 }
 
-void BaseParser::ReadUseRestrictionsSetting() {
-    if( 0 != luaL_dostring( luaState, "return use_turn_restrictions\n") ) {
-        ERR(lua_tostring( luaState,-1)<< " occured in scripting block");
+void BaseParser::ReadUseRestrictionsSetting()
+{
+    if (0 != luaL_dostring(lua_state, "return use_turn_restrictions\n"))
+    {
+        throw OSRMException("ERROR occured in scripting block");
     }
-    if( lua_isboolean( luaState, -1) ) {
-        use_turn_restrictions = lua_toboolean(luaState, -1);
+    if (lua_isboolean(lua_state, -1))
+    {
+        use_turn_restrictions = lua_toboolean(lua_state, -1);
     }
-    if( use_turn_restrictions ) {
-        INFO("Using turn restrictions" );
-    } else {
-        INFO("Ignoring turn restrictions" );
+    if (use_turn_restrictions)
+    {
+        SimpleLogger().Write() << "Using turn restrictions";
+    }
+    else
+    {
+        SimpleLogger().Write() << "Ignoring turn restrictions";
     }
 }
 
-void BaseParser::ReadRestrictionExceptions() {
-    if(lua_function_exists(luaState, "get_exceptions" )) {
-        //get list of turn restriction exceptions
-        try {
-            luabind::call_function<void>(
-                luaState,
-                "get_exceptions",
-                boost::ref(restriction_exceptions)
-                );
-            INFO("Found " << restriction_exceptions.size() << " exceptions to turn restriction");
-            BOOST_FOREACH(std::string & str, restriction_exceptions) {
-                INFO("   " << str);
-            }
-        } catch (const luabind::error &er) {
-            lua_State* Ler=er.state();
-            report_errors(Ler, -1);
-            ERR(er.what());
+void BaseParser::ReadRestrictionExceptions()
+{
+    if (lua_function_exists(lua_state, "get_exceptions"))
+    {
+        // get list of turn restriction exceptions
+        luabind::call_function<void>(
+            lua_state, "get_exceptions", boost::ref(restriction_exceptions));
+        const unsigned exception_count = restriction_exceptions.size();
+        SimpleLogger().Write() << "Found " << exception_count
+                               << " exceptions to turn restrictions:";
+        for (const std::string &str : restriction_exceptions)
+        {
+            SimpleLogger().Write() << "  " << str;
         }
-    } else {
-        INFO("Found no exceptions to turn restrictions");
+    }
+    else
+    {
+        SimpleLogger().Write() << "Found no exceptions to turn restrictions";
     }
 }
 
-void BaseParser::report_errors(lua_State *L, const int status) const {
-    if( 0!=status ) {
-        std::cerr << "-- " << lua_tostring(L, -1) << std::endl;
-        lua_pop(L, 1); // remove error message
+void BaseParser::report_errors(lua_State *lua_state, const int status) const
+{
+    if (0 != status)
+    {
+        std::cerr << "-- " << lua_tostring(lua_state, -1) << std::endl;
+        lua_pop(lua_state, 1); // remove error message
     }
 }
 
-void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* localLuaState) {
-    try {
-        luabind::call_function<void>( localLuaState, "node_function", boost::ref(n) );
-    } catch (const luabind::error &er) {
-        lua_State* Ler=er.state();
-        report_errors(Ler, -1);
-        ERR(er.what());
-    }
+void BaseParser::ParseNodeInLua(ImportNode &node, lua_State *local_lua_state)
+{
+    luabind::call_function<void>(local_lua_state, "node_function", boost::ref(node));
 }
 
-void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* localLuaState) {
-    if(2 > w.path.size()) {
-        return;
-    }
-    try {
-        luabind::call_function<void>( localLuaState, "way_function", boost::ref(w) );
-    } catch (const luabind::error &er) {
-        lua_State* Ler=er.state();
-        report_errors(Ler, -1);
-        ERR(er.what());
-    }
+void BaseParser::ParseWayInLua(ExtractionWay &way, lua_State *local_lua_state)
+{
+    luabind::call_function<void>(local_lua_state, "way_function", boost::ref(way));
 }
 
-bool BaseParser::ShouldIgnoreRestriction(const std::string& except_tag_string) const {
-    //should this restriction be ignored? yes if there's an overlap between:
-    //a) the list of modes in the except tag of the restriction (except_tag_string), ex: except=bus;bicycle
-    //b) the lua profile defines a hierachy of modes, ex: [access, vehicle, bicycle]
-    
-    if( "" == except_tag_string ) {
+bool BaseParser::ShouldIgnoreRestriction(const std::string &except_tag_string) const
+{
+    // should this restriction be ignored? yes if there's an overlap between:
+    // a) the list of modes in the except tag of the restriction
+    //    (except_tag_string), eg: except=bus;bicycle
+    // b) the lua profile defines a hierachy of modes,
+    //    eg: [access, vehicle, bicycle]
+
+    if (except_tag_string.empty())
+    {
         return false;
     }
-    
-    //Be warned, this is quadratic work here, but we assume that
-    //only a few exceptions are actually defined.
+
+    // Be warned, this is quadratic work here, but we assume that
+    // only a few exceptions are actually defined.
     std::vector<std::string> exceptions;
     boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*"));
-    BOOST_FOREACH(std::string& str, exceptions) {
-        if( restriction_exceptions.end() != std::find(restriction_exceptions.begin(), restriction_exceptions.end(), str) ) {
+    for (std::string &current_string : exceptions)
+    {
+        const auto string_iterator =
+            std::find(restriction_exceptions.begin(), restriction_exceptions.end(), current_string);
+        if (restriction_exceptions.end() != string_iterator)
+        {
             return true;
         }
     }
diff --git a/Extractor/BaseParser.h b/Extractor/BaseParser.h
index 6a19efa..b18da34 100644
--- a/Extractor/BaseParser.h
+++ b/Extractor/BaseParser.h
@@ -1,59 +1,67 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef BASEPARSER_H_
 #define BASEPARSER_H_
 
-extern "C" {
-#include <lua.h>
-#include <lauxlib.h>
-#include <lualib.h>
-}
-
-#include <boost/noncopyable.hpp>
+#include <string>
+#include <vector>
 
-#include "ExtractorCallbacks.h"
-#include "ScriptingEnvironment.h"
+struct lua_State;
+class ExtractorCallbacks;
+class ScriptingEnvironment;
+struct ExtractionWay;
+struct ImportNode;
 
-class BaseParser : boost::noncopyable {
-public:
-    BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se);
+class BaseParser
+{
+  public:
+    BaseParser() = delete;
+    BaseParser(const BaseParser &) = delete;
+    BaseParser(ExtractorCallbacks *extractor_callbacks,
+               ScriptingEnvironment &scripting_environment);
     virtual ~BaseParser() {}
     virtual bool ReadHeader() = 0;
     virtual bool Parse() = 0;
 
-    virtual void ParseNodeInLua(ImportNode& n, lua_State* luaStateForThread);
-    virtual void ParseWayInLua(ExtractionWay& n, lua_State* luaStateForThread);
-    virtual void report_errors(lua_State *L, const int status) const;
+    virtual void ParseNodeInLua(ImportNode &node, lua_State *lua_state);
+    virtual void ParseWayInLua(ExtractionWay &way, lua_State *lua_state);
+    virtual void report_errors(lua_State *lua_state, const int status) const;
 
-protected:   
+  protected:
     virtual void ReadUseRestrictionsSetting();
     virtual void ReadRestrictionExceptions();
-    virtual bool ShouldIgnoreRestriction(const std::string& except_tag_string) const;
-    
-    ExtractorCallbacks* extractor_callbacks;
-    ScriptingEnvironment& scriptingEnvironment;
-    lua_State* luaState;
+    virtual bool ShouldIgnoreRestriction(const std::string &except_tag_string) const;
+
+    ExtractorCallbacks *extractor_callbacks;
+    lua_State *lua_state;
+    ScriptingEnvironment &scripting_environment;
     std::vector<std::string> restriction_exceptions;
     bool use_turn_restrictions;
-
 };
 
 #endif /* BASEPARSER_H_ */
diff --git a/Extractor/ExtractionContainers.cpp b/Extractor/ExtractionContainers.cpp
index 2cb2baf..91981d6 100644
--- a/Extractor/ExtractionContainers.cpp
+++ b/Extractor/ExtractionContainers.cpp
@@ -1,306 +1,428 @@
 /*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
 
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
- 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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #include "ExtractionContainers.h"
+#include "ExtractionWay.h"
+#include "../Util/OSRMException.h"
+#include "../Util/SimpleLogger.h"
+#include "../Util/TimingUtil.h"
+#include "../DataStructures/RangeTable.h"
+
+#include <boost/assert.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+#include <stxxl/sort>
+
+#include <chrono>
+#include <limits>
+
+ExtractionContainers::ExtractionContainers()
+{
+    // Check if stxxl can be instantiated
+    stxxl::vector<unsigned> dummy_vector;
+    name_list.push_back("");
+}
+
+ExtractionContainers::~ExtractionContainers()
+{
+    used_node_id_list.clear();
+    all_nodes_list.clear();
+    all_edges_list.clear();
+    name_list.clear();
+    restrictions_list.clear();
+    way_start_end_id_list.clear();
+}
 
-void ExtractionContainers::PrepareData(const std::string & outputFileName, const std::string restrictionsFileName, const unsigned amountOfRAM) {
-    try {
-        unsigned usedNodeCounter = 0;
-        unsigned usedEdgeCounter = 0;
-        double time = get_timestamp();
-        boost::uint64_t memory_to_use = static_cast<boost::uint64_t>(amountOfRAM) * 1024 * 1024 * 1024;
+void ExtractionContainers::PrepareData(const std::string &output_file_name,
+                                       const std::string &restrictions_file_name)
+{
+    try
+    {
+        unsigned number_of_used_nodes = 0;
+        unsigned number_of_used_edges = 0;
 
         std::cout << "[extractor] Sorting used nodes        ... " << std::flush;
-        stxxl::sort(usedNodeIDs.begin(), usedNodeIDs.end(), Cmp(), memory_to_use);
-        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
+        TIMER_START(sorting_used_nodes);
+        stxxl::sort(used_node_id_list.begin(), used_node_id_list.end(), Cmp(), stxxl_memory);
+        TIMER_STOP(sorting_used_nodes);
+        std::cout << "ok, after " << TIMER_SEC(sorting_used_nodes) << "s" << std::endl;
 
-        time = get_timestamp();
         std::cout << "[extractor] Erasing duplicate nodes   ... " << std::flush;
-        stxxl::vector<NodeID>::iterator NewEnd = std::unique ( usedNodeIDs.begin(),usedNodeIDs.end() ) ;
-        usedNodeIDs.resize ( NewEnd - usedNodeIDs.begin() );
-        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
-        time = get_timestamp();
+        TIMER_START(erasing_dups);
+        auto new_end = std::unique(used_node_id_list.begin(), used_node_id_list.end());
+        used_node_id_list.resize(new_end - used_node_id_list.begin());
+        TIMER_STOP(erasing_dups);
+        std::cout << "ok, after " << TIMER_SEC(erasing_dups) << "s" << std::endl;
+
 
         std::cout << "[extractor] Sorting all nodes         ... " << std::flush;
-        stxxl::sort(allNodes.begin(), allNodes.end(), CmpNodeByID(), memory_to_use);
-        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
-        time = get_timestamp();
+        TIMER_START(sorting_nodes);
+        stxxl::sort(all_nodes_list.begin(), all_nodes_list.end(), CmpNodeByID(), stxxl_memory);
+        TIMER_STOP(sorting_nodes);
+        std::cout << "ok, after " << TIMER_SEC(sorting_nodes) << "s" << std::endl;
 
-        std::cout << "[extractor] Sorting used ways         ... " << std::flush;
-        stxxl::sort(wayStartEndVector.begin(), wayStartEndVector.end(), CmpWayByID(), memory_to_use);
-        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
 
-        std::cout << "[extractor] Sorting restrctns. by from... " << std::flush;
-        stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByFrom(), memory_to_use);
-        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
+        std::cout << "[extractor] Sorting used ways         ... " << std::flush;
+        TIMER_START(sort_ways);
+        stxxl::sort(
+            way_start_end_id_list.begin(), way_start_end_id_list.end(), CmpWayByID(), stxxl_memory);
+        TIMER_STOP(sort_ways);
+        std::cout << "ok, after " << TIMER_SEC(sort_ways) << "s" << std::endl;
+
+        std::cout << "[extractor] Sorting restrictions. by from... " << std::flush;
+        TIMER_START(sort_restrictions);
+        stxxl::sort(restrictions_list.begin(),
+                    restrictions_list.end(),
+                    CmpRestrictionContainerByFrom(),
+                    stxxl_memory);
+        TIMER_STOP(sort_restrictions);
+        std::cout << "ok, after " << TIMER_SEC(sort_restrictions) << "s" << std::endl;
 
         std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
-        STXXLRestrictionsVector::iterator restrictionsIT = restrictionsVector.begin();
-        STXXLWayIDStartEndVector::iterator wayStartAndEndEdgeIT = wayStartEndVector.begin();
-
-        while(wayStartAndEndEdgeIT != wayStartEndVector.end() && restrictionsIT != restrictionsVector.end()) {
-            if(wayStartAndEndEdgeIT->wayID < restrictionsIT->fromWay){
-                ++wayStartAndEndEdgeIT;
+        TIMER_START(fix_restriction_starts);
+        auto restrictions_iterator = restrictions_list.begin();
+        auto way_start_and_end_iterator = way_start_end_id_list.begin();
+
+        while (way_start_and_end_iterator != way_start_end_id_list.end() &&
+               restrictions_iterator != restrictions_list.end())
+        {
+            if (way_start_and_end_iterator->wayID < restrictions_iterator->fromWay)
+            {
+                ++way_start_and_end_iterator;
                 continue;
             }
-            if(wayStartAndEndEdgeIT->wayID > restrictionsIT->fromWay) {
-                ++restrictionsIT;
+
+            if (way_start_and_end_iterator->wayID > restrictions_iterator->fromWay)
+            {
+                ++restrictions_iterator;
                 continue;
             }
-            assert(wayStartAndEndEdgeIT->wayID == restrictionsIT->fromWay);
-            NodeID viaNode = restrictionsIT->restriction.viaNode;
-
-            if(wayStartAndEndEdgeIT->firstStart == viaNode) {
-                restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->firstTarget;
-            } else if(wayStartAndEndEdgeIT->firstTarget == viaNode) {
-                restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->firstStart;
-            } else if(wayStartAndEndEdgeIT->lastStart == viaNode) {
-                restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->lastTarget;
-            } else if(wayStartAndEndEdgeIT->lastTarget == viaNode) {
-                restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->lastStart;
+
+            BOOST_ASSERT(way_start_and_end_iterator->wayID == restrictions_iterator->fromWay);
+            const NodeID via_node_id = restrictions_iterator->restriction.viaNode;
+
+            if (way_start_and_end_iterator->firstStart == via_node_id)
+            {
+                restrictions_iterator->restriction.fromNode =
+                    way_start_and_end_iterator->firstTarget;
+            }
+            else if (way_start_and_end_iterator->firstTarget == via_node_id)
+            {
+                restrictions_iterator->restriction.fromNode =
+                    way_start_and_end_iterator->firstStart;
+            }
+            else if (way_start_and_end_iterator->lastStart == via_node_id)
+            {
+                restrictions_iterator->restriction.fromNode =
+                    way_start_and_end_iterator->lastTarget;
             }
-            ++restrictionsIT;
+            else if (way_start_and_end_iterator->lastTarget == via_node_id)
+            {
+                restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastStart;
+            }
+            ++restrictions_iterator;
         }
 
-        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
-        time = get_timestamp();
+        TIMER_STOP(fix_restriction_starts);
+        std::cout << "ok, after " << TIMER_SEC(fix_restriction_starts) << "s" << std::endl;
 
-        std::cout << "[extractor] Sorting restrctns. by to  ... " << std::flush;
-        stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByTo(), memory_to_use);
-        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
+        std::cout << "[extractor] Sorting restrictions. by to  ... " << std::flush;
+        TIMER_START(sort_restrictions_to);
+        stxxl::sort(restrictions_list.begin(),
+                    restrictions_list.end(),
+                    CmpRestrictionContainerByTo(),
+                    stxxl_memory);
+        TIMER_STOP(sort_restrictions_to);
+        std::cout << "ok, after " << TIMER_SEC(sort_restrictions_to) << "s" << std::endl;
 
-        time = get_timestamp();
-        unsigned usableRestrictionsCounter(0);
+        unsigned number_of_useable_restrictions = 0;
         std::cout << "[extractor] Fixing restriction ends   ... " << std::flush;
-        restrictionsIT = restrictionsVector.begin();
-        wayStartAndEndEdgeIT = wayStartEndVector.begin();
-        while(wayStartAndEndEdgeIT != wayStartEndVector.end() && restrictionsIT != restrictionsVector.end()) {
-            if(wayStartAndEndEdgeIT->wayID < restrictionsIT->toWay){
-                ++wayStartAndEndEdgeIT;
+        TIMER_START(fix_restriction_ends);
+        restrictions_iterator = restrictions_list.begin();
+        way_start_and_end_iterator = way_start_end_id_list.begin();
+        while (way_start_and_end_iterator != way_start_end_id_list.end() &&
+               restrictions_iterator != restrictions_list.end())
+        {
+            if (way_start_and_end_iterator->wayID < restrictions_iterator->toWay)
+            {
+                ++way_start_and_end_iterator;
                 continue;
             }
-            if(wayStartAndEndEdgeIT->wayID > restrictionsIT->toWay) {
-                ++restrictionsIT;
+            if (way_start_and_end_iterator->wayID > restrictions_iterator->toWay)
+            {
+                ++restrictions_iterator;
                 continue;
             }
-            NodeID viaNode = restrictionsIT->restriction.viaNode;
-            if(wayStartAndEndEdgeIT->lastStart == viaNode) {
-                restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->lastTarget;
-            } else if(wayStartAndEndEdgeIT->lastTarget == viaNode) {
-                restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->lastStart;
-            } else if(wayStartAndEndEdgeIT->firstStart == viaNode) {
-                restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->firstTarget;
-            } else if(wayStartAndEndEdgeIT->firstTarget == viaNode) {
-                restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->firstStart;
+            NodeID via_node_id = restrictions_iterator->restriction.viaNode;
+            if (way_start_and_end_iterator->lastStart == via_node_id)
+            {
+                restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastTarget;
+            }
+            else if (way_start_and_end_iterator->lastTarget == via_node_id)
+            {
+                restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastStart;
+            }
+            else if (way_start_and_end_iterator->firstStart == via_node_id)
+            {
+                restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstTarget;
+            }
+            else if (way_start_and_end_iterator->firstTarget == via_node_id)
+            {
+                restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstStart;
             }
 
-            if(UINT_MAX != restrictionsIT->restriction.fromNode && UINT_MAX != restrictionsIT->restriction.toNode) {
-                ++usableRestrictionsCounter;
+            if (std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.fromNode &&
+                std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.toNode)
+            {
+                ++number_of_useable_restrictions;
             }
-            ++restrictionsIT;
+            ++restrictions_iterator;
         }
-        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
-        INFO("usable restrictions: " << usableRestrictionsCounter );
-        //serialize restrictions
-        std::ofstream restrictionsOutstream;
-        restrictionsOutstream.open(restrictionsFileName.c_str(), std::ios::binary);
-        restrictionsOutstream.write((char*)&usableRestrictionsCounter, sizeof(unsigned));
-        for(restrictionsIT = restrictionsVector.begin(); restrictionsIT != restrictionsVector.end(); ++restrictionsIT) {
-            if(UINT_MAX != restrictionsIT->restriction.fromNode && UINT_MAX != restrictionsIT->restriction.toNode) {
-                restrictionsOutstream.write((char *)&(restrictionsIT->restriction), sizeof(_Restriction));
+        TIMER_STOP(fix_restriction_ends);
+        std::cout << "ok, after " << TIMER_SEC(fix_restriction_ends) << "s" << std::endl;
+
+        SimpleLogger().Write() << "usable restrictions: " << number_of_useable_restrictions;
+        // serialize restrictions
+        std::ofstream restrictions_out_stream;
+        restrictions_out_stream.open(restrictions_file_name.c_str(), std::ios::binary);
+        restrictions_out_stream.write((char *)&fingerprint, sizeof(FingerPrint));
+        restrictions_out_stream.write((char *)&number_of_useable_restrictions, sizeof(unsigned));
+
+        for(const auto & restriction_container : restrictions_list)
+        {
+            if (std::numeric_limits<unsigned>::max() != restriction_container.restriction.fromNode &&
+                std::numeric_limits<unsigned>::max() != restriction_container.restriction.toNode)
+            {
+                restrictions_out_stream.write((char *)&(restriction_container.restriction),
+                                              sizeof(TurnRestriction));
             }
         }
-        restrictionsOutstream.close();
+        restrictions_out_stream.close();
 
-        std::ofstream fout;
-        fout.open(outputFileName.c_str(), std::ios::binary);
-        fout.write((char*)&usedNodeCounter, sizeof(unsigned));
-        time = get_timestamp();
+        std::ofstream file_out_stream;
+        file_out_stream.open(output_file_name.c_str(), std::ios::binary);
+        file_out_stream.write((char *)&fingerprint, sizeof(FingerPrint));
+        file_out_stream.write((char *)&number_of_used_nodes, sizeof(unsigned));
         std::cout << "[extractor] Confirming/Writing used nodes     ... " << std::flush;
-
-        STXXLNodeVector::iterator nodesIT = allNodes.begin();
-        STXXLNodeIDVector::iterator usedNodeIDsIT = usedNodeIDs.begin();
-        while(usedNodeIDsIT != usedNodeIDs.end() && nodesIT != allNodes.end()) {
-            if(*usedNodeIDsIT < nodesIT->id){
-                ++usedNodeIDsIT;
+        TIMER_START(write_nodes);
+        // identify all used nodes by a merging step of two sorted lists
+        auto node_iterator = all_nodes_list.begin();
+        auto node_id_iterator = used_node_id_list.begin();
+        while (node_id_iterator != used_node_id_list.end() && node_iterator != all_nodes_list.end())
+        {
+            if (*node_id_iterator < node_iterator->node_id)
+            {
+                ++node_id_iterator;
                 continue;
             }
-            if(*usedNodeIDsIT > nodesIT->id) {
-                ++nodesIT;
+            if (*node_id_iterator > node_iterator->node_id)
+            {
+                ++node_iterator;
                 continue;
             }
-            if(*usedNodeIDsIT == nodesIT->id) {
-                fout.write((char*)&(*nodesIT), sizeof(_Node));
-                ++usedNodeCounter;
-                ++usedNodeIDsIT;
-                ++nodesIT;
-            }
+            BOOST_ASSERT(*node_id_iterator == node_iterator->node_id);
+
+            file_out_stream.write((char *)&(*node_iterator), sizeof(ExternalMemoryNode));
+
+            ++number_of_used_nodes;
+            ++node_id_iterator;
+            ++node_iterator;
         }
 
-        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
+        TIMER_STOP(write_nodes);
+        std::cout << "ok, after " << TIMER_SEC(write_nodes) << "s" << std::endl;
 
         std::cout << "[extractor] setting number of nodes   ... " << std::flush;
-        std::ios::pos_type positionInFile = fout.tellp();
-        fout.seekp(std::ios::beg);
-        fout.write((char*)&usedNodeCounter, sizeof(unsigned));
-        fout.seekp(positionInFile);
+        std::ios::pos_type previous_file_position = file_out_stream.tellp();
+        file_out_stream.seekp(std::ios::beg + sizeof(FingerPrint));
+        file_out_stream.write((char *)&number_of_used_nodes, sizeof(unsigned));
+        file_out_stream.seekp(previous_file_position);
 
         std::cout << "ok" << std::endl;
-        time = get_timestamp();
 
         // Sort edges by start.
         std::cout << "[extractor] Sorting edges by start    ... " << std::flush;
-        stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByStartID(), memory_to_use);
-        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
-        time = get_timestamp();
+        TIMER_START(sort_edges_by_start);
+        stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByStartID(), stxxl_memory);
+        TIMER_STOP(sort_edges_by_start);
+        std::cout << "ok, after " << TIMER_SEC(sort_edges_by_start) << "s" << std::endl;
+
 
         std::cout << "[extractor] Setting start coords      ... " << std::flush;
-        fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
+        TIMER_START(set_start_coords);
+        file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
         // Traverse list of edges and nodes in parallel and set start coord
-        nodesIT = allNodes.begin();
-        STXXLEdgeVector::iterator edgeIT = allEdges.begin();
-        while(edgeIT != allEdges.end() && nodesIT != allNodes.end()) {
-            if(edgeIT->start < nodesIT->id){
-                ++edgeIT;
+        node_iterator = all_nodes_list.begin();
+        auto edge_iterator = all_edges_list.begin();
+        while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
+        {
+            if (edge_iterator->start < node_iterator->node_id)
+            {
+                ++edge_iterator;
                 continue;
             }
-            if(edgeIT->start > nodesIT->id) {
-                nodesIT++;
+            if (edge_iterator->start > node_iterator->node_id)
+            {
+                node_iterator++;
                 continue;
             }
-            if(edgeIT->start == nodesIT->id) {
-                edgeIT->startCoord.lat = nodesIT->lat;
-                edgeIT->startCoord.lon = nodesIT->lon;
-                ++edgeIT;
-            }
+
+            BOOST_ASSERT(edge_iterator->start == node_iterator->node_id);
+            edge_iterator->source_coordinate.lat = node_iterator->lat;
+            edge_iterator->source_coordinate.lon = node_iterator->lon;
+            ++edge_iterator;
         }
-        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
-        time = get_timestamp();
+        TIMER_STOP(set_start_coords);
+        std::cout << "ok, after " << TIMER_SEC(set_start_coords) << "s" << std::endl;
 
         // Sort Edges by target
         std::cout << "[extractor] Sorting edges by target   ... " << std::flush;
-        stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByTargetID(), memory_to_use);
-        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
-        time = get_timestamp();
+        TIMER_START(sort_edges_by_target);
+        stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByTargetID(), stxxl_memory);
+        TIMER_STOP(sort_edges_by_target);
+        std::cout << "ok, after " << TIMER_SEC(sort_edges_by_target) << "s" << std::endl;
 
         std::cout << "[extractor] Setting target coords     ... " << std::flush;
+        TIMER_START(set_target_coords);
         // Traverse list of edges and nodes in parallel and set target coord
-        nodesIT = allNodes.begin();
-        edgeIT = allEdges.begin();
-
-        while(edgeIT != allEdges.end() && nodesIT != allNodes.end()) {
-            if(edgeIT->target < nodesIT->id){
-                ++edgeIT;
+        node_iterator = all_nodes_list.begin();
+        edge_iterator = all_edges_list.begin();
+
+        while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
+        {
+            if (edge_iterator->target < node_iterator->node_id)
+            {
+                ++edge_iterator;
                 continue;
             }
-            if(edgeIT->target > nodesIT->id) {
-                ++nodesIT;
+            if (edge_iterator->target > node_iterator->node_id)
+            {
+                ++node_iterator;
                 continue;
             }
-            if(edgeIT->target == nodesIT->id) {
-                if(edgeIT->startCoord.lat != INT_MIN && edgeIT->startCoord.lon != INT_MIN) {
-                    edgeIT->targetCoord.lat = nodesIT->lat;
-                    edgeIT->targetCoord.lon = nodesIT->lon;
-
-                    double distance = ApproximateDistance(edgeIT->startCoord.lat, edgeIT->startCoord.lon, nodesIT->lat, nodesIT->lon);
-                    assert(edgeIT->speed != -1);
-                    double weight = ( distance * 10. ) / (edgeIT->speed / 3.6);
-                    int intWeight = std::max(1, (int)std::floor((edgeIT->isDurationSet ? edgeIT->speed : weight)+.5) );
-                    int intDist = std::max(1, (int)distance);
-                    short zero = 0;
-                    short one = 1;
-
-                    fout.write((char*)&edgeIT->start, sizeof(unsigned));
-                    fout.write((char*)&edgeIT->target, sizeof(unsigned));
-                    fout.write((char*)&intDist, sizeof(int));
-                    switch(edgeIT->direction) {
-                    case ExtractionWay::notSure:
-                        fout.write((char*)&zero, sizeof(short));
-                        break;
-                    case ExtractionWay::oneway:
-                        fout.write((char*)&one, sizeof(short));
-                        break;
-                    case ExtractionWay::bidirectional:
-                        fout.write((char*)&zero, sizeof(short));
-
-                        break;
-                    case ExtractionWay::opposite:
-                        fout.write((char*)&one, sizeof(short));
-                        break;
-                    default:
-                      std::cerr << "[error] edge with no direction: " << edgeIT->direction << std::endl;
-                      assert(false);
-                        break;
-                    }
-                    fout.write((char*)&intWeight, sizeof(int));
-                    assert(edgeIT->type >= 0);
-                    fout.write((char*)&edgeIT->type, sizeof(short));
-                    fout.write((char*)&edgeIT->nameID, sizeof(unsigned));
-                    fout.write((char*)&edgeIT->isRoundabout, sizeof(bool));
-                    fout.write((char*)&edgeIT->ignoreInGrid, sizeof(bool));
-                    fout.write((char*)&edgeIT->isAccessRestricted, sizeof(bool));
-                    fout.write((char*)&edgeIT->isContraFlow, sizeof(bool));
-                    ++usedEdgeCounter;
+            BOOST_ASSERT(edge_iterator->target == node_iterator->node_id);
+            if (edge_iterator->source_coordinate.lat != std::numeric_limits<int>::min() &&
+                edge_iterator->source_coordinate.lon != std::numeric_limits<int>::min())
+            {
+                BOOST_ASSERT(edge_iterator->speed != -1);
+                BOOST_ASSERT(edge_iterator->type >= 0);
+                edge_iterator->target_coordinate.lat = node_iterator->lat;
+                edge_iterator->target_coordinate.lon = node_iterator->lon;
+
+                const double distance = FixedPointCoordinate::ApproximateEuclideanDistance(
+                    edge_iterator->source_coordinate.lat,
+                    edge_iterator->source_coordinate.lon,
+                    node_iterator->lat,
+                    node_iterator->lon);
+
+                const double weight = (distance * 10.) / (edge_iterator->speed / 3.6);
+                int integer_weight = std::max(
+                    1,
+                    (int)std::floor(
+                        (edge_iterator->is_duration_set ? edge_iterator->speed : weight) + .5));
+                int integer_distance = std::max(1, (int)distance);
+                short zero = 0;
+                short one = 1;
+
+                file_out_stream.write((char *)&edge_iterator->start, sizeof(unsigned));
+                file_out_stream.write((char *)&edge_iterator->target, sizeof(unsigned));
+                file_out_stream.write((char *)&integer_distance, sizeof(int));
+                switch (edge_iterator->direction)
+                {
+                case ExtractionWay::notSure:
+                    file_out_stream.write((char *)&zero, sizeof(short));
+                    break;
+                case ExtractionWay::oneway:
+                    file_out_stream.write((char *)&one, sizeof(short));
+                    break;
+                case ExtractionWay::bidirectional:
+                    file_out_stream.write((char *)&zero, sizeof(short));
+                    break;
+                case ExtractionWay::opposite:
+                    file_out_stream.write((char *)&one, sizeof(short));
+                    break;
+                default:
+                    throw OSRMException("edge has broken direction");
                 }
-                ++edgeIT;
+
+                file_out_stream.write((char *)&integer_weight, sizeof(int));
+                file_out_stream.write((char *)&edge_iterator->type, sizeof(short));
+                file_out_stream.write((char *)&edge_iterator->name_id, sizeof(unsigned));
+                file_out_stream.write((char *)&edge_iterator->is_roundabout, sizeof(bool));
+                file_out_stream.write((char *)&edge_iterator->is_in_tiny_cc, sizeof(bool));
+                file_out_stream.write((char *)&edge_iterator->is_access_restricted, sizeof(bool));
+                file_out_stream.write((char *)&edge_iterator->is_contra_flow, sizeof(bool));
+                file_out_stream.write((char *)&edge_iterator->is_split, sizeof(bool));
+                ++number_of_used_edges;
             }
+            ++edge_iterator;
         }
-        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
+        TIMER_STOP(set_target_coords);
+        std::cout << "ok, after " << TIMER_SEC(set_target_coords) << "s" << std::endl;
+
         std::cout << "[extractor] setting number of edges   ... " << std::flush;
 
-        fout.seekp(positionInFile);
-        fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
-        fout.close();
+        file_out_stream.seekp(previous_file_position);
+        file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
+        file_out_stream.close();
         std::cout << "ok" << std::endl;
-        time = get_timestamp();
+
         std::cout << "[extractor] writing street name index ... " << std::flush;
-        std::string nameOutFileName = (outputFileName + ".names");
-        std::ofstream nameOutFile(nameOutFileName.c_str(), std::ios::binary);
-        unsigned sizeOfNameIndex = nameVector.size();
-        nameOutFile.write((char *)&(sizeOfNameIndex), sizeof(unsigned));
-
-        BOOST_FOREACH(const std::string & str, nameVector) {
-            unsigned lengthOfRawString = strlen(str.c_str());
-            nameOutFile.write((char *)&(lengthOfRawString), sizeof(unsigned));
-            nameOutFile.write(str.c_str(), lengthOfRawString);
+        TIMER_START(write_name_index);
+        std::string name_file_streamName = (output_file_name + ".names");
+        boost::filesystem::ofstream name_file_stream(name_file_streamName, std::ios::binary);
+
+        unsigned total_length = 0;
+        std::vector<unsigned> name_lengths;
+        for (const std::string &temp_string : name_list)
+        {
+            const unsigned string_length = std::min(static_cast<unsigned>(temp_string.length()), 255u);
+            name_lengths.push_back(string_length);
+            total_length += string_length;
         }
 
-        nameOutFile.close();
-        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
-
-        //        time = get_timestamp();
-        //        cout << "[extractor] writing address list      ... " << flush;
-        //
-        //        adressFileName.append(".address");
-        //        ofstream addressOutFile(adressFileName.c_str());
-        //        for(STXXLAddressVector::iterator it = adressVector.begin(); it != adressVector.end(); it++) {
-        //            addressOutFile << it->node.id << "|" << it->node.lat << "|" << it->node.lon << "|" << it->city << "|" << it->street << "|" << it->housenumber << "|" << it->state << "|" << it->country << "\n";
-        //        }
-        //        addressOutFile.close();
-        //        cout << "ok, after " << get_timestamp() - time << "s" << endl;
+        RangeTable<> table(name_lengths);
+        name_file_stream << table;
 
-        INFO("Processed " << usedNodeCounter << " nodes and " << usedEdgeCounter << " edges");
+        name_file_stream.write((char*) &total_length, sizeof(unsigned));
+        // write all chars consecutively
+        for (const std::string &temp_string : name_list)
+        {
+            const unsigned string_length = std::min(static_cast<unsigned>(temp_string.length()), 255u);
+            name_file_stream.write(temp_string.c_str(), string_length);
+        }
 
+        name_file_stream.close();
+        TIMER_STOP(write_name_index);
+        std::cout << "ok, after " << TIMER_SEC(write_name_index) << "s" << std::endl;
 
-    } catch ( const std::exception& e ) {
-      std::cerr <<  "Caught Execption:" << e.what() << std::endl;
+        SimpleLogger().Write() << "Processed " << number_of_used_nodes << " nodes and "
+                               << number_of_used_edges << " edges";
     }
+    catch (const std::exception &e) { std::cerr << "Caught Execption:" << e.what() << std::endl; }
 }
-
diff --git a/Extractor/ExtractionContainers.h b/Extractor/ExtractionContainers.h
index f5dfa78..a272387 100644
--- a/Extractor/ExtractionContainers.h
+++ b/Extractor/ExtractionContainers.h
@@ -1,69 +1,69 @@
 /*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
 
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
- 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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef EXTRACTIONCONTAINERS_H_
 #define EXTRACTIONCONTAINERS_H_
 
+#include "InternalExtractorEdge.h"
 #include "ExtractorStructs.h"
-#include "../DataStructures/TimingUtil.h"
+#include "../DataStructures/Restriction.h"
+#include "../Util/FingerPrint.h"
 
-#include <boost/foreach.hpp>
-#include <stxxl.h>
+#include <stxxl/vector>
 
-class ExtractionContainers {
-public:
+class ExtractionContainers
+{
+#ifndef _MSC_VER
+    constexpr static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? std::numeric_limits<int>::max() : std::numeric_limits<unsigned>::max());
+#else
+    const static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? INT_MAX : UINT_MAX);
+#endif
+  public:
     typedef stxxl::vector<NodeID> STXXLNodeIDVector;
-    typedef stxxl::vector<_Node> STXXLNodeVector;
+    typedef stxxl::vector<ExternalMemoryNode> STXXLNodeVector;
     typedef stxxl::vector<InternalExtractorEdge> STXXLEdgeVector;
     typedef stxxl::vector<std::string> STXXLStringVector;
-    typedef stxxl::vector<_RawRestrictionContainer> STXXLRestrictionsVector;
-    typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
-
-    ExtractionContainers() {
-        //Check if another instance of stxxl is already running or if there is a general problem
-        try {
-            stxxl::vector<unsigned> testForRunningInstance;
-        } catch(std::exception & e) {
-            ERR("Could not instantiate STXXL layer." << std::endl << e.what());
-        }
+    typedef stxxl::vector<InputRestrictionContainer> STXXLRestrictionsVector;
+    typedef stxxl::vector<WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
 
-        nameVector.push_back("");
-    }
-    virtual ~ExtractionContainers() {
-        usedNodeIDs.clear();
-        allNodes.clear();
-        allEdges.clear();
-        nameVector.clear();
-        restrictionsVector.clear();
-        wayStartEndVector.clear();
-    }
+    STXXLNodeIDVector used_node_id_list;
+    STXXLNodeVector all_nodes_list;
+    STXXLEdgeVector all_edges_list;
+    STXXLStringVector name_list;
+    STXXLRestrictionsVector restrictions_list;
+    STXXLWayIDStartEndVector way_start_end_id_list;
+    const FingerPrint fingerprint;
 
-    void PrepareData( const std::string & outputFileName, const std::string restrictionsFileName, const unsigned amountOfRAM);
+    ExtractionContainers();
 
-    STXXLNodeIDVector           usedNodeIDs;
-    STXXLNodeVector             allNodes;
-    STXXLEdgeVector             allEdges;
-    STXXLStringVector           nameVector;
-    STXXLRestrictionsVector     restrictionsVector;
-    STXXLWayIDStartEndVector    wayStartEndVector;
+    virtual ~ExtractionContainers();
 
+    void PrepareData(const std::string &output_file_name,
+                     const std::string &restrictions_file_name);
 };
 
 #endif /* EXTRACTIONCONTAINERS_H_ */
diff --git a/Extractor/ExtractionHelperFunctions.h b/Extractor/ExtractionHelperFunctions.h
index 6771939..a918744 100644
--- a/Extractor/ExtractionHelperFunctions.h
+++ b/Extractor/ExtractionHelperFunctions.h
@@ -1,83 +1,89 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+*/
 
-#ifndef EXTRACTIONHELPERFUNCTIONS_H_
-#define EXTRACTIONHELPERFUNCTIONS_H_
+#ifndef EXTRACTION_HELPER_FUNCTIONS_H
+#define EXTRACTION_HELPER_FUNCTIONS_H
+
+#include "../Util/StringUtil.h"
 
 #include <boost/algorithm/string.hpp>
 #include <boost/algorithm/string_regex.hpp>
 #include <boost/regex.hpp>
-#include <climits>
 
-
-#include "../Util/StringUtil.h"
+#include <limits>
 
 namespace qi = boost::spirit::qi;
 
-//TODO: Move into LUA
+// TODO: Move into LUA
 
-inline bool durationIsValid(const std::string &s) {
-    boost::regex e ("((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl);
+inline bool durationIsValid(const std::string &s)
+{
+    boost::regex e(
+        "((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",
+        boost::regex_constants::icase | boost::regex_constants::perl);
 
-    std::vector< std::string > result;
-    boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ;
-    bool matched = regex_match(s, e);
+    std::vector<std::string> result;
+    boost::algorithm::split_regex(result, s, boost::regex(":"));
+    const bool matched = regex_match(s, e);
     return matched;
 }
 
-inline unsigned parseDuration(const std::string &s) {
-	unsigned hours = 0;
+inline unsigned parseDuration(const std::string &s)
+{
+    unsigned hours = 0;
     unsigned minutes = 0;
     unsigned seconds = 0;
-    boost::regex e ("((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl);
-
-    std::vector< std::string > result;
-    boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ;
-    bool matched = regex_match(s, e);
-    if(matched) {
-    	if(1 == result.size()) {
-    		minutes = stringToInt(result[0]);
-    	}
-    	if(2 == result.size()) {
-    		minutes =  stringToInt(result[1]);
-    		hours = stringToInt(result[0]);
-    	}
-    	if(3 == result.size()) {
-            seconds = stringToInt(result[2]);
-            minutes = stringToInt(result[1]);
-            hours   = stringToInt(result[0]);
-    	}
-        return 10*(3600*hours+60*minutes+seconds);
-    }
-    return UINT_MAX;
-}
-
-inline int parseMaxspeed(std::string input) { //call-by-value on purpose.
-    boost::algorithm::to_lower(input);
-    int n = stringToInt(input);
-    if (input.find("mph") != std::string::npos || input.find("mp/h") != std::string::npos) {
-        n = (n*1609)/1000;
+    boost::regex e(
+        "((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",
+        boost::regex_constants::icase | boost::regex_constants::perl);
+
+    std::vector<std::string> result;
+    boost::algorithm::split_regex(result, s, boost::regex(":"));
+    const bool matched = regex_match(s, e);
+    if (matched)
+    {
+        if (1 == result.size())
+        {
+            minutes = StringToUint(result[0]);
+        }
+        if (2 == result.size())
+        {
+            minutes = StringToUint(result[1]);
+            hours = StringToUint(result[0]);
+        }
+        if (3 == result.size())
+        {
+            seconds = StringToUint(result[2]);
+            minutes = StringToUint(result[1]);
+            hours = StringToUint(result[0]);
+        }
+        return 10 * (3600 * hours + 60 * minutes + seconds);
     }
-    return n;
+    return std::numeric_limits<unsigned>::max();
 }
 
-#endif /* EXTRACTIONHELPERFUNCTIONS_H_ */
+#endif // EXTRACTION_HELPER_FUNCTIONS_H_
diff --git a/Extractor/ExtractionWay.h b/Extractor/ExtractionWay.h
new file mode 100644
index 0000000..6c3c93d
--- /dev/null
+++ b/Extractor/ExtractionWay.h
@@ -0,0 +1,79 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef EXTRACTION_WAY_H
+#define EXTRACTION_WAY_H
+
+#include "../DataStructures/HashTable.h"
+#include "../typedefs.h"
+
+#include <string>
+#include <vector>
+
+struct ExtractionWay
+{
+    ExtractionWay() { Clear(); }
+
+    inline void Clear()
+    {
+        id = SPECIAL_NODEID;
+        nameID = INVALID_NAMEID;
+        path.clear();
+        keyVals.Clear();
+        direction = ExtractionWay::notSure;
+        speed = -1;
+        backward_speed = -1;
+        duration = -1;
+        type = -1;
+        access = true;
+        roundabout = false;
+        isAccessRestricted = false;
+        ignoreInGrid = false;
+    }
+
+    enum Directions
+    { notSure = 0,
+      oneway,
+      bidirectional,
+      opposite };
+    unsigned id;
+    unsigned nameID;
+    double speed;
+    double backward_speed;
+    double duration;
+    Directions direction;
+    std::string name;
+    short type;
+    bool access;
+    bool roundabout;
+    bool isAccessRestricted;
+    bool ignoreInGrid;
+    std::vector<NodeID> path;
+    HashTable<std::string, std::string> keyVals;
+};
+
+#endif // EXTRACTION_WAY_H
diff --git a/Extractor/ExtractorCallbacks.cpp b/Extractor/ExtractorCallbacks.cpp
index c8b5fc1..5e27817 100644
--- a/Extractor/ExtractorCallbacks.cpp
+++ b/Extractor/ExtractorCallbacks.cpp
@@ -1,142 +1,171 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+*/
 
-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.
+#include "ExtractorCallbacks.h"
+#include "ExtractionContainers.h"
+#include "ExtractionWay.h"
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+#include "../DataStructures/Restriction.h"
+#include "../DataStructures/ImportNode.h"
+#include "../Util/SimpleLogger.h"
 
+#include <osrm/Coordinate.h>
 
-#include "ExtractorCallbacks.h"
-#include "ExtractionHelperFunctions.h"
+#include <limits>
+#include <string>
+#include <vector>
 
-ExtractorCallbacks::ExtractorCallbacks() {externalMemory = NULL; stringMap = NULL; }
-ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap) {
-    externalMemory = ext;
-    stringMap = strMap;
+ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers,
+                                       std::unordered_map<std::string, NodeID> &string_map)
+    : string_map(string_map), external_memory(extraction_containers)
+{
 }
 
-ExtractorCallbacks::~ExtractorCallbacks() { }
-
 /** warning: caller needs to take care of synchronization! */
-void ExtractorCallbacks::nodeFunction(const _Node &n) {
-    if(n.lat <= 85*100000 && n.lat >= -85*100000) {
-        externalMemory->allNodes.push_back(n);
+void ExtractorCallbacks::ProcessNode(const ExternalMemoryNode &n)
+{
+    if (n.lat <= 85 * COORDINATE_PRECISION && n.lat >= -85 * COORDINATE_PRECISION)
+    {
+        external_memory.all_nodes_list.push_back(n);
     }
 }
 
-bool ExtractorCallbacks::restrictionFunction(const _RawRestrictionContainer &r) {
-    externalMemory->restrictionsVector.push_back(r);
+bool ExtractorCallbacks::ProcessRestriction(const InputRestrictionContainer &restriction)
+{
+    external_memory.restrictions_list.push_back(restriction);
     return true;
 }
 
 /** warning: caller needs to take care of synchronization! */
-void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
-    if((0 < parsed_way.speed) || (0 < parsed_way.duration)) { //Only true if the way is specified by the speed profile
-        if(UINT_MAX == parsed_way.id){
-            DEBUG("found bogus way with id: " << parsed_way.id << " of size " << parsed_way.path.size());
-            return;
-        }
+void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way)
+{
+    if ((0 >= parsed_way.speed) && (0 >= parsed_way.duration))
+    { // Only true if the way is specified by the speed profile
+        return;
+    }
 
-        if(0 < parsed_way.duration) {
-         //TODO: iterate all way segments and set duration corresponding to the length of each segment
-            parsed_way.speed = parsed_way.duration/(parsed_way.path.size()-1);
-        }
+    if (parsed_way.path.size() <= 1)
+    { // safe-guard against broken data
+        return;
+    }
 
-        if(FLT_EPSILON >= fabs(-1. - parsed_way.speed)){
-            DEBUG("found way with bogus speed, id: " << parsed_way.id);
-            return;
-        }
+    if (std::numeric_limits<unsigned>::max() == parsed_way.id)
+    {
+        SimpleLogger().Write(logDEBUG) << "found bogus way with id: " << parsed_way.id
+                                       << " of size " << parsed_way.path.size();
+        return;
+    }
 
-        //Get the unique identifier for the street name
-        const StringMap::const_iterator string_map_iterator = stringMap->find(parsed_way.name);
-        if(stringMap->end() == string_map_iterator) {
-            parsed_way.nameID = externalMemory->nameVector.size();
-            externalMemory->nameVector.push_back(parsed_way.name);
-            stringMap->insert(std::make_pair(parsed_way.name, parsed_way.nameID));
-        } else {
-            parsed_way.nameID = string_map_iterator->second;
-        }
+    if (0 < parsed_way.duration)
+    {
+        // TODO: iterate all way segments and set duration corresponding to the length of each
+        // segment
+        parsed_way.speed = parsed_way.duration / (parsed_way.path.size() - 1);
+    }
 
-        if(ExtractionWay::opposite == parsed_way.direction) {
-            std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
-            parsed_way.direction = ExtractionWay::oneway;
-        }
+    if (std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.speed))
+    {
+        SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << parsed_way.id;
+        return;
+    }
 
-        const bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
-
-        for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
-            externalMemory->allEdges.push_back(
-                    InternalExtractorEdge(parsed_way.path[n],
-                            parsed_way.path[n+1],
-                            parsed_way.type,
-                            (split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
-                            parsed_way.speed,
-                            parsed_way.nameID,
-                            parsed_way.roundabout,
-                            parsed_way.ignoreInGrid,
-                            (0 < parsed_way.duration),
-                            parsed_way.isAccessRestricted
-                    )
-            );
-            externalMemory->usedNodeIDs.push_back(parsed_way.path[n]);
-        }
-        externalMemory->usedNodeIDs.push_back(parsed_way.path.back());
-
-        //The following information is needed to identify start and end segments of restrictions
-        externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
-
-        if(split_bidirectional_edge) { //Only true if the way should be split
-            std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
-            for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
-                externalMemory->allEdges.push_back(
-                        InternalExtractorEdge(parsed_way.path[n],
-                                parsed_way.path[n+1],
-                                parsed_way.type,
-                                ExtractionWay::oneway,
-                                parsed_way.backward_speed,
-                                parsed_way.nameID,
-                                parsed_way.roundabout,
-                                parsed_way.ignoreInGrid,
-                                (0 < parsed_way.duration),
-                                parsed_way.isAccessRestricted,
-                                (ExtractionWay::oneway == parsed_way.direction)
-                        )
-                );
-            }
-            externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
+    // Get the unique identifier for the street name
+    const auto &string_map_iterator = string_map.find(parsed_way.name);
+    if (string_map.end() == string_map_iterator)
+    {
+        parsed_way.nameID = external_memory.name_list.size();
+        external_memory.name_list.push_back(parsed_way.name);
+        string_map.insert(std::make_pair(parsed_way.name, parsed_way.nameID));
+    }
+    else
+    {
+        parsed_way.nameID = string_map_iterator->second;
+    }
+
+    if (ExtractionWay::opposite == parsed_way.direction)
+    {
+        std::reverse(parsed_way.path.begin(), parsed_way.path.end());
+        parsed_way.direction = ExtractionWay::oneway;
+    }
+
+    const bool split_edge =
+        (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
+
+    for (unsigned n = 0; n < (parsed_way.path.size() - 1); ++n)
+    {
+        external_memory.all_edges_list.push_back(InternalExtractorEdge(
+            parsed_way.path[n],
+            parsed_way.path[n + 1],
+            parsed_way.type,
+            (split_edge ? ExtractionWay::oneway : parsed_way.direction),
+            parsed_way.speed,
+            parsed_way.nameID,
+            parsed_way.roundabout,
+            parsed_way.ignoreInGrid,
+            (0 < parsed_way.duration),
+            parsed_way.isAccessRestricted,
+            false,
+            split_edge));
+        external_memory.used_node_id_list.push_back(parsed_way.path[n]);
+    }
+    external_memory.used_node_id_list.push_back(parsed_way.path.back());
+
+    // The following information is needed to identify start and end segments of restrictions
+    external_memory.way_start_end_id_list.push_back(
+        WayIDStartAndEndEdge(parsed_way.id,
+                             parsed_way.path[0],
+                             parsed_way.path[1],
+                             parsed_way.path[parsed_way.path.size() - 2],
+                             parsed_way.path.back()));
+
+    if (split_edge)
+    { // Only true if the way should be split
+        std::reverse(parsed_way.path.begin(), parsed_way.path.end());
+        for (std::vector<NodeID>::size_type n = 0; n < parsed_way.path.size() - 1; ++n)
+        {
+            external_memory.all_edges_list.push_back(
+                InternalExtractorEdge(parsed_way.path[n],
+                                      parsed_way.path[n + 1],
+                                      parsed_way.type,
+                                      ExtractionWay::oneway,
+                                      parsed_way.backward_speed,
+                                      parsed_way.nameID,
+                                      parsed_way.roundabout,
+                                      parsed_way.ignoreInGrid,
+                                      (0 < parsed_way.duration),
+                                      parsed_way.isAccessRestricted,
+                                      (ExtractionWay::oneway == parsed_way.direction),
+                                      split_edge));
         }
+        external_memory.way_start_end_id_list.push_back(
+            WayIDStartAndEndEdge(parsed_way.id,
+                                 parsed_way.path[0],
+                                 parsed_way.path[1],
+                                 parsed_way.path[parsed_way.path.size() - 2],
+                                 parsed_way.path.back()));
     }
 }
diff --git a/Extractor/ExtractorCallbacks.h b/Extractor/ExtractorCallbacks.h
index 4293d13..fcdb272 100644
--- a/Extractor/ExtractorCallbacks.h
+++ b/Extractor/ExtractorCallbacks.h
@@ -1,57 +1,63 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef EXTRACTORCALLBACKS_H_
-#define EXTRACTORCALLBACKS_H_
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <string>
-#include <vector>
-
-#include <cfloat>
+*/
 
-#include <boost/algorithm/string.hpp>
-#include <boost/algorithm/string/regex.hpp>
-#include <boost/regex.hpp>
+#ifndef EXTRACTOR_CALLBACKS_H
+#define EXTRACTOR_CALLBACKS_H
 
-#include "ExtractionContainers.h"
-#include "ExtractorStructs.h"
+#include "../typedefs.h"
 
-class ExtractorCallbacks{
-private:
-    StringMap * stringMap;
-    ExtractionContainers * externalMemory;
+#include <unordered_map>
+#include <string>
 
-    ExtractorCallbacks();
-public:
-    explicit ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap);
+struct ExternalMemoryNode;
+class ExtractionContainers;
+struct ExtractionWay;
+struct InputRestrictionContainer;
 
-    ~ExtractorCallbacks();
+class ExtractorCallbacks
+{
+  private:
+    std::unordered_map<std::string, NodeID> &string_map;
+    ExtractionContainers &external_memory;
 
-    /** warning: caller needs to take care of synchronization! */
-    void nodeFunction(const _Node &n);
+  public:
+    ExtractorCallbacks() = delete;
+    ExtractorCallbacks(const ExtractorCallbacks &) = delete;
+    explicit ExtractorCallbacks(ExtractionContainers &extraction_containers,
+                                std::unordered_map<std::string, NodeID> &string_map);
 
-    bool restrictionFunction(const _RawRestrictionContainer &r);
+    // warning: caller needs to take care of synchronization!
+    void ProcessNode(const ExternalMemoryNode &node);
 
-    /** warning: caller needs to take care of synchronization! */
-    void wayFunction(ExtractionWay &w);
+    // warning: caller needs to take care of synchronization!
+    bool ProcessRestriction(const InputRestrictionContainer &restriction);
 
+    // warning: caller needs to take care of synchronization!
+    void ProcessWay(ExtractionWay &way);
 };
 
-#endif /* EXTRACTORCALLBACKS_H_ */
+#endif /* EXTRACTOR_CALLBACKS_H */
diff --git a/Extractor/ExtractorStructs.h b/Extractor/ExtractorStructs.h
index fe21da9..51a74c3 100644
--- a/Extractor/ExtractorStructs.h
+++ b/Extractor/ExtractorStructs.h
@@ -1,222 +1,114 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef EXTRACTORSTRUCTS_H_
-#define EXTRACTORSTRUCTS_H_
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <climits>
-#include <string>
+*/
 
-#include <boost/algorithm/string.hpp>
-#include <boost/algorithm/string/regex.hpp>
-#include <boost/regex.hpp>
-#include <boost/unordered_map.hpp>
+#ifndef EXTRACTORSTRUCTS_H_
+#define EXTRACTORSTRUCTS_H_
 
-#include "../DataStructures/Coordinate.h"
 #include "../DataStructures/HashTable.h"
 #include "../DataStructures/ImportNode.h"
-#include "../DataStructures/NodeCoords.h"
-#include "../DataStructures/Restriction.h"
-#include "../DataStructures/TimingUtil.h"
 #include "../typedefs.h"
 
-typedef boost::unordered_map<std::string, NodeID > StringMap;
-typedef boost::unordered_map<std::string, std::pair<int, short> > StringToIntPairMap;
-
-struct ExtractionWay {
-    ExtractionWay() {
-		Clear();
-    }
-	
-	inline void Clear(){
-		id = UINT_MAX;
-		nameID = UINT_MAX;
-		path.clear();
-		keyVals.EraseAll();
-        direction = ExtractionWay::notSure;
-        speed = -1;
-        backward_speed = -1;
-        duration = -1;
-        type = -1;
-        access = true;
-        roundabout = false;
-        isAccessRestricted = false;
-        ignoreInGrid = false;
-    }
-
-    enum Directions {
-        notSure = 0, oneway, bidirectional, opposite
-    };
-    Directions direction;
-    unsigned id;
-    unsigned nameID;
-    std::string name;
-    double speed;
-    double backward_speed;
-    double duration;
-    short type;
-    bool access;
-    bool roundabout;
-    bool isAccessRestricted;
-    bool ignoreInGrid;
-    std::vector< NodeID > path;
-    HashTable<std::string, std::string> keyVals;
-};
+#include <limits>
+#include <string>
 
-struct ExtractorRelation {
-    ExtractorRelation() : type(unknown){}
-    enum {
-        unknown = 0, ferry, turnRestriction
-    } type;
+struct ExtractorRelation
+{
+    ExtractorRelation() : type(unknown) {}
+    enum
+    { unknown = 0,
+      ferry,
+      turnRestriction } type;
     HashTable<std::string, std::string> keyVals;
 };
 
-struct InternalExtractorEdge {
-    InternalExtractorEdge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) {};
-    InternalExtractorEdge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { }
-    InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { }
-    InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(false) {
-        assert(0 <= type);
-    }
-    InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar, bool icf): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(icf) {
-        assert(0 <= type);
-    }
-    NodeID start;
-    NodeID target;
-    short type;
-    short direction;
-    double speed;
-    unsigned nameID;
-    bool isRoundabout;
-    bool ignoreInGrid;
-    bool isDurationSet;
-    bool isAccessRestricted;
-    bool isContraFlow;
-
-    _Coordinate startCoord;
-    _Coordinate targetCoord;
-
-    static InternalExtractorEdge min_value() {
-        return InternalExtractorEdge(0,0);
-    }
-    static InternalExtractorEdge max_value() {
-        return InternalExtractorEdge((std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)());
-    }
-};
-
-
-
-struct _WayIDStartAndEndEdge {
+struct WayIDStartAndEndEdge
+{
     unsigned wayID;
     NodeID firstStart;
     NodeID firstTarget;
     NodeID lastStart;
     NodeID lastTarget;
-    _WayIDStartAndEndEdge() : wayID(UINT_MAX), firstStart(UINT_MAX), firstTarget(UINT_MAX), lastStart(UINT_MAX), lastTarget(UINT_MAX) {}
-    _WayIDStartAndEndEdge(unsigned w, NodeID fs, NodeID ft, NodeID ls, NodeID lt) :  wayID(w), firstStart(fs), firstTarget(ft), lastStart(ls), lastTarget(lt) {}
-
-    static _WayIDStartAndEndEdge min_value() {
-        return _WayIDStartAndEndEdge((std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)());
+    WayIDStartAndEndEdge()
+        : wayID(std::numeric_limits<unsigned>::max()), firstStart(std::numeric_limits<unsigned>::max()), firstTarget(std::numeric_limits<unsigned>::max()), lastStart(std::numeric_limits<unsigned>::max()),
+          lastTarget(std::numeric_limits<unsigned>::max())
+    {
     }
-    static _WayIDStartAndEndEdge max_value() {
-        return _WayIDStartAndEndEdge((std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)());
-    }
-};
 
-struct CmpWayByID : public std::binary_function<_WayIDStartAndEndEdge, _WayIDStartAndEndEdge, bool> {
-    typedef _WayIDStartAndEndEdge value_type;
-    bool operator ()  (const _WayIDStartAndEndEdge & a, const _WayIDStartAndEndEdge & b) const {
-        return a.wayID < b.wayID;
-    }
-    value_type max_value() {
-        return _WayIDStartAndEndEdge::max_value();
-    }
-    value_type min_value() {
-        return _WayIDStartAndEndEdge::min_value();
+    explicit WayIDStartAndEndEdge(unsigned w, NodeID fs, NodeID ft, NodeID ls, NodeID lt)
+        : wayID(w), firstStart(fs), firstTarget(ft), lastStart(ls), lastTarget(lt)
+    {
     }
-};
 
-struct Cmp : public std::binary_function<NodeID, NodeID, bool> {
-    typedef NodeID value_type;
-    bool operator ()  (const NodeID & a, const NodeID & b) const {
-        return a < b;
-    }
-    value_type max_value() {
-        return 0xffffffff;
+    static WayIDStartAndEndEdge min_value()
+    {
+        return WayIDStartAndEndEdge((std::numeric_limits<unsigned>::min)(),
+                                    (std::numeric_limits<unsigned>::min)(),
+                                    (std::numeric_limits<unsigned>::min)(),
+                                    (std::numeric_limits<unsigned>::min)(),
+                                    (std::numeric_limits<unsigned>::min)());
     }
-    value_type min_value() {
-        return 0x0;
+    static WayIDStartAndEndEdge max_value()
+    {
+        return WayIDStartAndEndEdge((std::numeric_limits<unsigned>::max)(),
+                                    (std::numeric_limits<unsigned>::max)(),
+                                    (std::numeric_limits<unsigned>::max)(),
+                                    (std::numeric_limits<unsigned>::max)(),
+                                    (std::numeric_limits<unsigned>::max)());
     }
 };
 
-struct CmpNodeByID : public std::binary_function<_Node, _Node, bool> {
-    typedef _Node value_type;
-    bool operator ()  (const _Node & a, const _Node & b) const {
-        return a.id < b.id;
-    }
-    value_type max_value()  {
-        return _Node::max_value();
-    }
-    value_type min_value() {
-        return _Node::min_value();
+struct CmpWayByID
+{
+    typedef WayIDStartAndEndEdge value_type;
+    bool operator()(const WayIDStartAndEndEdge &a, const WayIDStartAndEndEdge &b) const
+    {
+        return a.wayID < b.wayID;
     }
+    value_type max_value() { return WayIDStartAndEndEdge::max_value(); }
+    value_type min_value() { return WayIDStartAndEndEdge::min_value(); }
 };
 
-struct CmpEdgeByStartID : public std::binary_function<InternalExtractorEdge, InternalExtractorEdge, bool> {
-    typedef InternalExtractorEdge value_type;
-    bool operator ()  (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const {
-        return a.start < b.start;
-    }
-    value_type max_value() {
-        return InternalExtractorEdge::max_value();
-    }
-    value_type min_value() {
-        return InternalExtractorEdge::min_value();
-    }
+struct Cmp
+{
+    typedef NodeID value_type;
+    bool operator()(const NodeID left, const NodeID right) const { return left < right; }
+    value_type max_value() { return 0xffffffff; }
+    value_type min_value() { return 0x0; }
 };
 
-struct CmpEdgeByTargetID : public std::binary_function<InternalExtractorEdge, InternalExtractorEdge, bool> {
-    typedef InternalExtractorEdge value_type;
-    bool operator ()  (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const {
-        return a.target < b.target;
-    }
-    value_type max_value() {
-        return InternalExtractorEdge::max_value();
-    }
-    value_type min_value() {
-        return InternalExtractorEdge::min_value();
+struct CmpNodeByID
+{
+    typedef ExternalMemoryNode value_type;
+    bool operator()(const ExternalMemoryNode &left, const ExternalMemoryNode &right) const
+    {
+        return left.node_id < right.node_id;
     }
+    value_type max_value() { return ExternalMemoryNode::max_value(); }
+    value_type min_value() { return ExternalMemoryNode::min_value(); }
 };
 
-inline std::string GetRandomString() {
-    char s[128];
-    static const char alphanum[] =
-            "0123456789"
-            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-            "abcdefghijklmnopqrstuvwxyz";
-
-    for (int i = 0; i < 127; ++i) {
-        s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
-    }
-    s[127] = 0;
-    return std::string(s);
-}
-
 #endif /* EXTRACTORSTRUCTS_H_ */
diff --git a/Extractor/InternalExtractorEdge.h b/Extractor/InternalExtractorEdge.h
new file mode 100644
index 0000000..02903e8
--- /dev/null
+++ b/Extractor/InternalExtractorEdge.h
@@ -0,0 +1,120 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef INTERNAL_EXTRACTOR_EDGE_H
+#define INTERNAL_EXTRACTOR_EDGE_H
+
+#include "../typedefs.h"
+#include <osrm/Coordinate.h>
+
+#include <boost/assert.hpp>
+
+struct InternalExtractorEdge
+{
+    InternalExtractorEdge()
+        : start(0), target(0), type(0), direction(0), speed(0), name_id(0), is_roundabout(false),
+          is_in_tiny_cc(false), is_duration_set(false), is_access_restricted(false),
+          is_contra_flow(false), is_split(false)
+    {
+    }
+
+    explicit InternalExtractorEdge(NodeID start,
+                                   NodeID target,
+                                   short type,
+                                   short direction,
+                                   double speed,
+                                   unsigned name_id,
+                                   bool is_roundabout,
+                                   bool is_in_tiny_cc,
+                                   bool is_duration_set,
+                                   bool is_access_restricted,
+                                   bool is_contra_flow,
+                                   bool is_split)
+        : start(start), target(target), type(type), direction(direction), speed(speed),
+          name_id(name_id), is_roundabout(is_roundabout), is_in_tiny_cc(is_in_tiny_cc),
+          is_duration_set(is_duration_set), is_access_restricted(is_access_restricted),
+          is_contra_flow(is_contra_flow), is_split(is_split)
+    {
+        BOOST_ASSERT(0 <= type);
+    }
+
+    // necessary static util functions for stxxl's sorting
+    static InternalExtractorEdge min_value()
+    {
+        return InternalExtractorEdge(0, 0, 0, 0, 0, 0, false, false, false, false, false, false);
+    }
+    static InternalExtractorEdge max_value()
+    {
+        return InternalExtractorEdge(
+            SPECIAL_NODEID, SPECIAL_NODEID, 0, 0, 0, 0, false, false, false, false, false, false);
+    }
+
+    NodeID start;
+    NodeID target;
+    short type;
+    short direction;
+    double speed;
+    unsigned name_id;
+    bool is_roundabout;
+    bool is_in_tiny_cc;
+    bool is_duration_set;
+    bool is_access_restricted;
+    bool is_contra_flow;
+    bool is_split;
+
+    FixedPointCoordinate source_coordinate;
+    FixedPointCoordinate target_coordinate;
+};
+
+struct CmpEdgeByStartID
+{
+    typedef InternalExtractorEdge value_type;
+    bool operator()(const InternalExtractorEdge &a, const InternalExtractorEdge &b) const
+    {
+        return a.start < b.start;
+    }
+
+    value_type max_value() { return InternalExtractorEdge::max_value(); }
+
+    value_type min_value() { return InternalExtractorEdge::min_value(); }
+};
+
+struct CmpEdgeByTargetID
+{
+    typedef InternalExtractorEdge value_type;
+
+    bool operator()(const InternalExtractorEdge &a, const InternalExtractorEdge &b) const
+    {
+        return a.target < b.target;
+    }
+
+    value_type max_value() { return InternalExtractorEdge::max_value(); }
+
+    value_type min_value() { return InternalExtractorEdge::min_value(); }
+};
+
+#endif // INTERNAL_EXTRACTOR_EDGE_H
diff --git a/Extractor/PBFParser.cpp b/Extractor/PBFParser.cpp
index 51b099f..1abc480 100644
--- a/Extractor/PBFParser.cpp
+++ b/Extractor/PBFParser.cpp
@@ -1,482 +1,664 @@
 /*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
 
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
- 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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#include "PBFParser.h"
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-PBFParser::PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser( ec, se ) {
-	GOOGLE_PROTOBUF_VERIFY_VERSION;
-	//TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
-	//NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
-	threadDataQueue = boost::make_shared<ConcurrentQueue<_ThreadData*> >( 2500 ); /* Max 2500 items in queue, hardcoded. */
-	input.open(fileName, std::ios::in | std::ios::binary);
+*/
 
-	if (!input) {
-		std::cerr << fileName << ": File not found." << std::endl;
-	}
+#include "PBFParser.h"
 
-#ifndef NDEBUG
-	blockCount = 0;
-	groupCount = 0;
-#endif
+#include "ExtractionWay.h"
+#include "ExtractorCallbacks.h"
+#include "ScriptingEnvironment.h"
+
+#include "../DataStructures/HashTable.h"
+#include "../DataStructures/ImportNode.h"
+#include "../DataStructures/Restriction.h"
+#include "../Util/MachineInfo.h"
+#include "../Util/OSRMException.h"
+#include "../Util/SimpleLogger.h"
+#include "../typedefs.h"
+
+#include <boost/assert.hpp>
+
+#include <tbb/parallel_for.h>
+#include <tbb/task_scheduler_init.h>
+
+#include <osrm/Coordinate.h>
+
+#include <zlib.h>
+
+#include <functional>
+#include <limits>
+#include <thread>
+
+PBFParser::PBFParser(const char *fileName,
+                     ExtractorCallbacks *extractor_callbacks,
+                     ScriptingEnvironment &scripting_environment,
+                     unsigned num_threads)
+    : BaseParser(extractor_callbacks, scripting_environment)
+{
+    if (0 == num_threads)
+    {
+        num_parser_threads = tbb::task_scheduler_init::default_num_threads();
+    }
+    else
+    {
+        num_parser_threads = num_threads;
+    }
+
+    GOOGLE_PROTOBUF_VERIFY_VERSION;
+    // TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
+    // NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
+
+    // Max 2500 items in queue, hardcoded.
+    thread_data_queue = std::make_shared<ConcurrentQueue<ParserThreadData *>>(2500);
+    input.open(fileName, std::ios::in | std::ios::binary);
+
+    if (!input)
+    {
+        throw OSRMException("pbf file not found.");
+    }
+
+    block_count = 0;
+    group_count = 0;
 }
 
-PBFParser::~PBFParser() {
-	if(input.is_open()) {
-		input.close();
-	}
-
-	// Clean up any leftover ThreadData objects in the queue
-	_ThreadData* td;
-	while (threadDataQueue->try_pop(td)) {
-		delete td;
-	}
-	google::protobuf::ShutdownProtobufLibrary();
-
-#ifndef NDEBUG
-	DEBUG("parsed " << blockCount << " blocks from pbf with " << groupCount << " groups");
-#endif
+PBFParser::~PBFParser()
+{
+    if (input.is_open())
+    {
+        input.close();
+    }
+
+    // Clean up any leftover ThreadData objects in the queue
+    ParserThreadData *thread_data;
+    while (thread_data_queue->try_pop(thread_data))
+    {
+        delete thread_data;
+    }
+    google::protobuf::ShutdownProtobufLibrary();
+
+    SimpleLogger().Write(logDEBUG) << "parsed " << block_count << " blocks from pbf with "
+                                   << group_count << " groups";
 }
 
-inline bool PBFParser::ReadHeader() {
-	_ThreadData initData;
-	/** read Header */
-	if(!readPBFBlobHeader(input, &initData)) {
-		return false;
-	}
-
-	if(readBlob(input, &initData)) {
-		if(!initData.PBFHeaderBlock.ParseFromArray(&(initData.charBuffer[0]), initData.charBuffer.size() ) ) {
-			std::cerr << "[error] Header not parseable!" << std::endl;
-			return false;
-		}
-
-		for(int i = 0, featureSize = initData.PBFHeaderBlock.required_features_size(); i < featureSize; ++i) {
-			const std::string& feature = initData.PBFHeaderBlock.required_features( i );
-			bool supported = false;
-			if ( "OsmSchema-V0.6" == feature ) {
-				supported = true;
-			}
-			else if ( "DenseNodes" == feature ) {
-				supported = true;
-			}
-
-			if ( !supported ) {
-				std::cerr << "[error] required feature not supported: " << feature.data() << std::endl;
-				return false;
-			}
-		}
-	} else {
-		std::cerr << "[error] blob not loaded!" << std::endl;
-	}
-	return true;
+inline bool PBFParser::ReadHeader()
+{
+    ParserThreadData init_data;
+    /** read Header */
+    if (!readPBFBlobHeader(input, &init_data))
+    {
+        return false;
+    }
+
+    if (readBlob(input, &init_data))
+    {
+        if (!init_data.PBFHeaderBlock.ParseFromArray(&(init_data.charBuffer[0]),
+                                                     static_cast<int>(init_data.charBuffer.size())))
+        {
+            std::cerr << "[error] Header not parseable!" << std::endl;
+            return false;
+        }
+
+        const auto feature_size = init_data.PBFHeaderBlock.required_features_size();
+        for (int i = 0; i < feature_size; ++i)
+        {
+            const std::string &feature = init_data.PBFHeaderBlock.required_features(i);
+            bool supported = false;
+            if ("OsmSchema-V0.6" == feature)
+            {
+                supported = true;
+            }
+            else if ("DenseNodes" == feature)
+            {
+                supported = true;
+            }
+
+            if (!supported)
+            {
+                std::cerr << "[error] required feature not supported: " << feature.data()
+                          << std::endl;
+                return false;
+            }
+        }
+    }
+    else
+    {
+        std::cerr << "[error] blob not loaded!" << std::endl;
+    }
+    return true;
 }
 
-inline void PBFParser::ReadData() {
-	bool keepRunning = true;
-	do {
-		_ThreadData *threadData = new _ThreadData();
-		keepRunning = readNextBlock(input, threadData);
-
-		if (keepRunning) {
-			threadDataQueue->push(threadData);
-		} else {
-			threadDataQueue->push(NULL); // No more data to read, parse stops when NULL encountered
-			delete threadData;
-		}
-	} while(keepRunning);
+inline void PBFParser::ReadData()
+{
+    bool keep_running = true;
+    do
+    {
+        ParserThreadData *thread_data = new ParserThreadData();
+        keep_running = readNextBlock(input, thread_data);
+
+        if (keep_running)
+        {
+            thread_data_queue->push(thread_data);
+        }
+        else
+        {
+            // No more data to read, parse stops when nullptr encountered
+            thread_data_queue->push(nullptr);
+            delete thread_data;
+        }
+    } while (keep_running);
 }
 
-inline void PBFParser::ParseData() {
-	while (true) {
-		_ThreadData *threadData;
-		threadDataQueue->wait_and_pop(threadData);
-		if( NULL==threadData ) {
-			INFO("Parse Data Thread Finished");
-			threadDataQueue->push(NULL); // Signal end of data for other threads
-			break;
-		}
-
-		loadBlock(threadData);
-
-		for(int i = 0, groupSize = threadData->PBFprimitiveBlock.primitivegroup_size(); i < groupSize; ++i) {
-			threadData->currentGroupID = i;
-			loadGroup(threadData);
-
-			if(threadData->entityTypeIndicator == TypeNode) {
-				parseNode(threadData);
-			}
-			if(threadData->entityTypeIndicator == TypeWay) {
-				parseWay(threadData);
-			}
-			if(threadData->entityTypeIndicator == TypeRelation) {
-				parseRelation(threadData);
-			}
-			if(threadData->entityTypeIndicator == TypeDenseNode) {
-				parseDenseNode(threadData);
-			}
-		}
-
-		delete threadData;
-		threadData = NULL;
-	}
+inline void PBFParser::ParseData()
+{
+    tbb::task_scheduler_init init(num_parser_threads);
+
+    while (true)
+    {
+        ParserThreadData *thread_data;
+        thread_data_queue->wait_and_pop(thread_data);
+        if (nullptr == thread_data)
+        {
+            thread_data_queue->push(nullptr); // Signal end of data for other threads
+            break;
+        }
+
+        loadBlock(thread_data);
+
+        int group_size = thread_data->PBFprimitiveBlock.primitivegroup_size();
+        for (int i = 0; i < group_size; ++i)
+        {
+            thread_data->currentGroupID = i;
+            loadGroup(thread_data);
+
+            if (thread_data->entityTypeIndicator == TypeNode)
+            {
+                parseNode(thread_data);
+            }
+            if (thread_data->entityTypeIndicator == TypeWay)
+            {
+                parseWay(thread_data);
+            }
+            if (thread_data->entityTypeIndicator == TypeRelation)
+            {
+                parseRelation(thread_data);
+            }
+            if (thread_data->entityTypeIndicator == TypeDenseNode)
+            {
+                parseDenseNode(thread_data);
+            }
+        }
+
+        delete thread_data;
+        thread_data = nullptr;
+    }
 }
 
-inline bool PBFParser::Parse() {
-	// Start the read and parse threads
-	boost::thread readThread(boost::bind(&PBFParser::ReadData, this));
+inline bool PBFParser::Parse()
+{
+    // Start the read and parse threads
+    std::thread read_thread(std::bind(&PBFParser::ReadData, this));
 
-	//Open several parse threads that are synchronized before call to
-	boost::thread parseThread(boost::bind(&PBFParser::ParseData, this));
+    // Open several parse threads that are synchronized before call to
+    std::thread parse_thread(std::bind(&PBFParser::ParseData, this));
 
-	// Wait for the threads to finish
-	readThread.join();
-	parseThread.join();
+    // Wait for the threads to finish
+    read_thread.join();
+    parse_thread.join();
 
-	return true;
+    return true;
 }
 
-inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
-	const OSMPBF::DenseNodes& dense = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).dense();
-	int denseTagIndex = 0;
-	int64_t m_lastDenseID = 0;
-	int64_t m_lastDenseLatitude = 0;
-	int64_t m_lastDenseLongitude = 0;
-
-	const int number_of_nodes = dense.id_size();
-	std::vector<ImportNode> extracted_nodes_vector(number_of_nodes);
-	for(int i = 0; i < number_of_nodes; ++i) {
-		m_lastDenseID += dense.id( i );
-		m_lastDenseLatitude += dense.lat( i );
-		m_lastDenseLongitude += dense.lon( i );
-		extracted_nodes_vector[i].id = m_lastDenseID;
-		extracted_nodes_vector[i].lat = 100000*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lat_offset() ) / NANO;
-		extracted_nodes_vector[i].lon = 100000*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO;
-		while (denseTagIndex < dense.keys_vals_size()) {
-			const int tagValue = dense.keys_vals( denseTagIndex );
-			if( 0==tagValue ) {
-				++denseTagIndex;
-				break;
-			}
-			const int keyValue = dense.keys_vals ( denseTagIndex+1 );
-			const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue).data();
-			const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue).data();
-			extracted_nodes_vector[i].keyVals.Add(key, value);
-			denseTagIndex += 2;
-		}
-	}
-
-#pragma omp parallel for schedule ( guided )
-	for(int i = 0; i < number_of_nodes; ++i) {
-	    ImportNode &n = extracted_nodes_vector[i];
-	    ParseNodeInLua( n, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) );
-	}
-
-	BOOST_FOREACH(ImportNode &n, extracted_nodes_vector) {
-	    extractor_callbacks->nodeFunction(n);
-	}
+inline void PBFParser::parseDenseNode(ParserThreadData *thread_data)
+{
+    const OSMPBF::DenseNodes &dense =
+        thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).dense();
+    int denseTagIndex = 0;
+    int64_t m_lastDenseID = 0;
+    int64_t m_lastDenseLatitude = 0;
+    int64_t m_lastDenseLongitude = 0;
+
+    const int number_of_nodes = dense.id_size();
+    std::vector<ImportNode> extracted_nodes_vector(number_of_nodes);
+    for (int i = 0; i < number_of_nodes; ++i)
+    {
+        m_lastDenseID += dense.id(i);
+        m_lastDenseLatitude += dense.lat(i);
+        m_lastDenseLongitude += dense.lon(i);
+        extracted_nodes_vector[i].node_id = static_cast<NodeID>(m_lastDenseID);
+        extracted_nodes_vector[i].lat = static_cast<int>(
+            COORDINATE_PRECISION *
+            ((double)m_lastDenseLatitude * thread_data->PBFprimitiveBlock.granularity() +
+             thread_data->PBFprimitiveBlock.lat_offset()) /
+            NANO);
+        extracted_nodes_vector[i].lon = static_cast<int>(
+            COORDINATE_PRECISION *
+            ((double)m_lastDenseLongitude * thread_data->PBFprimitiveBlock.granularity() +
+             thread_data->PBFprimitiveBlock.lon_offset()) /
+            NANO);
+        while (denseTagIndex < dense.keys_vals_size())
+        {
+            const int tagValue = dense.keys_vals(denseTagIndex);
+            if (0 == tagValue)
+            {
+                ++denseTagIndex;
+                break;
+            }
+            const int keyValue = dense.keys_vals(denseTagIndex + 1);
+            const std::string &key = thread_data->PBFprimitiveBlock.stringtable().s(tagValue);
+            const std::string &value = thread_data->PBFprimitiveBlock.stringtable().s(keyValue);
+            extracted_nodes_vector[i].keyVals.Add(std::move(key), std::move(value));
+            denseTagIndex += 2;
+        }
+    }
+
+    tbb::parallel_for(tbb::blocked_range<size_t>(0, extracted_nodes_vector.size()),
+                      [this, &extracted_nodes_vector](const tbb::blocked_range<size_t> &range)
+                      {
+        lua_State *lua_state = this->scripting_environment.getLuaState();
+        for (size_t i = range.begin(); i != range.end(); ++i)
+        {
+            ImportNode &import_node = extracted_nodes_vector[i];
+            ParseNodeInLua(import_node, lua_state);
+        }
+    });
+
+    for (const ImportNode &import_node : extracted_nodes_vector)
+    {
+        extractor_callbacks->ProcessNode(import_node);
+    }
 }
 
-inline void PBFParser::parseNode(_ThreadData * ) {
-	ERR("Parsing of simple nodes not supported. PBF should use dense nodes");
+inline void PBFParser::parseNode(ParserThreadData *)
+{
+    throw OSRMException("Parsing of simple nodes not supported. PBF should use dense nodes");
 }
 
-inline void PBFParser::parseRelation(_ThreadData * threadData) {
-	//TODO: leave early, if relation is not a restriction
-	//TODO: reuse rawRestriction container
-	if( !use_turn_restrictions ) {
-		return;
-	}
-	const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
-	for(int i = 0; i < group.relations_size(); ++i ) {
-		std::string except_tag_string;
-		const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i);
-		bool isRestriction = false;
-		bool isOnlyRestriction = false;
-		for(int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k) {
-			const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k));
-			const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k));
-			if ("type" == key) {
-				if( "restriction" == val) {
-					isRestriction = true;
-				} else {
-					break;
-				}
-			}
-			if ("restriction" == key) {
-				if(val.find("only_") == 0) {
-					isOnlyRestriction = true;
-				}
-			}
-			if ("except" == key) {
-				except_tag_string = val;
-			}
-		}
-
-		if( isRestriction && ShouldIgnoreRestriction(except_tag_string) ) {
-			continue;
-		}
-
-		if(isRestriction) {
-			int64_t lastRef = 0;
-			_RawRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
-			for(int rolesIndex = 0; rolesIndex < inputRelation.roles_sid_size(); ++rolesIndex) {
-				std::string role(threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) ).data());
-				lastRef += inputRelation.memids(rolesIndex);
-
-				if(!("from" == role || "to" == role || "via" == role)) {
-					continue;
-				}
-
-				switch(inputRelation.types(rolesIndex)) {
-				case 0: //node
-					if("from" == role || "to" == role) { //Only via should be a node
-						continue;
-					}
-					assert("via" == role);
-					if(UINT_MAX != currentRestrictionContainer.viaNode) {
-						currentRestrictionContainer.viaNode = UINT_MAX;
-					}
-					assert(UINT_MAX == currentRestrictionContainer.viaNode);
-					currentRestrictionContainer.restriction.viaNode = lastRef;
-					break;
-				case 1: //way
-					assert("from" == role || "to" == role || "via" == role);
-					if("from" == role) {
-						currentRestrictionContainer.fromWay = lastRef;
-					}
-					if ("to" == role) {
-						currentRestrictionContainer.toWay = lastRef;
-					}
-					if ("via" == role) {
-						assert(currentRestrictionContainer.restriction.toNode == UINT_MAX);
-						currentRestrictionContainer.viaNode = lastRef;
-					}
-					break;
-				case 2: //relation, not used. relations relating to relations are evil.
-					continue;
-					assert(false);
-					break;
-
-				default: //should not happen
-					//cout << "unknown";
-					assert(false);
-					break;
-				}
-			}
-			if(!extractor_callbacks->restrictionFunction(currentRestrictionContainer)) {
-				std::cerr << "[PBFParser] relation not parsed" << std::endl;
-			}
-		}
-	}
+inline void PBFParser::parseRelation(ParserThreadData *thread_data)
+{
+    // TODO: leave early, if relation is not a restriction
+    // TODO: reuse rawRestriction container
+    if (!use_turn_restrictions)
+    {
+        return;
+    }
+    const OSMPBF::PrimitiveGroup &group =
+        thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID);
+
+    for (int i = 0, relation_size = group.relations_size(); i < relation_size; ++i)
+    {
+        std::string except_tag_string;
+        const OSMPBF::Relation &inputRelation =
+            thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).relations(i);
+        bool is_restriction = false;
+        bool is_only_restriction = false;
+        for (int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k)
+        {
+            const std::string &key =
+                thread_data->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k));
+            const std::string &val =
+                thread_data->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k));
+            if ("type" == key)
+            {
+                if ("restriction" == val)
+                {
+                    is_restriction = true;
+                }
+                else
+                {
+                    break;
+                }
+            }
+            if (("restriction" == key) && (val.find("only_") == 0))
+            {
+                is_only_restriction = true;
+            }
+            if ("except" == key)
+            {
+                except_tag_string = val;
+            }
+        }
+
+        if (is_restriction && ShouldIgnoreRestriction(except_tag_string))
+        {
+            continue;
+        }
+
+        if (is_restriction)
+        {
+            int64_t last_ref = 0;
+            InputRestrictionContainer current_restriction_container(is_only_restriction);
+            for (int rolesIndex = 0, last_role = inputRelation.roles_sid_size();
+                 rolesIndex < last_role;
+                 ++rolesIndex)
+            {
+                const std::string &role = thread_data->PBFprimitiveBlock.stringtable().s(
+                    inputRelation.roles_sid(rolesIndex));
+                last_ref += inputRelation.memids(rolesIndex);
+
+                if (!("from" == role || "to" == role || "via" == role))
+                {
+                    continue;
+                }
+
+                switch (inputRelation.types(rolesIndex))
+                {
+                case 0: // node
+                    if ("from" == role || "to" == role)
+                    { // Only via should be a node
+                        continue;
+                    }
+                    BOOST_ASSERT("via" == role);
+                    if (std::numeric_limits<unsigned>::max() !=
+                        current_restriction_container.viaNode)
+                    {
+                        current_restriction_container.viaNode =
+                            std::numeric_limits<unsigned>::max();
+                    }
+                    BOOST_ASSERT(std::numeric_limits<unsigned>::max() ==
+                                 current_restriction_container.viaNode);
+                    current_restriction_container.restriction.viaNode =
+                        static_cast<NodeID>(last_ref);
+                    break;
+                case 1: // way
+                    BOOST_ASSERT("from" == role || "to" == role || "via" == role);
+                    if ("from" == role)
+                    {
+                        current_restriction_container.fromWay = static_cast<EdgeID>(last_ref);
+                    }
+                    if ("to" == role)
+                    {
+                        current_restriction_container.toWay = static_cast<EdgeID>(last_ref);
+                    }
+                    if ("via" == role)
+                    {
+                        BOOST_ASSERT(current_restriction_container.restriction.toNode ==
+                                     std::numeric_limits<unsigned>::max());
+                        current_restriction_container.viaNode = static_cast<NodeID>(last_ref);
+                    }
+                    break;
+                case 2: // relation, not used. relations relating to relations are evil.
+                    continue;
+                    BOOST_ASSERT(false);
+                    break;
+
+                default: // should not happen
+                    BOOST_ASSERT(false);
+                    break;
+                }
+            }
+            if (!extractor_callbacks->ProcessRestriction(current_restriction_container))
+            {
+                std::cerr << "[PBFParser] relation not parsed" << std::endl;
+            }
+        }
+    }
 }
 
-inline void PBFParser::parseWay(_ThreadData * threadData) {
-	const int number_of_ways = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size();
-	std::vector<ExtractionWay> parsed_way_vector(number_of_ways);
-	for(int i = 0; i < number_of_ways; ++i) {
-		const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i );
-		parsed_way_vector[i].id = inputWay.id();
-		unsigned pathNode(0);
-		const int number_of_referenced_nodes = inputWay.refs_size();
-		for(int j = 0; j < number_of_referenced_nodes; ++j) {
-			pathNode += inputWay.refs(j);
-			parsed_way_vector[i].path.push_back(pathNode);
-		}
-		assert(inputWay.keys_size() == inputWay.vals_size());
-		const int number_of_keys = inputWay.keys_size();
-		for(int j = 0; j < number_of_keys; ++j) {
-			const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(j));
-			const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(j));
-			parsed_way_vector[i].keyVals.Add(key, val);
-		}
-	}
-
-#pragma omp parallel for schedule ( guided )
-	for(int i = 0; i < number_of_ways; ++i) {
-	    ExtractionWay & w = parsed_way_vector[i];
-	    ParseWayInLua( w, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) );
-	}
-
-	BOOST_FOREACH(ExtractionWay & w, parsed_way_vector) {
-	    extractor_callbacks->wayFunction(w);
-	}
+inline void PBFParser::parseWay(ParserThreadData *thread_data)
+{
+    const int number_of_ways =
+        thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).ways_size();
+    std::vector<ExtractionWay> parsed_way_vector(number_of_ways);
+    for (int i = 0; i < number_of_ways; ++i)
+    {
+        const OSMPBF::Way &input_way =
+            thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).ways(i);
+        parsed_way_vector[i].id = static_cast<EdgeID>(input_way.id());
+        unsigned node_id_in_path = 0;
+        const auto number_of_referenced_nodes = input_way.refs_size();
+        for (auto j = 0; j < number_of_referenced_nodes; ++j)
+        {
+            node_id_in_path += static_cast<NodeID>(input_way.refs(j));
+            parsed_way_vector[i].path.push_back(node_id_in_path);
+        }
+        BOOST_ASSERT(input_way.keys_size() == input_way.vals_size());
+        const auto number_of_keys = input_way.keys_size();
+        for (auto j = 0; j < number_of_keys; ++j)
+        {
+            const std::string &key =
+                thread_data->PBFprimitiveBlock.stringtable().s(input_way.keys(j));
+            const std::string &val =
+                thread_data->PBFprimitiveBlock.stringtable().s(input_way.vals(j));
+            parsed_way_vector[i].keyVals.Add(std::move(key), std::move(val));
+        }
+    }
+
+    // TODO: investigate if schedule guided will be handled by tbb automatically
+    tbb::parallel_for(tbb::blocked_range<size_t>(0, parsed_way_vector.size()),
+                      [this, &parsed_way_vector](const tbb::blocked_range<size_t> &range)
+                      {
+        lua_State *lua_state = this->scripting_environment.getLuaState();
+        for (size_t i = range.begin(); i != range.end(); i++)
+        {
+            ExtractionWay &extraction_way = parsed_way_vector[i];
+            if (2 <= extraction_way.path.size())
+            {
+                ParseWayInLua(extraction_way, lua_state);
+            }
+        }
+    });
+
+    for (ExtractionWay &extraction_way : parsed_way_vector)
+    {
+        if (2 <= extraction_way.path.size())
+        {
+            extractor_callbacks->ProcessWay(extraction_way);
+        }
+    }
 }
 
-inline void PBFParser::loadGroup(_ThreadData * threadData) {
+inline void PBFParser::loadGroup(ParserThreadData *thread_data)
+{
 #ifndef NDEBUG
-	++groupCount;
+    ++group_count;
 #endif
 
-	const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
-	threadData->entityTypeIndicator = 0;
-	if ( group.nodes_size() != 0 ) {
-		threadData->entityTypeIndicator = TypeNode;
-	}
-	if ( group.ways_size() != 0 ) {
-		threadData->entityTypeIndicator = TypeWay;
-	}
-	if ( group.relations_size() != 0 ) {
-		threadData->entityTypeIndicator = TypeRelation;
-	}
-	if ( group.has_dense() )  {
-		threadData->entityTypeIndicator = TypeDenseNode;
-		assert( group.dense().id_size() != 0 );
-	}
-	assert( threadData->entityTypeIndicator != 0 );
+    const OSMPBF::PrimitiveGroup &group =
+        thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID);
+    thread_data->entityTypeIndicator = TypeDummy;
+    if (0 != group.nodes_size())
+    {
+        thread_data->entityTypeIndicator = TypeNode;
+    }
+    if (0 != group.ways_size())
+    {
+        thread_data->entityTypeIndicator = TypeWay;
+    }
+    if (0 != group.relations_size())
+    {
+        thread_data->entityTypeIndicator = TypeRelation;
+    }
+    if (group.has_dense())
+    {
+        thread_data->entityTypeIndicator = TypeDenseNode;
+        BOOST_ASSERT(0 != group.dense().id_size());
+    }
+    BOOST_ASSERT(thread_data->entityTypeIndicator != TypeDummy);
 }
 
-inline void PBFParser::loadBlock(_ThreadData * threadData) {
-#ifndef NDEBUG
-	++blockCount;
-#endif
-	threadData->currentGroupID = 0;
-	threadData->currentEntityID = 0;
-}
-
-inline bool PBFParser::readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData) {
-	int size(0);
-	stream.read((char *)&size, sizeof(int));
-	size = swapEndian(size);
-	if(stream.eof()) {
-		return false;
-	}
-	if ( size > MAX_BLOB_HEADER_SIZE || size < 0 ) {
-		return false;
-	}
-	char *data = new char[size];
-	stream.read(data, size*sizeof(data[0]));
-
-	bool dataSuccessfullyParsed = (threadData->PBFBlobHeader).ParseFromArray( data, size);
-	delete[] data;
-	return dataSuccessfullyParsed;
+inline void PBFParser::loadBlock(ParserThreadData *thread_data)
+{
+    ++block_count;
+    thread_data->currentGroupID = 0;
+    thread_data->currentEntityID = 0;
 }
 
-inline bool PBFParser::unpackZLIB(std::fstream &, _ThreadData * threadData) {
-	unsigned rawSize = threadData->PBFBlob.raw_size();
-	char* unpackedDataArray = new char[rawSize];
-	z_stream compressedDataStream;
-	compressedDataStream.next_in = ( unsigned char* ) threadData->PBFBlob.zlib_data().data();
-	compressedDataStream.avail_in = threadData->PBFBlob.zlib_data().size();
-	compressedDataStream.next_out = ( unsigned char* ) unpackedDataArray;
-	compressedDataStream.avail_out = rawSize;
-	compressedDataStream.zalloc = Z_NULL;
-	compressedDataStream.zfree = Z_NULL;
-	compressedDataStream.opaque = Z_NULL;
-	int ret = inflateInit( &compressedDataStream );
-	if ( ret != Z_OK ) {
-		std::cerr << "[error] failed to init zlib stream" << std::endl;
-		delete[] unpackedDataArray;
-		return false;
-	}
-
-	ret = inflate( &compressedDataStream, Z_FINISH );
-	if ( ret != Z_STREAM_END ) {
-		std::cerr << "[error] failed to inflate zlib stream" << std::endl;
-		std::cerr << "[error] Error type: " << ret << std::endl;
-		delete[] unpackedDataArray;
-		return false;
-	}
-
-	ret = inflateEnd( &compressedDataStream );
-	if ( ret != Z_OK ) {
-		std::cerr << "[error] failed to deinit zlib stream" << std::endl;
-		delete[] unpackedDataArray;
-		return false;
-	}
-
-	threadData->charBuffer.clear(); threadData->charBuffer.resize(rawSize);
-	std::copy(unpackedDataArray, unpackedDataArray + rawSize, threadData->charBuffer.begin());
-	delete[] unpackedDataArray;
-	return true;
+inline bool PBFParser::readPBFBlobHeader(std::fstream &stream, ParserThreadData *thread_data)
+{
+    int size(0);
+    stream.read((char *)&size, sizeof(int));
+    size = SwapEndian(size);
+    if (stream.eof())
+    {
+        return false;
+    }
+    if (size > MAX_BLOB_HEADER_SIZE || size < 0)
+    {
+        return false;
+    }
+    char *data = new char[size];
+    stream.read(data, size * sizeof(data[0]));
+
+    bool dataSuccessfullyParsed = (thread_data->PBFBlobHeader).ParseFromArray(data, size);
+    delete[] data;
+    return dataSuccessfullyParsed;
 }
 
-inline bool PBFParser::unpackLZMA(std::fstream &, _ThreadData * ) {
-	return false;
+inline bool PBFParser::unpackZLIB(ParserThreadData *thread_data)
+{
+    auto raw_size = thread_data->PBFBlob.raw_size();
+    char *unpacked_data_array = new char[raw_size];
+    z_stream compressed_data_stream;
+    compressed_data_stream.next_in = (unsigned char *)thread_data->PBFBlob.zlib_data().data();
+    compressed_data_stream.avail_in = thread_data->PBFBlob.zlib_data().size();
+    compressed_data_stream.next_out = (unsigned char *)unpacked_data_array;
+    compressed_data_stream.avail_out = raw_size;
+    compressed_data_stream.zalloc = Z_NULL;
+    compressed_data_stream.zfree = Z_NULL;
+    compressed_data_stream.opaque = Z_NULL;
+    int return_code = inflateInit(&compressed_data_stream);
+    if (return_code != Z_OK)
+    {
+        std::cerr << "[error] failed to init zlib stream" << std::endl;
+        delete[] unpacked_data_array;
+        return false;
+    }
+
+    return_code = inflate(&compressed_data_stream, Z_FINISH);
+    if (return_code != Z_STREAM_END)
+    {
+        std::cerr << "[error] failed to inflate zlib stream" << std::endl;
+        std::cerr << "[error] Error type: " << return_code << std::endl;
+        delete[] unpacked_data_array;
+        return false;
+    }
+
+    return_code = inflateEnd(&compressed_data_stream);
+    if (return_code != Z_OK)
+    {
+        std::cerr << "[error] failed to deinit zlib stream" << std::endl;
+        delete[] unpacked_data_array;
+        return false;
+    }
+
+    thread_data->charBuffer.clear();
+    thread_data->charBuffer.resize(raw_size);
+    std::copy(unpacked_data_array, unpacked_data_array + raw_size, thread_data->charBuffer.begin());
+    delete[] unpacked_data_array;
+    return true;
 }
 
-inline bool PBFParser::readBlob(std::fstream& stream, _ThreadData * threadData) {
-	if(stream.eof()) {
-		return false;
-	}
-
-	const int size = threadData->PBFBlobHeader.datasize();
-	if ( size < 0 || size > MAX_BLOB_SIZE ) {
-		std::cerr << "[error] invalid Blob size:" << size << std::endl;
-		return false;
-	}
-
-	char* data = new char[size];
-	stream.read(data, sizeof(data[0])*size);
-
-	if ( !threadData->PBFBlob.ParseFromArray( data, size ) ) {
-		std::cerr << "[error] failed to parse blob" << std::endl;
-		delete[] data;
-		return false;
-	}
-
-	if ( threadData->PBFBlob.has_raw() ) {
-		const std::string& data = threadData->PBFBlob.raw();
-		threadData->charBuffer.clear();
-		threadData->charBuffer.resize( data.size() );
-		std::copy(data.begin(), data.end(), threadData->charBuffer.begin());
-	} else if ( threadData->PBFBlob.has_zlib_data() ) {
-		if ( !unpackZLIB(stream, threadData) ) {
-			std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl;
-			delete[] data;
-			return false;
-		}
-	} else if ( threadData->PBFBlob.has_lzma_data() ) {
-		if ( !unpackLZMA(stream, threadData) ) {
-			std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl;
-		}
-		delete[] data;
-		return false;
-	} else {
-		std::cerr << "[error] Blob contains no data" << std::endl;
-		delete[] data;
-		return false;
-	}
-	delete[] data;
-	return true;
+inline bool PBFParser::unpackLZMA(ParserThreadData *) { return false; }
+
+inline bool PBFParser::readBlob(std::fstream &stream, ParserThreadData *thread_data)
+{
+    if (stream.eof())
+    {
+        return false;
+    }
+
+    const int size = thread_data->PBFBlobHeader.datasize();
+    if (size < 0 || size > MAX_BLOB_SIZE)
+    {
+        std::cerr << "[error] invalid Blob size:" << size << std::endl;
+        return false;
+    }
+
+    char *data = new char[size];
+    stream.read(data, sizeof(data[0]) * size);
+
+    if (!thread_data->PBFBlob.ParseFromArray(data, size))
+    {
+        std::cerr << "[error] failed to parse blob" << std::endl;
+        delete[] data;
+        return false;
+    }
+
+    if (thread_data->PBFBlob.has_raw())
+    {
+        const std::string &data = thread_data->PBFBlob.raw();
+        thread_data->charBuffer.clear();
+        thread_data->charBuffer.resize(data.size());
+        std::copy(data.begin(), data.end(), thread_data->charBuffer.begin());
+    }
+    else if (thread_data->PBFBlob.has_zlib_data())
+    {
+        if (!unpackZLIB(thread_data))
+        {
+            std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl;
+            delete[] data;
+            return false;
+        }
+    }
+    else if (thread_data->PBFBlob.has_lzma_data())
+    {
+        if (!unpackLZMA(thread_data))
+        {
+            std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl;
+        }
+        delete[] data;
+        return false;
+    }
+    else
+    {
+        std::cerr << "[error] Blob contains no data" << std::endl;
+        delete[] data;
+        return false;
+    }
+    delete[] data;
+    return true;
 }
 
-bool PBFParser::readNextBlock(std::fstream& stream, _ThreadData * threadData) {
-	if(stream.eof()) {
-		return false;
-	}
-
-	if ( !readPBFBlobHeader(stream, threadData) ){
-		return false;
-	}
-
-	if ( threadData->PBFBlobHeader.type() != "OSMData" ) {
-		return false;
-	}
-
-	if ( !readBlob(stream, threadData) ) {
-		return false;
-	}
-
-	if ( !threadData->PBFprimitiveBlock.ParseFromArray( &(threadData->charBuffer[0]), threadData-> charBuffer.size() ) ) {
-		ERR("failed to parse PrimitiveBlock");
-		return false;
-	}
-	return true;
+bool PBFParser::readNextBlock(std::fstream &stream, ParserThreadData *thread_data)
+{
+    if (stream.eof())
+    {
+        return false;
+    }
+
+    if (!readPBFBlobHeader(stream, thread_data))
+    {
+        return false;
+    }
+
+    if (thread_data->PBFBlobHeader.type() != "OSMData")
+    {
+        return false;
+    }
+
+    if (!readBlob(stream, thread_data))
+    {
+        return false;
+    }
+
+    if (!thread_data->PBFprimitiveBlock.ParseFromArray(&(thread_data->charBuffer[0]),
+                                                       thread_data->charBuffer.size()))
+    {
+        std::cerr << "failed to parse PrimitiveBlock" << std::endl;
+        return false;
+    }
+    return true;
 }
diff --git a/Extractor/PBFParser.h b/Extractor/PBFParser.h
index f3748b6..c65a29d 100644
--- a/Extractor/PBFParser.h
+++ b/Extractor/PBFParser.h
@@ -1,57 +1,57 @@
 /*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
 
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
- 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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef PBFPARSER_H_
 #define PBFPARSER_H_
 
-#include "../DataStructures/HashTable.h"
-#include "../DataStructures/ConcurrentQueue.h"
-#include "../Util/MachineInfo.h"
-#include "../Util/OpenMPWrapper.h"
-#include "../typedefs.h"
-
 #include "BaseParser.h"
-#include <boost/shared_ptr.hpp>
-#include <boost/make_shared.hpp>
-#include <boost/ref.hpp>
+#include "../DataStructures/ConcurrentQueue.h"
 
 #include <osmpbf/fileformat.pb.h>
 #include <osmpbf/osmformat.pb.h>
 
-#include <zlib.h>
-
-
+#include <fstream>
+#include <memory>
 
-class PBFParser : public BaseParser {
+class PBFParser : public BaseParser
+{
 
-    enum EntityType {
-        TypeNode = 1,
-        TypeWay = 2,
-        TypeRelation = 4,
-        TypeDenseNode = 8
-    } ;
+    enum EntityType
+    { TypeDummy = 0,
+      TypeNode = 1,
+      TypeWay = 2,
+      TypeRelation = 4,
+      TypeDenseNode = 8 };
 
-    struct _ThreadData {
+    struct ParserThreadData
+    {
         int currentGroupID;
         int currentEntityID;
-        short entityTypeIndicator;
+        EntityType entityTypeIndicator;
 
         OSMPBF::BlobHeader PBFBlobHeader;
         OSMPBF::Blob PBFBlob;
@@ -62,41 +62,42 @@ class PBFParser : public BaseParser {
         std::vector<char> charBuffer;
     };
 
-public:
-    PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se);
+  public:
+    PBFParser(const char *file_name,
+              ExtractorCallbacks *extractor_callbacks,
+              ScriptingEnvironment &scripting_environment,
+              unsigned num_parser_threads = 0);
     virtual ~PBFParser();
 
     inline bool ReadHeader();
-	inline bool Parse();
+    inline bool Parse();
 
-private:
+  private:
     inline void ReadData();
     inline void ParseData();
-    inline void parseDenseNode(_ThreadData * threadData);
-    inline void parseNode(_ThreadData * );
-    inline void parseRelation(_ThreadData * threadData);
-    inline void parseWay(_ThreadData * threadData);
-
-    inline void loadGroup(_ThreadData * threadData);
-    inline void loadBlock(_ThreadData * threadData);
-    inline bool readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData);
-    inline bool unpackZLIB(std::fstream &, _ThreadData * threadData);
-    inline bool unpackLZMA(std::fstream &, _ThreadData * );
-    inline bool readBlob(std::fstream& stream, _ThreadData * threadData) ;
-    inline bool readNextBlock(std::fstream& stream, _ThreadData * threadData);
+    inline void parseDenseNode(ParserThreadData *thread_data);
+    inline void parseNode(ParserThreadData *thread_data);
+    inline void parseRelation(ParserThreadData *thread_data);
+    inline void parseWay(ParserThreadData *thread_data);
+
+    inline void loadGroup(ParserThreadData *thread_data);
+    inline void loadBlock(ParserThreadData *thread_data);
+    inline bool readPBFBlobHeader(std::fstream &stream, ParserThreadData *thread_data);
+    inline bool unpackZLIB(ParserThreadData *thread_data);
+    inline bool unpackLZMA(ParserThreadData *thread_data);
+    inline bool readBlob(std::fstream &stream, ParserThreadData *thread_data);
+    inline bool readNextBlock(std::fstream &stream, ParserThreadData *thread_data);
 
     static const int NANO = 1000 * 1000 * 1000;
     static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
     static const int MAX_BLOB_SIZE = 32 * 1024 * 1024;
 
-#ifndef NDEBUG
-    /* counting the number of read blocks and groups */
-    unsigned groupCount;
-    unsigned blockCount;
-#endif
+    unsigned group_count;
+    unsigned block_count;
 
-    std::fstream input;     // the input stream to parse
-    boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue;
+    std::fstream input; // the input stream to parse
+    std::shared_ptr<ConcurrentQueue<ParserThreadData *>> thread_data_queue;
+    unsigned num_parser_threads;
 };
 
 #endif /* PBFPARSER_H_ */
diff --git a/Extractor/ScriptingEnvironment.cpp b/Extractor/ScriptingEnvironment.cpp
index 6bab21c..01dee39 100644
--- a/Extractor/ScriptingEnvironment.cpp
+++ b/Extractor/ScriptingEnvironment.cpp
@@ -1,108 +1,121 @@
 /*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
 
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
- 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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #include "ScriptingEnvironment.h"
 
+#include "ExtractionHelperFunctions.h"
+#include "ExtractionWay.h"
+#include "../DataStructures/ImportNode.h"
+#include "../Util/LuaUtil.h"
+#include "../Util/OSRMException.h"
+#include "../Util/SimpleLogger.h"
+#include "../typedefs.h"
+
 ScriptingEnvironment::ScriptingEnvironment() {}
-ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
-	INFO("Using script " << fileName);
+ScriptingEnvironment::ScriptingEnvironment(const char *file_name)
+: file_name(file_name)
+{
+    SimpleLogger().Write() << "Using script " << file_name;
+}
+
+void ScriptingEnvironment::initLuaState(lua_State* lua_state)
+{
+    luabind::open(lua_state);
+    // open utility libraries string library;
+    luaL_openlibs(lua_state);
+
+    luaAddScriptFolderToLoadPath(lua_state, file_name.c_str());
+
+    // Add our function to the state's global scope
+    luabind::module(lua_state)[
+        luabind::def("print", LUA_print<std::string>),
+        luabind::def("durationIsValid", durationIsValid),
+        luabind::def("parseDuration", parseDuration)
+    ];
 
-    // Create a new lua state
-    for(int i = 0; i < omp_get_max_threads(); ++i)
-        luaStateVector.push_back(luaL_newstate());
+    luabind::module(lua_state)[luabind::class_<HashTable<std::string, std::string>>("keyVals")
+                                    .def("Add", &HashTable<std::string, std::string>::Add)
+                                    .def("Find", &HashTable<std::string, std::string>::Find)
+                                    .def("Holds", &HashTable<std::string, std::string>::Holds)];
 
-    // Connect LuaBind to this lua state for all threads
-#pragma omp parallel
+    luabind::module(lua_state)[luabind::class_<ImportNode>("Node")
+                                    .def(luabind::constructor<>())
+                                    .def_readwrite("lat", &ImportNode::lat)
+                                    .def_readwrite("lon", &ImportNode::lon)
+                                    .def_readonly("id", &ImportNode::node_id)
+                                    .def_readwrite("bollard", &ImportNode::bollard)
+                                    .def_readwrite("traffic_light", &ImportNode::trafficLight)
+                                    .def_readwrite("tags", &ImportNode::keyVals)];
+
+    luabind::module(lua_state)
+        [luabind::class_<ExtractionWay>("Way")
+             .def(luabind::constructor<>())
+             .def_readonly("id", &ExtractionWay::id)
+             .def_readwrite("name", &ExtractionWay::name)
+             .def_readwrite("speed", &ExtractionWay::speed)
+             .def_readwrite("backward_speed", &ExtractionWay::backward_speed)
+             .def_readwrite("duration", &ExtractionWay::duration)
+             .def_readwrite("type", &ExtractionWay::type)
+             .def_readwrite("access", &ExtractionWay::access)
+             .def_readwrite("roundabout", &ExtractionWay::roundabout)
+             .def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted)
+             .def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
+             .def_readwrite("tags", &ExtractionWay::keyVals)
+             .def_readwrite("direction", &ExtractionWay::direction)
+             .enum_("constants")[
+                 luabind::value("notSure", 0),
+                 luabind::value("oneway", 1),
+                 luabind::value("bidirectional", 2),
+                 luabind::value("opposite", 3)
+             ]];
+
+    // fails on c++11/OS X 10.9
+    luabind::module(lua_state)[luabind::class_<std::vector<std::string>>("vector").def(
+        "Add",
+        static_cast<void (std::vector<std::string>::*)(const std::string &)>(
+            &std::vector<std::string>::push_back))];
+
+    if (0 != luaL_dofile(lua_state, file_name.c_str()))
     {
-        lua_State * myLuaState = getLuaStateForThreadID(omp_get_thread_num());
-        luabind::open(myLuaState);
-        //open utility libraries string library;
-        luaL_openlibs(myLuaState);
-
-        luaAddScriptFolderToLoadPath( myLuaState, fileName );
-
-        // Add our function to the state's global scope
-        luabind::module(myLuaState) [
-                                     luabind::def("print", LUA_print<std::string>),
-                                     luabind::def("parseMaxspeed", parseMaxspeed),
-                                     luabind::def("durationIsValid", durationIsValid),
-                                     luabind::def("parseDuration", parseDuration)
-        ];
-
-        luabind::module(myLuaState) [
-                                     luabind::class_<HashTable<std::string, std::string> >("keyVals")
-                                     .def("Add", &HashTable<std::string, std::string>::Add)
-                                     .def("Find", &HashTable<std::string, std::string>::Find)
-                                     .def("Holds", &HashTable<std::string, std::string>::Holds)
-                                     ];
-
-        luabind::module(myLuaState) [
-                                     luabind::class_<ImportNode>("Node")
-                                     .def(luabind::constructor<>())
-                                     .def_readwrite("lat", &ImportNode::lat)
-                                     .def_readwrite("lon", &ImportNode::lon)
-                                     .def_readwrite("id", &ImportNode::id)
-                                     .def_readwrite("bollard", &ImportNode::bollard)
-                                     .def_readwrite("traffic_light", &ImportNode::trafficLight)
-                                     .def_readwrite("tags", &ImportNode::keyVals)
-                                     ];
-
-        luabind::module(myLuaState) [
-                                     luabind::class_<ExtractionWay>("Way")
-                                     .def(luabind::constructor<>())
-                                     .def_readwrite("name", &ExtractionWay::name)
-                                     .def_readwrite("speed", &ExtractionWay::speed)
-                                     .def_readwrite("backward_speed", &ExtractionWay::backward_speed)
-                                     .def_readwrite("duration", &ExtractionWay::duration)
-                                     .def_readwrite("type", &ExtractionWay::type)
-                                     .def_readwrite("access", &ExtractionWay::access)
-                                     .def_readwrite("roundabout", &ExtractionWay::roundabout)
-                                     .def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted)
-                                     .def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
-                                     .def_readwrite("tags", &ExtractionWay::keyVals)
-                                     .def_readwrite("direction", &ExtractionWay::direction)
-                                     .enum_("constants")
-										 [
-										  luabind::value("notSure", 0),
-										  luabind::value("oneway", 1),
-										  luabind::value("bidirectional", 2),
-										  luabind::value("opposite", 3)
-										 ]
-        							 ];
-        luabind::module(myLuaState) [
-                                     luabind::class_<std::vector<std::string> >("vector")
-                                     .def("Add", &std::vector<std::string>::push_back)
-                                     ];
-
-        if(0 != luaL_dofile(myLuaState, fileName) ) {
-            ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
-        }
+        throw OSRMException("ERROR occured in scripting block");
     }
 }
 
-ScriptingEnvironment::~ScriptingEnvironment() {
-    for(unsigned i = 0; i < luaStateVector.size(); ++i) {
-        //        luaStateVector[i];
+lua_State *ScriptingEnvironment::getLuaState()
+{
+    bool initialized = false;
+    auto& ref = script_contexts.local(initialized);
+    if (!initialized)
+    {
+        std::shared_ptr<lua_State> state(luaL_newstate(), lua_close);
+        ref = state;
+        initLuaState(ref.get());
     }
-}
 
-lua_State * ScriptingEnvironment::getLuaStateForThreadID(const int id) {
-    return luaStateVector[id];
+    return ref.get();
 }
+
diff --git a/Extractor/ScriptingEnvironment.h b/Extractor/ScriptingEnvironment.h
index 015ff25..2b1fffe 100644
--- a/Extractor/ScriptingEnvironment.h
+++ b/Extractor/ScriptingEnvironment.h
@@ -1,50 +1,52 @@
 /*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
 
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
- 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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef SCRIPTINGENVIRONMENT_H_
 #define SCRIPTINGENVIRONMENT_H_
 
-extern "C" {
-#include <lua.h>
-#include <lauxlib.h>
-#include <lualib.h>
-}
-#include <luabind/luabind.hpp>
+#include <string>
+#include <memory>
+#include <tbb/enumerable_thread_specific.h>
 
-#include "ExtractionHelperFunctions.h"
-#include "ExtractorStructs.h"
+struct lua_State;
 
-#include "../typedefs.h"
-#include "../DataStructures/ImportNode.h"
-#include "../Util/LuaUtil.h"
-#include "../Util/OpenMPWrapper.h"
-
-class ScriptingEnvironment {
-public:
+class ScriptingEnvironment
+{
+  public:
     ScriptingEnvironment();
-    ScriptingEnvironment(const char * fileName);
-    virtual ~ScriptingEnvironment();
+    explicit ScriptingEnvironment(const char *file_name);
+
+    lua_State *getLuaState();
 
-    lua_State * getLuaStateForThreadID(const int);
+  private:
+    void initLuaState(lua_State* lua_state);
 
-    std::vector<lua_State *> luaStateVector;
+    std::string file_name;
+    tbb::enumerable_thread_specific<std::shared_ptr<lua_State>> script_contexts;
 };
 
 #endif /* SCRIPTINGENVIRONMENT_H_ */
diff --git a/Extractor/XMLParser.cpp b/Extractor/XMLParser.cpp
index fa810a7..3a5446e 100644
--- a/Extractor/XMLParser.cpp
+++ b/Extractor/XMLParser.cpp
@@ -1,276 +1,353 @@
 /*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
 
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
- 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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#include <boost/ref.hpp>
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #include "XMLParser.h"
 
-#include "ExtractorStructs.h"
+#include "ExtractionWay.h"
+#include "ExtractorCallbacks.h"
+
 #include "../DataStructures/HashTable.h"
+#include "../DataStructures/ImportNode.h"
 #include "../DataStructures/InputReaderFactory.h"
+#include "../DataStructures/Restriction.h"
+#include "../Util/SimpleLogger.h"
+#include "../Util/StringUtil.h"
+#include "../typedefs.h"
 
+#include <osrm/Coordinate.h>
 
-XMLParser::XMLParser(const char * filename, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser(ec, se) {
-	WARN("Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf");
-	inputReader = inputReaderFactory(filename);
+XMLParser::XMLParser(const char *filename,
+                     ExtractorCallbacks *extractor_callbacks,
+                     ScriptingEnvironment &scripting_environment)
+    : BaseParser(extractor_callbacks, scripting_environment)
+{
+    inputReader = inputReaderFactory(filename);
 }
 
-bool XMLParser::ReadHeader() {
-	return (xmlTextReaderRead( inputReader ) == 1);
-}
-bool XMLParser::Parse() {
-	while ( xmlTextReaderRead( inputReader ) == 1 ) {
-		const int type = xmlTextReaderNodeType( inputReader );
-
-		//1 is Element
-		if ( type != 1 ) {
-			continue;
-		}
-		
-		xmlChar* currentName = xmlTextReaderName( inputReader );
-		if ( currentName == NULL ) {
-			continue;
-		}
-		
-		if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) {
-			ImportNode n = _ReadXMLNode();
-			ParseNodeInLua( n, luaState );
-			extractor_callbacks->nodeFunction(n);
-//			if(!extractor_callbacks->nodeFunction(n))
-//				std::cerr << "[XMLParser] dense node not parsed" << std::endl;
-		}
-
-		if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
-			ExtractionWay way = _ReadXMLWay( );
-			ParseWayInLua( way, luaState );
-			extractor_callbacks->wayFunction(way);
-//			if(!extractor_callbacks->wayFunction(way))
-//				std::cerr << "[PBFParser] way not parsed" << std::endl;
-		}
-		if( use_turn_restrictions ) {
-			if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
-				_RawRestrictionContainer r = _ReadXMLRestriction();
-				if(r.fromWay != UINT_MAX) {
-					if(!extractor_callbacks->restrictionFunction(r)) {
-						std::cerr << "[XMLParser] restriction not parsed" << std::endl;
-					}
-				}
-			}
-		}
-		xmlFree( currentName );
-	}
-	return true;
+bool XMLParser::ReadHeader() { return xmlTextReaderRead(inputReader) == 1; }
+bool XMLParser::Parse()
+{
+    while (xmlTextReaderRead(inputReader) == 1)
+    {
+        const int type = xmlTextReaderNodeType(inputReader);
+
+        // 1 is Element
+        if (type != 1)
+        {
+            continue;
+        }
+
+        xmlChar *currentName = xmlTextReaderName(inputReader);
+        if (currentName == nullptr)
+        {
+            continue;
+        }
+
+        if (xmlStrEqual(currentName, (const xmlChar *)"node") == 1)
+        {
+            ImportNode current_node = ReadXMLNode();
+            ParseNodeInLua(current_node, lua_state);
+            extractor_callbacks->ProcessNode(current_node);
+        }
+
+        if (xmlStrEqual(currentName, (const xmlChar *)"way") == 1)
+        {
+            ExtractionWay way = ReadXMLWay();
+            ParseWayInLua(way, lua_state);
+            extractor_callbacks->ProcessWay(way);
+        }
+        if (use_turn_restrictions && xmlStrEqual(currentName, (const xmlChar *)"relation") == 1)
+        {
+            InputRestrictionContainer current_restriction = ReadXMLRestriction();
+            if ((UINT_MAX != current_restriction.fromWay) &&
+                !extractor_callbacks->ProcessRestriction(current_restriction))
+            {
+                std::cerr << "[XMLParser] restriction not parsed" << std::endl;
+            }
+        }
+        xmlFree(currentName);
+    }
+    return true;
 }
 
-_RawRestrictionContainer XMLParser::_ReadXMLRestriction() {
-    _RawRestrictionContainer restriction;
+InputRestrictionContainer XMLParser::ReadXMLRestriction()
+{
+
+    InputRestrictionContainer restriction;
+
+    if (xmlTextReaderIsEmptyElement(inputReader) == 1)
+    {
+        return restriction;
+    }
+
     std::string except_tag_string;
+    const int depth = xmlTextReaderDepth(inputReader);
+    while (xmlTextReaderRead(inputReader) == 1)
+    {
+        const int child_type = xmlTextReaderNodeType(inputReader);
+        if (child_type != 1 && child_type != 15)
+        {
+            continue;
+        }
+        const int child_depth = xmlTextReaderDepth(inputReader);
+        xmlChar *child_name = xmlTextReaderName(inputReader);
+        if (child_name == nullptr)
+        {
+            continue;
+        }
+        if (depth == child_depth && child_type == 15 &&
+            xmlStrEqual(child_name, (const xmlChar *)"relation") == 1)
+        {
+            xmlFree(child_name);
+            break;
+        }
+        if (child_type != 1)
+        {
+            xmlFree(child_name);
+            continue;
+        }
+
+        if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
+        {
+            xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
+            xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
+            if (key != nullptr && value != nullptr)
+            {
+                if (xmlStrEqual(key, (const xmlChar *)"restriction") &&
+                    StringStartsWith((const char *)value, "only_"))
+                {
+                    restriction.restriction.flags.isOnly = true;
+                }
+                if (xmlStrEqual(key, (const xmlChar *)"except"))
+                {
+                    except_tag_string = (const char *)value;
+                }
+            }
 
-	if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
-		const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) {
-			const int childType = xmlTextReaderNodeType( inputReader );
-			if ( childType != 1 && childType != 15 ) {
-				continue;
-			}
-			const int childDepth = xmlTextReaderDepth( inputReader );
-			xmlChar* childName = xmlTextReaderName( inputReader );
-			if ( childName == NULL ) {
-				continue;
-			}
-			if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) {
-				xmlFree( childName );
-				break;
-			}
-			if ( childType != 1 ) {
-				xmlFree( childName );
-				continue;
-			}
-
-			if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
-				xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
-				xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
-				if ( k != NULL && value != NULL ) {
-					if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){
-						if(0 == std::string((const char *) value).find("only_")) {
-							restriction.restriction.flags.isOnly = true;
-						}
-					}
-					if ( xmlStrEqual(k, (const xmlChar *) "except") ) {
-						except_tag_string = (const char*) value;
-					}
-				}
-
-				if ( k != NULL ) {
-					xmlFree( k );
-				}
-				if ( value != NULL ) {
-					xmlFree( value );
-				}
-			} else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) {
-				xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
-				if ( ref != NULL ) {
-					xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" );
-					xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" );
-
-					if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) {
-						restriction.toWay = atoi((const char*) ref);
-					}
-					if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) {
-						restriction.fromWay = atoi((const char*) ref);
-					}
-					if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) {
-						restriction.restriction.viaNode = atoi((const char*) ref);
-					}
-
-					if(NULL != type) {
-						xmlFree( type );
-					}
-					if(NULL != role) {
-						xmlFree( role );
-					}
-					if(NULL != ref) {
-						xmlFree( ref );
-					}
-				}
-			}
-			xmlFree( childName );
-		}
-	}
-
-	if( ShouldIgnoreRestriction(except_tag_string) ) {
-		restriction.fromWay = UINT_MAX;				 //workaround to ignore the restriction
-	}
-	return restriction;
+            if (key != nullptr)
+            {
+                xmlFree(key);
+            }
+            if (value != nullptr)
+            {
+                xmlFree(value);
+            }
+        }
+        else if (xmlStrEqual(child_name, (const xmlChar *)"member") == 1)
+        {
+            xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
+            if (ref != nullptr)
+            {
+                xmlChar *role = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"role");
+                xmlChar *type = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"type");
+
+                if (xmlStrEqual(role, (const xmlChar *)"to") &&
+                    xmlStrEqual(type, (const xmlChar *)"way"))
+                {
+                    restriction.toWay = StringToUint((const char *)ref);
+                }
+                if (xmlStrEqual(role, (const xmlChar *)"from") &&
+                    xmlStrEqual(type, (const xmlChar *)"way"))
+                {
+                    restriction.fromWay = StringToUint((const char *)ref);
+                }
+                if (xmlStrEqual(role, (const xmlChar *)"via") &&
+                    xmlStrEqual(type, (const xmlChar *)"node"))
+                {
+                    restriction.restriction.viaNode = StringToUint((const char *)ref);
+                }
+
+                if (nullptr != type)
+                {
+                    xmlFree(type);
+                }
+                if (nullptr != role)
+                {
+                    xmlFree(role);
+                }
+                if (nullptr != ref)
+                {
+                    xmlFree(ref);
+                }
+            }
+        }
+        xmlFree(child_name);
+    }
+
+    if (ShouldIgnoreRestriction(except_tag_string))
+    {
+        restriction.fromWay = UINT_MAX; // workaround to ignore the restriction
+    }
+    return restriction;
 }
 
-ExtractionWay XMLParser::_ReadXMLWay() {
-	ExtractionWay way;
-	if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
-		const int depth = xmlTextReaderDepth( inputReader );
-		while ( xmlTextReaderRead( inputReader ) == 1 ) {
-			const int childType = xmlTextReaderNodeType( inputReader );
-			if ( childType != 1 && childType != 15 ) {
-				continue;
-			}
-			const int childDepth = xmlTextReaderDepth( inputReader );
-			xmlChar* childName = xmlTextReaderName( inputReader );
-			if ( childName == NULL ) {
-				continue;
-			}
-
-			if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) {
-				xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
-				way.id = atoi((char*)id);
-				xmlFree(id);
-				xmlFree( childName );
-				break;
-			}
-			if ( childType != 1 ) {
-				xmlFree( childName );
-				continue;
-			}
-
-			if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
-				xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
-				xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
-				//				cout << "->k=" << k << ", v=" << value << endl;
-				if ( k != NULL && value != NULL ) {
-					way.keyVals.Add(std::string( (char *) k ), std::string( (char *) value));
-				}
-				if ( k != NULL ) {
-					xmlFree( k );
-				}
-				if ( value != NULL ) {
-					xmlFree( value );
-				}
-			} else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) {
-				xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
-				if ( ref != NULL ) {
-					way.path.push_back( atoi(( const char* ) ref ) );
-					xmlFree( ref );
-				}
-			}
-			xmlFree( childName );
-		}
-	}
-	return way;
+ExtractionWay XMLParser::ReadXMLWay()
+{
+    ExtractionWay way;
+    if (xmlTextReaderIsEmptyElement(inputReader) == 1)
+    {
+        return way;
+    }
+    const int depth = xmlTextReaderDepth(inputReader);
+    while (xmlTextReaderRead(inputReader) == 1)
+    {
+        const int child_type = xmlTextReaderNodeType(inputReader);
+        if (child_type != 1 && child_type != 15)
+        {
+            continue;
+        }
+        const int child_depth = xmlTextReaderDepth(inputReader);
+        xmlChar *child_name = xmlTextReaderName(inputReader);
+        if (child_name == nullptr)
+        {
+            continue;
+        }
+
+        if (depth == child_depth && child_type == 15 &&
+            xmlStrEqual(child_name, (const xmlChar *)"way") == 1)
+        {
+            xmlChar *node_id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
+            way.id = StringToUint((char *)node_id);
+            xmlFree(node_id);
+            xmlFree(child_name);
+            break;
+        }
+        if (child_type != 1)
+        {
+            xmlFree(child_name);
+            continue;
+        }
+
+        if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
+        {
+            xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
+            xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
+
+            if (key != nullptr && value != nullptr)
+            {
+                way.keyVals.Add(std::string((char *)key), std::string((char *)value));
+            }
+            if (key != nullptr)
+            {
+                xmlFree(key);
+            }
+            if (value != nullptr)
+            {
+                xmlFree(value);
+            }
+        }
+        else if (xmlStrEqual(child_name, (const xmlChar *)"nd") == 1)
+        {
+            xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
+            if (ref != nullptr)
+            {
+                way.path.push_back(StringToUint((const char *)ref));
+                xmlFree(ref);
+            }
+        }
+        xmlFree(child_name);
+    }
+    return way;
 }
 
-ImportNode XMLParser::_ReadXMLNode() {
-	ImportNode node;
-
-	xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" );
-	if ( attribute != NULL ) {
-		node.lat =  static_cast<NodeID>(100000.*atof(( const char* ) attribute ) );
-		xmlFree( attribute );
-	}
-	attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" );
-	if ( attribute != NULL ) {
-		node.lon =  static_cast<NodeID>(100000.*atof(( const char* ) attribute ));
-		xmlFree( attribute );
-	}
-	attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
-	if ( attribute != NULL ) {
-		node.id =  atoi(( const char* ) attribute );
-		xmlFree( attribute );
-	}
-
-	if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
-		const int depth = xmlTextReaderDepth( inputReader );
-		while ( xmlTextReaderRead( inputReader ) == 1 ) {
-			const int childType = xmlTextReaderNodeType( inputReader );
-			// 1 = Element, 15 = EndElement
-			if ( childType != 1 && childType != 15 ) {
-				continue;
-			}
-			const int childDepth = xmlTextReaderDepth( inputReader );
-			xmlChar* childName = xmlTextReaderName( inputReader );
-			if ( childName == NULL ) {
-				continue;
-			}
-
-			if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) {
-				xmlFree( childName );
-				break;
-			}
-			if ( childType != 1 ) {
-				xmlFree( childName );
-				continue;
-			}
-
-			if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
-				xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
-				xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
-				if ( k != NULL && value != NULL ) {
-					node.keyVals.Add(std::string( reinterpret_cast<char*>(k) ), std::string( reinterpret_cast<char*>(value)));
-				}
-				if ( k != NULL ) {
-					xmlFree( k );
-				}
-				if ( value != NULL ) {
-					xmlFree( value );
-				}
-			}
-
-			xmlFree( childName );
-		}
-	}
-	return node;
+ImportNode XMLParser::ReadXMLNode()
+{
+    ImportNode node;
+
+    xmlChar *attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lat");
+    if (attribute != nullptr)
+    {
+        node.lat = static_cast<int>(COORDINATE_PRECISION * StringToDouble((const char *)attribute));
+        xmlFree(attribute);
+    }
+    attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lon");
+    if (attribute != nullptr)
+    {
+        node.lon = static_cast<int>(COORDINATE_PRECISION * StringToDouble((const char *)attribute));
+        xmlFree(attribute);
+    }
+    attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
+    if (attribute != nullptr)
+    {
+        node.node_id = StringToUint((const char *)attribute);
+        xmlFree(attribute);
+    }
+
+    if (xmlTextReaderIsEmptyElement(inputReader) == 1)
+    {
+        return node;
+    }
+    const int depth = xmlTextReaderDepth(inputReader);
+    while (xmlTextReaderRead(inputReader) == 1)
+    {
+        const int child_type = xmlTextReaderNodeType(inputReader);
+        // 1 = Element, 15 = EndElement
+        if (child_type != 1 && child_type != 15)
+        {
+            continue;
+        }
+        const int child_depth = xmlTextReaderDepth(inputReader);
+        xmlChar *child_name = xmlTextReaderName(inputReader);
+        if (child_name == nullptr)
+        {
+            continue;
+        }
+
+        if (depth == child_depth && child_type == 15 &&
+            xmlStrEqual(child_name, (const xmlChar *)"node") == 1)
+        {
+            xmlFree(child_name);
+            break;
+        }
+        if (child_type != 1)
+        {
+            xmlFree(child_name);
+            continue;
+        }
+
+        if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
+        {
+            xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
+            xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
+            if (key != nullptr && value != nullptr)
+            {
+                node.keyVals.Add(std::string((char *)(key)), std::string((char *)(value)));
+            }
+            if (key != nullptr)
+            {
+                xmlFree(key);
+            }
+            if (value != nullptr)
+            {
+                xmlFree(value);
+            }
+        }
+
+        xmlFree(child_name);
+    }
+    return node;
 }
diff --git a/Extractor/XMLParser.h b/Extractor/XMLParser.h
index a2af2fb..178747a 100644
--- a/Extractor/XMLParser.h
+++ b/Extractor/XMLParser.h
@@ -1,41 +1,53 @@
 /*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
- 
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
- 
- 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.
- 
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef XMLPARSER_H_
 #define XMLPARSER_H_
 
+#include "BaseParser.h"
+#include "../DataStructures/Restriction.h"
+
 #include <libxml/xmlreader.h>
 
-#include "../typedefs.h"
-#include "BaseParser.h"
+class ExtractorCallbacks;
 
-class XMLParser : public BaseParser {
-public:
-    XMLParser(const char* filename, ExtractorCallbacks* ec, ScriptingEnvironment& se);
+class XMLParser : public BaseParser
+{
+  public:
+    XMLParser(const char *filename,
+              ExtractorCallbacks *extractor_callbacks,
+              ScriptingEnvironment &scripting_environment);
     bool ReadHeader();
     bool Parse();
-    
-private:
-    _RawRestrictionContainer _ReadXMLRestriction();
-    ExtractionWay _ReadXMLWay();
-    ImportNode _ReadXMLNode();
+
+  private:
+    InputRestrictionContainer ReadXMLRestriction();
+    ExtractionWay ReadXMLWay();
+    ImportNode ReadXMLNode();
     xmlTextReaderPtr inputReader;
 };
 
diff --git a/Gemfile.lock b/Gemfile.lock
index 32a3fda..ac056a0 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,23 +1,23 @@
 GEM
   remote: http://rubygems.org/
   specs:
-    builder (3.0.0)
-    cucumber (1.1.4)
+    builder (3.2.2)
+    cucumber (1.3.8)
       builder (>= 2.1.2)
-      diff-lcs (>= 1.1.2)
-      gherkin (~> 2.7.1)
-      json (>= 1.4.6)
-      term-ansicolor (>= 1.0.6)
-    diff-lcs (1.1.3)
-    gherkin (2.7.6)
-      json (>= 1.4.6)
-    json (1.6.5)
+      diff-lcs (>= 1.1.3)
+      gherkin (~> 2.12.1)
+      multi_json (>= 1.7.5, < 2.0)
+      multi_test (>= 0.0.2)
+    diff-lcs (1.2.4)
+    gherkin (2.12.1)
+      multi_json (~> 1.3)
+    multi_json (1.8.0)
+    multi_test (0.0.2)
     osmlib-base (0.1.4)
-    rake (0.9.2.2)
-    rspec-expectations (2.11.3)
-      diff-lcs (~> 1.1.3)
-    sys-proctable (0.9.1)
-    term-ansicolor (1.0.7)
+    rake (10.1.0)
+    rspec-expectations (2.14.3)
+      diff-lcs (>= 1.1.3, < 2.0)
+    sys-proctable (0.9.3)
 
 PLATFORMS
   ruby
diff --git a/Include/osrm/Coordinate.h b/Include/osrm/Coordinate.h
new file mode 100644
index 0000000..dc05855
--- /dev/null
+++ b/Include/osrm/Coordinate.h
@@ -0,0 +1,105 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef FIXED_POINT_COORDINATE_H_
+#define FIXED_POINT_COORDINATE_H_
+
+#include <functional>
+#include <iosfwd> //for std::ostream
+#include <string>
+
+const float COORDINATE_PRECISION = 1000000.f;
+
+struct FixedPointCoordinate
+{
+    int lat;
+    int lon;
+
+    FixedPointCoordinate();
+    explicit FixedPointCoordinate(int lat, int lon);
+    void Reset();
+    bool isSet() const;
+    bool isValid() const;
+    bool operator==(const FixedPointCoordinate &other) const;
+
+    static double
+    ApproximateDistance(const int lat1, const int lon1, const int lat2, const int lon2);
+
+    static double ApproximateDistance(const FixedPointCoordinate &first_coordinate,
+                                      const FixedPointCoordinate &second_coordinate);
+
+    static float ApproximateEuclideanDistance(const FixedPointCoordinate &first_coordinate,
+                                              const FixedPointCoordinate &second_coordinate);
+
+    static float ApproximateEuclideanDistance(const int lat1,
+                                              const int lon1,
+                                              const int lat2,
+                                              const int lon2);
+
+    static float ApproximateSquaredEuclideanDistance(const FixedPointCoordinate &first_coordinate,
+                                                     const FixedPointCoordinate &second_coordinate);
+
+    static void convertInternalLatLonToString(const int value, std::string &output);
+
+    static void convertInternalCoordinateToString(const FixedPointCoordinate &coordinate,
+                                                  std::string &output);
+
+    static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coordinate,
+                                                          std::string &output);
+
+    static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
+                                              const FixedPointCoordinate &segment_target,
+                                              const FixedPointCoordinate &query_location);
+
+    static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
+                                              const FixedPointCoordinate &segment_target,
+                                              const FixedPointCoordinate &query_location,
+                                              FixedPointCoordinate &nearest_location,
+                                              float &ratio);
+
+    static int OrderedPerpendicularDistanceApproximation(const FixedPointCoordinate& segment_source,
+                                                         const FixedPointCoordinate& segment_target,
+                                                         const FixedPointCoordinate& query_location);
+
+
+    static float GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B);
+
+    float GetBearing(const FixedPointCoordinate &other) const;
+
+    void Output(std::ostream &out) const;
+
+    static float DegreeToRadian(const float degree);
+    static float RadianToDegree(const float radian);
+};
+
+inline std::ostream &operator<<(std::ostream &out_stream, FixedPointCoordinate const &coordinate)
+{
+    coordinate.Output(out_stream);
+    return out_stream;
+}
+
+#endif /* FIXED_POINT_COORDINATE_H_ */
diff --git a/Include/osrm/Header.h b/Include/osrm/Header.h
new file mode 100644
index 0000000..de0b2ab
--- /dev/null
+++ b/Include/osrm/Header.h
@@ -0,0 +1,53 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef HTTP_HEADER_H
+#define HTTP_HEADER_H
+
+#include <string>
+#include <algorithm>
+
+namespace http
+{
+struct Header
+{
+    Header& operator=(const Header& other) = default;
+    Header(const std::string & name, const std::string & value) : name(name), value(value) {}
+    Header(const Header && other) : name(std::move(other.name)), value(std::move(other.value)) {}
+
+    void Clear()
+    {
+        name.clear();
+        value.clear();
+    }
+
+    std::string name;
+    std::string value;
+};
+}
+
+#endif // HTTP_HEADER_H
diff --git a/Include/osrm/Reply.h b/Include/osrm/Reply.h
new file mode 100644
index 0000000..a2ee1f4
--- /dev/null
+++ b/Include/osrm/Reply.h
@@ -0,0 +1,74 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef REPLY_H
+#define REPLY_H
+
+#include "Header.h"
+
+#include <boost/asio.hpp>
+
+#include <vector>
+
+namespace http
+{
+
+const char okHTML[] = "";
+const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}";
+const char internalServerErrorHTML[] =
+    "{\"status\": 500,\"status_message\":\"Internal Server Error\"}";
+const char seperators[] = {':', ' '};
+const char crlf[] = {'\r', '\n'};
+const std::string okString = "HTTP/1.0 200 OK\r\n";
+const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n";
+const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
+
+class Reply
+{
+  public:
+    enum status_type
+    { ok = 200,
+      badRequest = 400,
+      internalServerError = 500 } status;
+
+    std::vector<Header> headers;
+    std::vector<boost::asio::const_buffer> ToBuffers();
+    std::vector<boost::asio::const_buffer> HeaderstoBuffers();
+    std::vector<char> content;
+    static Reply StockReply(status_type status);
+    void SetSize(const unsigned size);
+    void SetUncompressedSize();
+
+    Reply();
+
+  private:
+    std::string ToString(Reply::status_type status);
+    boost::asio::const_buffer ToBuffer(Reply::status_type status);
+};
+}
+
+#endif // REPLY_H
diff --git a/Include/osrm/RouteParameters.h b/Include/osrm/RouteParameters.h
new file mode 100644
index 0000000..89a1774
--- /dev/null
+++ b/Include/osrm/RouteParameters.h
@@ -0,0 +1,83 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef ROUTE_PARAMETERS_H
+#define ROUTE_PARAMETERS_H
+
+#include <osrm/Coordinate.h>
+
+#include <boost/fusion/container/vector/vector_fwd.hpp>
+
+#include <string>
+#include <vector>
+
+struct RouteParameters
+{
+    RouteParameters();
+
+    void setZoomLevel(const short level);
+
+    void setAlternateRouteFlag(const bool flag);
+
+    void setDeprecatedAPIFlag(const std::string &);
+
+    void setChecksum(const unsigned check_sum);
+
+    void setInstructionFlag(const bool flag);
+
+    void setService(const std::string &service);
+
+    void setOutputFormat(const std::string &format);
+
+    void setJSONpParameter(const std::string &parameter);
+
+    void addHint(const std::string &hint);
+
+    void setLanguage(const std::string &language);
+
+    void setGeometryFlag(const bool flag);
+
+    void setCompressionFlag(const bool flag);
+
+    void addCoordinate(const boost::fusion::vector<double, double> &coordinates);
+
+    short zoom_level;
+    bool print_instructions;
+    bool alternate_route;
+    bool geometry;
+    bool compression;
+    bool deprecatedAPI;
+    unsigned check_sum;
+    std::string service;
+    std::string output_format;
+    std::string jsonp_parameter;
+    std::string language;
+    std::vector<std::string> hints;
+    std::vector<FixedPointCoordinate> coordinates;
+};
+
+#endif // ROUTE_PARAMETERS_H
diff --git a/Include/osrm/ServerPaths.h b/Include/osrm/ServerPaths.h
new file mode 100644
index 0000000..52b60c7
--- /dev/null
+++ b/Include/osrm/ServerPaths.h
@@ -0,0 +1,38 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef SERVER_PATH_H
+#define SERVER_PATH_H
+
+#include <boost/filesystem.hpp>
+
+#include <unordered_map>
+#include <string>
+
+typedef std::unordered_map<std::string, boost::filesystem::path> ServerPaths;
+
+#endif // SERVER_PATH_H
diff --git a/LICENCE.TXT b/LICENCE.TXT
index dba13ed..28fe97b 100644
--- a/LICENCE.TXT
+++ b/LICENCE.TXT
@@ -1,661 +1,22 @@
-                    GNU AFFERO GENERAL PUBLIC LICENSE
-                       Version 3, 19 November 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The GNU Affero General Public License is a free, copyleft license for
-software and other kinds of works, specifically designed to ensure
-cooperation with the community in the case of network server software.
-
-  The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works.  By contrast,
-our General Public Licenses are intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
-  Developers that use our General Public Licenses protect your rights
-with two steps: (1) assert copyright on the software, and (2) offer
-you this License which gives you legal permission to copy, distribute
-and/or modify the software.
-
-  A secondary benefit of defending all users' freedom is that
-improvements made in alternate versions of the program, if they
-receive widespread use, become available for other developers to
-incorporate.  Many developers of free software are heartened and
-encouraged by the resulting cooperation.  However, in the case of
-software used on network servers, this result may fail to come about.
-The GNU General Public License permits making a modified version and
-letting the public access it on a server without ever releasing its
-source code to the public.
-
-  The GNU Affero General Public License is designed specifically to
-ensure that, in such cases, the modified source code becomes available
-to the community.  It requires the operator of a network server to
-provide the source code of the modified version running there to the
-users of that server.  Therefore, public use of a modified version, on
-a publicly accessible server, gives the public access to the source
-code of the modified version.
-
-  An older license, called the Affero General Public License and
-published by Affero, was designed to accomplish similar goals.  This is
-a different license, not a version of the Affero GPL, but Affero has
-released a new version of the Affero GPL which permits relicensing under
-this license.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                       TERMS AND CONDITIONS
-
-  0. Definitions.
-
-  "This License" refers to version 3 of the GNU Affero General Public License.
-
-  "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
-  "The Program" refers to any copyrightable work licensed under this
-License.  Each licensee is addressed as "you".  "Licensees" and
-"recipients" may be individuals or organizations.
-
-  To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy.  The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
-  A "covered work" means either the unmodified Program or a work based
-on the Program.
-
-  To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy.  Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
-  To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies.  Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
-  An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License.  If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
-  1. Source Code.
-
-  The "source code" for a work means the preferred form of the work
-for making modifications to it.  "Object code" means any non-source
-form of a work.
-
-  A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
-  The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form.  A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
-  The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities.  However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work.  For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
-  The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
-  The Corresponding Source for a work in source code form is that
-same work.
-
-  2. Basic Permissions.
-
-  All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met.  This License explicitly affirms your unlimited
-permission to run the unmodified Program.  The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work.  This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
-  You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force.  You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright.  Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
-  Conveying under any other circumstances is permitted solely under
-the conditions stated below.  Sublicensing is not allowed; section 10
-makes it unnecessary.
-
-  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
-  No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
-  When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
-  4. Conveying Verbatim Copies.
-
-  You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
-  You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
-  5. Conveying Modified Source Versions.
-
-  You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
-    a) The work must carry prominent notices stating that you modified
-    it, and giving a relevant date.
-
-    b) The work must carry prominent notices stating that it is
-    released under this License and any conditions added under section
-    7.  This requirement modifies the requirement in section 4 to
-    "keep intact all notices".
-
-    c) You must license the entire work, as a whole, under this
-    License to anyone who comes into possession of a copy.  This
-    License will therefore apply, along with any applicable section 7
-    additional terms, to the whole of the work, and all its parts,
-    regardless of how they are packaged.  This License gives no
-    permission to license the work in any other way, but it does not
-    invalidate such permission if you have separately received it.
-
-    d) If the work has interactive user interfaces, each must display
-    Appropriate Legal Notices; however, if the Program has interactive
-    interfaces that do not display Appropriate Legal Notices, your
-    work need not make them do so.
-
-  A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit.  Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
-  6. Conveying Non-Source Forms.
-
-  You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
-    a) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by the
-    Corresponding Source fixed on a durable physical medium
-    customarily used for software interchange.
-
-    b) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by a
-    written offer, valid for at least three years and valid for as
-    long as you offer spare parts or customer support for that product
-    model, to give anyone who possesses the object code either (1) a
-    copy of the Corresponding Source for all the software in the
-    product that is covered by this License, on a durable physical
-    medium customarily used for software interchange, for a price no
-    more than your reasonable cost of physically performing this
-    conveying of source, or (2) access to copy the
-    Corresponding Source from a network server at no charge.
-
-    c) Convey individual copies of the object code with a copy of the
-    written offer to provide the Corresponding Source.  This
-    alternative is allowed only occasionally and noncommercially, and
-    only if you received the object code with such an offer, in accord
-    with subsection 6b.
-
-    d) Convey the object code by offering access from a designated
-    place (gratis or for a charge), and offer equivalent access to the
-    Corresponding Source in the same way through the same place at no
-    further charge.  You need not require recipients to copy the
-    Corresponding Source along with the object code.  If the place to
-    copy the object code is a network server, the Corresponding Source
-    may be on a different server (operated by you or a third party)
-    that supports equivalent copying facilities, provided you maintain
-    clear directions next to the object code saying where to find the
-    Corresponding Source.  Regardless of what server hosts the
-    Corresponding Source, you remain obligated to ensure that it is
-    available for as long as needed to satisfy these requirements.
-
-    e) Convey the object code using peer-to-peer transmission, provided
-    you inform other peers where the object code and Corresponding
-    Source of the work are being offered to the general public at no
-    charge under subsection 6d.
-
-  A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
-  A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling.  In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage.  For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product.  A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
-  "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source.  The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
-  If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information.  But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
-  The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed.  Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
-  Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
-  7. Additional Terms.
-
-  "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law.  If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
-  When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it.  (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.)  You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
-  Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
-    a) Disclaiming warranty or limiting liability differently from the
-    terms of sections 15 and 16 of this License; or
-
-    b) Requiring preservation of specified reasonable legal notices or
-    author attributions in that material or in the Appropriate Legal
-    Notices displayed by works containing it; or
-
-    c) Prohibiting misrepresentation of the origin of that material, or
-    requiring that modified versions of such material be marked in
-    reasonable ways as different from the original version; or
-
-    d) Limiting the use for publicity purposes of names of licensors or
-    authors of the material; or
-
-    e) Declining to grant rights under trademark law for use of some
-    trade names, trademarks, or service marks; or
-
-    f) Requiring indemnification of licensors and authors of that
-    material by anyone who conveys the material (or modified versions of
-    it) with contractual assumptions of liability to the recipient, for
-    any liability that these contractual assumptions directly impose on
-    those licensors and authors.
-
-  All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10.  If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term.  If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
-  If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
-  Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
-  8. Termination.
-
-  You may not propagate or modify a covered work except as expressly
-provided under this License.  Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
-  However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
-  Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
-  Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License.  If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
-  9. Acceptance Not Required for Having Copies.
-
-  You are not required to accept this License in order to receive or
-run a copy of the Program.  Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance.  However,
-nothing other than this License grants you permission to propagate or
-modify any covered work.  These actions infringe copyright if you do
-not accept this License.  Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
-  10. Automatic Licensing of Downstream Recipients.
-
-  Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License.  You are not responsible
-for enforcing compliance by third parties with this License.
-
-  An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations.  If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
-  You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License.  For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
-  11. Patents.
-
-  A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based.  The
-work thus licensed is called the contributor's "contributor version".
-
-  A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version.  For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
-  Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
-  In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement).  To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
-  If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients.  "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
-  If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
-  A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License.  You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
-  Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
-  12. No Surrender of Others' Freedom.
-
-  If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all.  For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
-  13. Remote Network Interaction; Use with the GNU General Public License.
-
-  Notwithstanding any other provision of this License, if you modify the
-Program, your modified version must prominently offer all users
-interacting with it remotely through a computer network (if your version
-supports such interaction) an opportunity to receive the Corresponding
-Source of your version by providing access to the Corresponding Source
-from a network server at no charge, through some standard or customary
-means of facilitating copying of software.  This Corresponding Source
-shall include the Corresponding Source for any work covered by version 3
-of the GNU General Public License that is incorporated pursuant to the
-following paragraph.
-
-  Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU General Public License into a single
-combined work, and to convey the resulting work.  The terms of this
-License will continue to apply to the part which is the covered work,
-but the work with which it is combined will remain governed by version
-3 of the GNU General Public License.
-
-  14. Revised Versions of this License.
-
-  The Free Software Foundation may publish revised and/or new versions of
-the GNU Affero General Public License from time to time.  Such new versions
-will be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-  Each version is given a distinguishing version number.  If the
-Program specifies that a certain numbered version of the GNU Affero General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation.  If the Program does not specify a version number of the
-GNU Affero General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
-  If the Program specifies that a proxy can decide which future
-versions of the GNU Affero General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
-  Later license versions may give you additional or different
-permissions.  However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
-  15. Disclaimer of Warranty.
-
-  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. Limitation of Liability.
-
-  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
-  17. Interpretation of Sections 15 and 16.
-
-  If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU Affero General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    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 Affero General Public License for more details.
-
-    You should have received a copy of the GNU Affero General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
-  If your software can interact with users remotely through a computer
-network, you should also make sure that it provides a way for users to
-get its source.  For example, if your program is a web application, its
-interface could display a "Source" link that leads users to an archive
-of the code.  There are many ways you could offer source, and different
-solutions will be better for different programs; see section 13 for the
-specific requirements.
-
-  You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU AGPL, see
-<http://www.gnu.org/licenses/>.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Library/OSRM.h b/Library/OSRM.h
new file mode 100644
index 0000000..16b9977
--- /dev/null
+++ b/Library/OSRM.h
@@ -0,0 +1,52 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef OSRM_H
+#define OSRM_H
+
+#include <osrm/ServerPaths.h>
+
+class OSRM_impl;
+struct RouteParameters;
+
+namespace http
+{
+class Reply;
+}
+
+class OSRM
+{
+  private:
+    OSRM_impl *OSRM_pimpl_;
+
+  public:
+    explicit OSRM(const ServerPaths &paths, const bool use_shared_memory = false);
+    ~OSRM();
+    void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
+};
+
+#endif // OSRM_H
diff --git a/Library/OSRM_impl.cpp b/Library/OSRM_impl.cpp
new file mode 100644
index 0000000..5c20b5a
--- /dev/null
+++ b/Library/OSRM_impl.cpp
@@ -0,0 +1,167 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+namespace boost { namespace interprocess { class named_mutex; } }
+
+#include "OSRM_impl.h"
+#include "OSRM.h"
+
+#include <osrm/Reply.h>
+#include <osrm/RouteParameters.h>
+#include <osrm/ServerPaths.h>
+
+#include "../Plugins/BasePlugin.h"
+#include "../Plugins/DistanceTablePlugin.h"
+#include "../Plugins/HelloWorldPlugin.h"
+#include "../Plugins/LocatePlugin.h"
+#include "../Plugins/NearestPlugin.h"
+#include "../Plugins/TimestampPlugin.h"
+#include "../Plugins/ViaRoutePlugin.h"
+#include "../Server/DataStructures/BaseDataFacade.h"
+#include "../Server/DataStructures/InternalDataFacade.h"
+#include "../Server/DataStructures/SharedBarriers.h"
+#include "../Server/DataStructures/SharedDataFacade.h"
+#include "../Util/SimpleLogger.h"
+
+#include <boost/assert.hpp>
+#include <boost/interprocess/sync/named_condition.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+
+#include <algorithm>
+#include <fstream>
+#include <utility>
+#include <vector>
+
+OSRM_impl::OSRM_impl(const ServerPaths &server_paths, const bool use_shared_memory)
+    : use_shared_memory(use_shared_memory)
+{
+    if (use_shared_memory)
+    {
+        barrier = new SharedBarriers();
+        query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>();
+    }
+    else
+    {
+        query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(server_paths);
+    }
+
+    // The following plugins handle all requests.
+    RegisterPlugin(new DistanceTablePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
+    RegisterPlugin(new HelloWorldPlugin());
+    RegisterPlugin(new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
+    RegisterPlugin(new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
+    RegisterPlugin(new TimestampPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
+    RegisterPlugin(new ViaRoutePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
+}
+
+OSRM_impl::~OSRM_impl()
+{
+    delete query_data_facade;
+    for (PluginMap::value_type &plugin_pointer : plugin_map)
+    {
+        delete plugin_pointer.second;
+    }
+    if (use_shared_memory)
+    {
+        delete barrier;
+    }
+}
+
+void OSRM_impl::RegisterPlugin(BasePlugin *plugin)
+{
+    SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
+    if (plugin_map.find(plugin->GetDescriptor()) != plugin_map.end())
+    {
+        delete plugin_map.find(plugin->GetDescriptor())->second;
+    }
+    plugin_map.emplace(plugin->GetDescriptor(), plugin);
+}
+
+void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
+{
+    const PluginMap::const_iterator &iter = plugin_map.find(route_parameters.service);
+
+    if (plugin_map.end() != iter)
+    {
+        reply.status = http::Reply::ok;
+        if (use_shared_memory)
+        {
+            // lock update pending
+            boost::interprocess::scoped_lock<boost::interprocess::named_mutex> pending_lock(
+                barrier->pending_update_mutex);
+
+            // lock query
+            boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
+                barrier->query_mutex);
+
+            // unlock update pending
+            pending_lock.unlock();
+
+            // increment query count
+            ++(barrier->number_of_queries);
+
+            (static_cast<SharedDataFacade<QueryEdge::EdgeData> *>(query_data_facade))
+                ->CheckAndReloadFacade();
+        }
+
+        iter->second->HandleRequest(route_parameters, reply);
+        if (use_shared_memory)
+        {
+            // lock query
+            boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
+                barrier->query_mutex);
+
+            // decrement query count
+            --(barrier->number_of_queries);
+            BOOST_ASSERT_MSG(0 <= barrier->number_of_queries, "invalid number of queries");
+
+            // notify all processes that were waiting for this condition
+            if (0 == barrier->number_of_queries)
+            {
+                barrier->no_running_queries_condition.notify_all();
+            }
+        }
+    }
+    else
+    {
+        reply = http::Reply::StockReply(http::Reply::badRequest);
+    }
+}
+
+// proxy code for compilation firewall
+
+OSRM::OSRM(const ServerPaths &paths, const bool use_shared_memory)
+    : OSRM_pimpl_(new OSRM_impl(paths, use_shared_memory))
+{
+}
+
+OSRM::~OSRM() { delete OSRM_pimpl_; }
+
+void OSRM::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
+{
+    OSRM_pimpl_->RunQuery(route_parameters, reply);
+}
diff --git a/Library/OSRM_impl.h b/Library/OSRM_impl.h
new file mode 100644
index 0000000..8ad98bb
--- /dev/null
+++ b/Library/OSRM_impl.h
@@ -0,0 +1,65 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef OSRM_IMPL_H
+#define OSRM_IMPL_H
+
+class BasePlugin;
+namespace http { class Reply; }
+struct RouteParameters;
+
+#include <osrm/ServerPaths.h>
+
+#include "../DataStructures/QueryEdge.h"
+
+#include <unordered_map>
+#include <string>
+
+struct SharedBarriers;
+template <class EdgeDataT> class BaseDataFacade;
+
+class OSRM_impl
+{
+  private:
+    typedef std::unordered_map<std::string, BasePlugin *> PluginMap;
+
+  public:
+    OSRM_impl(const ServerPaths &paths, const bool use_shared_memory);
+    OSRM_impl(const OSRM_impl &) = delete;
+    virtual ~OSRM_impl();
+    void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
+
+  private:
+    void RegisterPlugin(BasePlugin *plugin);
+    PluginMap plugin_map;
+    bool use_shared_memory;
+    SharedBarriers *barrier;
+    // base class pointer to the objects
+    BaseDataFacade<QueryEdge::EdgeData> *query_data_facade;
+};
+
+#endif // OSRM_IMPL_H
diff --git a/Plugins/BasePlugin.h b/Plugins/BasePlugin.h
index 266d5d8..11c6940 100644
--- a/Plugins/BasePlugin.h
+++ b/Plugins/BasePlugin.h
@@ -1,41 +1,50 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef BASEPLUGIN_H_
 #define BASEPLUGIN_H_
 
-#include <cassert>
+#include "../Util/StringUtil.h"
+
+#include <osrm/Coordinate.h>
+#include <osrm/Reply.h>
+#include <osrm/RouteParameters.h>
+
 #include <string>
 #include <vector>
 
-#include "RouteParameters.h"
-#include "../Server/BasicDatastructures.h"
-
-class BasePlugin {
-public:
-	BasePlugin() { }
-	//Maybe someone can explain the pure virtual destructor thing to me (dennis)
-	virtual ~BasePlugin() { }
-	virtual std::string GetDescriptor() const = 0;
-	virtual std::string GetVersionString() const = 0 ;
-	virtual void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) = 0;
+class BasePlugin
+{
+  public:
+    BasePlugin() {}
+    // Maybe someone can explain the pure virtual destructor thing to me (dennis)
+    virtual ~BasePlugin() {}
+    virtual const std::string GetDescriptor() const = 0;
+    virtual void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply) = 0;
 };
 
 #endif /* BASEPLUGIN_H_ */
diff --git a/Plugins/DistanceTablePlugin.h b/Plugins/DistanceTablePlugin.h
new file mode 100644
index 0000000..d3e307b
--- /dev/null
+++ b/Plugins/DistanceTablePlugin.h
@@ -0,0 +1,146 @@
+/*
+
+Copyright (c) 2014, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef DISTANCE_TABLE_PLUGIN_H
+#define DISTANCE_TABLE_PLUGIN_H
+
+#include "BasePlugin.h"
+
+#include "../Algorithms/ObjectToBase64.h"
+#include "../DataStructures/JSONContainer.h"
+#include "../DataStructures/QueryEdge.h"
+#include "../DataStructures/SearchEngine.h"
+#include "../Descriptors/BaseDescriptor.h"
+#include "../Util/SimpleLogger.h"
+#include "../Util/StringUtil.h"
+#include "../Util/TimingUtil.h"
+
+#include <cstdlib>
+
+#include <algorithm>
+#include <memory>
+#include <unordered_map>
+#include <string>
+#include <vector>
+
+template <class DataFacadeT> class DistanceTablePlugin : public BasePlugin
+{
+  private:
+    std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
+
+  public:
+    explicit DistanceTablePlugin(DataFacadeT *facade) : descriptor_string("table"), facade(facade)
+    {
+        search_engine_ptr = std::make_shared<SearchEngine<DataFacadeT>>(facade);
+    }
+
+    virtual ~DistanceTablePlugin() {}
+
+    const std::string GetDescriptor() const { return descriptor_string; }
+
+    void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
+    {
+        // check number of parameters
+        if (2 > route_parameters.coordinates.size())
+        {
+            reply = http::Reply::StockReply(http::Reply::badRequest);
+            return;
+        }
+
+        RawRouteData raw_route;
+        raw_route.check_sum = facade->GetCheckSum();
+
+        if (std::any_of(begin(route_parameters.coordinates),
+                        end(route_parameters.coordinates),
+                        [&](FixedPointCoordinate coordinate)
+                        { return !coordinate.isValid(); }))
+        {
+            reply = http::Reply::StockReply(http::Reply::badRequest);
+            return;
+        }
+
+        for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
+        {
+            raw_route.raw_via_node_coordinates.emplace_back(std::move(coordinate));
+        }
+
+        const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
+        unsigned max_locations =
+            std::min(100u, static_cast<unsigned>(raw_route.raw_via_node_coordinates.size()));
+        PhantomNodeArray phantom_node_vector(max_locations);
+        for (unsigned i = 0; i < max_locations; ++i)
+        {
+            if (checksum_OK && i < route_parameters.hints.size() &&
+                !route_parameters.hints[i].empty())
+            {
+                PhantomNode current_phantom_node;
+                DecodeObjectFromBase64(route_parameters.hints[i], current_phantom_node);
+                if (current_phantom_node.isValid(facade->GetNumberOfNodes()))
+                {
+                    phantom_node_vector[i].emplace_back(std::move(current_phantom_node));
+                    continue;
+                }
+            }
+            facade->IncrementalFindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
+                                                            phantom_node_vector[i],
+                                                            route_parameters.zoom_level,
+                                                            1);
+
+            BOOST_ASSERT(phantom_node_vector[i].front().isValid(facade->GetNumberOfNodes()));
+        }
+
+        // TIMER_START(distance_table);
+        std::shared_ptr<std::vector<EdgeWeight>> result_table =
+            search_engine_ptr->distance_table(phantom_node_vector);
+        // TIMER_STOP(distance_table);
+
+        if (!result_table)
+        {
+            reply = http::Reply::StockReply(http::Reply::badRequest);
+            return;
+        }
+        JSON::Object json_object;
+        JSON::Array json_array;
+        const unsigned number_of_locations = static_cast<unsigned>(phantom_node_vector.size());
+        for (unsigned row = 0; row < number_of_locations; ++row)
+        {
+            JSON::Array json_row;
+            auto row_begin_iterator = result_table->begin() + (row * number_of_locations);
+            auto row_end_iterator = result_table->begin() + ((row + 1) * number_of_locations);
+            json_row.values.insert(json_row.values.end(), row_begin_iterator, row_end_iterator);
+            json_array.values.push_back(json_row);
+        }
+        json_object.values["distance_table"] = json_array;
+        JSON::render(reply.content, json_object);
+    }
+
+  private:
+    std::string descriptor_string;
+    DataFacadeT *facade;
+};
+
+#endif // DISTANCE_TABLE_PLUGIN_H
diff --git a/Plugins/HelloWorldPlugin.h b/Plugins/HelloWorldPlugin.h
index ae0ff64..2d99a10 100644
--- a/Plugins/HelloWorldPlugin.h
+++ b/Plugins/HelloWorldPlugin.h
@@ -1,50 +1,103 @@
 /*
- * LocatePlugin.h
- *
- *  Created on: 01.01.2011
- *      Author: dennis
- */
 
-#ifndef HELLOWORLDPLUGIN_H_
-#define HELLOWORLDPLUGIN_H_
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-#include <sstream>
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef HELLO_WORLD_PLUGIN_H
+#define HELLO_WORLD_PLUGIN_H
 
 #include "BasePlugin.h"
-#include "RouteParameters.h"
-
-class HelloWorldPlugin : public BasePlugin {
-public:
-	HelloWorldPlugin() {}
-	virtual ~HelloWorldPlugin() { /*std::cout << GetDescriptor() << " destructor" << std::endl;*/ }
-	std::string GetDescriptor() const { return std::string("hello"); }
-	std::string GetVersionString() const { return std::string("0.1a"); }
-
-	void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
-		reply.status = http::Reply::ok;
-		reply.content.append("<html><head><title>Hello World Demonstration Document</title></head><body><h1>Hello, World!</h1>");
-		std::stringstream content;
-		content << "<pre>";
-        content << "zoom level: " << routeParameters.zoomLevel << "\n";
-        content << "checksum: " << routeParameters.checkSum << "\n";
-        content << "instructions: " << (routeParameters.printInstructions ? "yes" : "no") << "\n";
-        content << "geometry: " << (routeParameters.geometry ? "yes" : "no") << "\n";
-        content << "compression: " << (routeParameters.compression ? "yes" : "no") << "\n";
-        content << "output format: " << routeParameters.outputFormat << "\n";
-        content << "json parameter: " << routeParameters.jsonpParameter << "\n";
-        content << "language: " << routeParameters.language << "<br>";
-        content << "Number of locations: " << routeParameters.coordinates.size() << "\n";
-        for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
-            content << "  [" << i << "] " << routeParameters.coordinates[i].lat/100000. << "," << routeParameters.coordinates[i].lon/100000. << "\n";
+#include "../DataStructures/JSONContainer.h"
+#include "../Util/StringUtil.h"
+
+#include <string>
+
+class HelloWorldPlugin : public BasePlugin
+{
+  private:
+    std::string temp_string;
+
+  public:
+    HelloWorldPlugin() : descriptor_string("hello") {}
+    virtual ~HelloWorldPlugin() {}
+    const std::string GetDescriptor() const { return descriptor_string; }
+
+    void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply)
+    {
+        reply.status = http::Reply::ok;
+
+        JSON::Object json_result;
+        std::string temp_string;
+        json_result.values["title"] = "Hello World";
+
+        temp_string = IntToString(routeParameters.zoom_level);
+        json_result.values["zoom_level"] = temp_string;
+
+        temp_string = UintToString(routeParameters.check_sum);
+        json_result.values["check_sum"] = temp_string;
+        json_result.values["instructions"] = (routeParameters.print_instructions ? "yes" : "no");
+        json_result.values["geometry"] = (routeParameters.geometry ? "yes" : "no");
+        json_result.values["compression"] = (routeParameters.compression ? "yes" : "no");
+        json_result.values["output_format"] = (!routeParameters.output_format.empty() ? "yes" : "no");
+
+        json_result.values["jsonp_parameter"] = (!routeParameters.jsonp_parameter.empty() ? "yes" : "no");
+        json_result.values["language"] = (!routeParameters.language.empty() ? "yes" : "no");
+
+        temp_string = UintToString(static_cast<unsigned>(routeParameters.coordinates.size()));
+        json_result.values["location_count"] = temp_string;
+
+        JSON::Array json_locations;
+        unsigned counter = 0;
+        for (const FixedPointCoordinate &coordinate : routeParameters.coordinates)
+        {
+            JSON::Object json_location;
+            JSON::Array json_coordinates;
+
+            json_coordinates.values.push_back(coordinate.lat / COORDINATE_PRECISION);
+            json_coordinates.values.push_back(coordinate.lon / COORDINATE_PRECISION);
+            json_location.values[UintToString(counter)] = json_coordinates;
+            json_locations.values.push_back(json_location);
+            ++counter;
         }
-        content << "Number of hints: " << routeParameters.hints.size() << "\n";
-        for(unsigned i = 0; i < routeParameters.hints.size(); ++i) {
-            content << "  [" << i << "] " << routeParameters.hints[i] << "\n";
+        json_result.values["locations"] = json_locations;
+        json_result.values["hint_count"] = routeParameters.hints.size();
+
+        JSON::Array json_hints;
+        counter = 0;
+        for (const std::string &current_hint : routeParameters.hints)
+        {
+            json_hints.values.push_back(current_hint);
+            ++counter;
         }
-        content << "</pre>";
-		reply.content.append(content.str());
-		reply.content.append("</body></html>");
-	}
+        json_result.values["hints"] = json_hints;
+
+        JSON::render(reply.content, json_result);
+    }
+
+  private:
+    std::string descriptor_string;
 };
 
-#endif /* HELLOWORLDPLUGIN_H_ */
+#endif // HELLO_WORLD_PLUGIN_H
diff --git a/Plugins/LocatePlugin.h b/Plugins/LocatePlugin.h
index f1c7d60..518259d 100644
--- a/Plugins/LocatePlugin.h
+++ b/Plugins/LocatePlugin.h
@@ -1,113 +1,79 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef LOCATEPLUGIN_H_
-#define LOCATEPLUGIN_H_
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef LOCATE_PLUGIN_H
+#define LOCATE_PLUGIN_H
 
 #include "BasePlugin.h"
-#include "RouteParameters.h"
-#include "../DataStructures/NodeInformationHelpDesk.h"
-#include "../Server/DataStructures/QueryObjectsStorage.h"
+#include "../DataStructures/JSONContainer.h"
 #include "../Util/StringUtil.h"
 
-#include <fstream>
+#include <string>
 
-/*
- * This Plugin locates the nearest node in the road network for a given coordinate.
- */
-class LocatePlugin : public BasePlugin {
-public:
-    LocatePlugin(QueryObjectsStorage * objects) {
-        nodeHelpDesk = objects->nodeHelpDesk;
-    }
-    std::string GetDescriptor() const { return std::string("locate"); }
-    std::string GetVersionString() const { return std::string("0.3 (DL)"); }
-    void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
-        //check number of parameters
-        if(!routeParameters.coordinates.size()) {
-            reply = http::Reply::stockReply(http::Reply::badRequest);
-            return;
-        }
-        if(false == checkCoord(routeParameters.coordinates[0])) {
-            reply = http::Reply::stockReply(http::Reply::badRequest);
+// locates the nearest node in the road network for a given coordinate.
+template <class DataFacadeT> class LocatePlugin : public BasePlugin
+{
+  public:
+    explicit LocatePlugin(DataFacadeT *facade) : descriptor_string("locate"), facade(facade) {}
+    const std::string GetDescriptor() const { return descriptor_string; }
+
+    void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
+    {
+        // check number of parameters
+        if (route_parameters.coordinates.empty() ||
+            !route_parameters.coordinates.front().isValid())
+        {
+            reply = http::Reply::StockReply(http::Reply::badRequest);
             return;
         }
 
-        //query to helpdesk
-        _Coordinate result;
-        std::string tmp;
-        //json
-
-//        JSONParameter = routeParameters.options.Find("jsonp");
-        if("" != routeParameters.jsonpParameter) {
-            reply.content += routeParameters.jsonpParameter;
-            reply.content += "(";
+        JSON::Object json_result;
+        FixedPointCoordinate result;
+        if (!facade->LocateClosestEndPointForCoordinate(route_parameters.coordinates.front(),
+                                                        result))
+        {
+            json_result.values["status"] = 207;
         }
-        reply.status = http::Reply::ok;
-        reply.content += ("{");
-        reply.content += ("\"version\":0.3,");
-        if(!nodeHelpDesk->FindNearestNodeCoordForLatLon(routeParameters.coordinates[0], result)) {
-            reply.content += ("\"status\":207,");
-            reply.content += ("\"mapped_coordinate\":[]");
-        } else {
-            //Write coordinate to stream
+        else
+        {
             reply.status = http::Reply::ok;
-            reply.content += ("\"status\":0,");
-            reply.content += ("\"mapped_coordinate\":");
-            convertInternalLatLonToString(result.lat, tmp);
-            reply.content += "[";
-            reply.content += tmp;
-            convertInternalLatLonToString(result.lon, tmp);
-            reply.content += ",";
-            reply.content += tmp;
-            reply.content += "]";
-        }
-        reply.content += ",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\"";
-        reply.content += ("}");
-        reply.headers.resize(3);
-        if("" != routeParameters.jsonpParameter) {
-            reply.content += ")";
-            reply.headers[1].name = "Content-Type";
-            reply.headers[1].value = "text/javascript";
-            reply.headers[2].name = "Content-Disposition";
-            reply.headers[2].value = "attachment; filename=\"location.js\"";
-        } else {
-            reply.headers[1].name = "Content-Type";
-            reply.headers[1].value = "application/x-javascript";
-            reply.headers[2].name = "Content-Disposition";
-            reply.headers[2].value = "attachment; filename=\"location.json\"";
+            json_result.values["status"] = 0;
+            JSON::Array json_coordinate;
+            json_coordinate.values.push_back(result.lat/COORDINATE_PRECISION);
+            json_coordinate.values.push_back(result.lon/COORDINATE_PRECISION);
+            json_result.values["mapped_coordinate"] = json_coordinate;
         }
-        reply.headers[0].name = "Content-Length";
-        intToString(reply.content.size(), tmp);
-        reply.headers[0].value = tmp;
-        return;
-    }
-private:
-    inline bool checkCoord(const _Coordinate & c) {
-        if(c.lat > 90*100000 || c.lat < -90*100000 || c.lon > 180*100000 || c.lon <-180*100000) {
-            return false;
-        }
-        return true;
+
+        JSON::render(reply.content, json_result);
     }
 
-    NodeInformationHelpDesk * nodeHelpDesk;
+  private:
+    std::string descriptor_string;
+    DataFacadeT *facade;
 };
 
-#endif /* LOCATEPLUGIN_H_ */
+#endif /* LOCATE_PLUGIN_H */
diff --git a/Plugins/NearestPlugin.h b/Plugins/NearestPlugin.h
index c10230f..27bd016 100644
--- a/Plugins/NearestPlugin.h
+++ b/Plugins/NearestPlugin.h
@@ -1,124 +1,91 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
 
-#ifndef NearestPlugin_H_
-#define NearestPlugin_H_
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-#include <fstream>
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-#include "BasePlugin.h"
-#include "RouteParameters.h"
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include "../Server/DataStructures/QueryObjectsStorage.h"
+*/
 
-#include "../DataStructures/NodeInformationHelpDesk.h"
-#include "../Util/StringUtil.h"
+#ifndef NEAREST_PLUGIN_H
+#define NEAREST_PLUGIN_H
+
+#include "BasePlugin.h"
+#include "../DataStructures/JSONContainer.h"
+#include "../DataStructures/PhantomNodes.h"
+
+#include <string>
 
 /*
  * This Plugin locates the nearest point on a street in the road network for a given coordinate.
  */
-class NearestPlugin : public BasePlugin {
-public:
-    NearestPlugin(QueryObjectsStorage * objects) : names(objects->names) {
-        nodeHelpDesk = objects->nodeHelpDesk;
 
-        descriptorTable.Set("", 0); //default descriptor
-        descriptorTable.Set("json", 1);
-    }
-    std::string GetDescriptor() const { return std::string("nearest"); }
-    std::string GetVersionString() const { return std::string("0.3 (DL)"); }
-    void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
-        //check number of parameters
-        if(!routeParameters.coordinates.size()) {
-            reply = http::Reply::stockReply(http::Reply::badRequest);
-            return;
-        }
-        if(false == checkCoord(routeParameters.coordinates[0])) {
-            reply = http::Reply::stockReply(http::Reply::badRequest);
+template <class DataFacadeT> class NearestPlugin : public BasePlugin
+{
+  public:
+    explicit NearestPlugin(DataFacadeT *facade) : facade(facade), descriptor_string("nearest") {}
+
+    const std::string GetDescriptor() const { return descriptor_string; }
+
+    void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
+    {
+        // check number of parameters
+        if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().isValid())
+        {
+            reply = http::Reply::StockReply(http::Reply::badRequest);
             return;
         }
 
-        //query to helpdesk
-        PhantomNode result;
-        nodeHelpDesk->FindPhantomNodeForCoordinate(routeParameters.coordinates[0], result, routeParameters.zoomLevel);
+        std::vector<PhantomNode> phantom_node_vector;
+        facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates.front(),
+                                                        phantom_node_vector,
+                                                        route_parameters.zoom_level,
+                                                        1);
 
-        std::string tmp;
-        //json
-
-        if("" != routeParameters.jsonpParameter) {
-            reply.content += routeParameters.jsonpParameter;
-            reply.content += "(";
+        JSON::Object json_result;
+        if (phantom_node_vector.empty() || !phantom_node_vector.front().isValid())
+        {
+            json_result.values["status"] = 207;
         }
-
-        reply.status = http::Reply::ok;
-        reply.content += ("{");
-        reply.content += ("\"version\":0.3,");
-        reply.content += ("\"status\":");
-        if(UINT_MAX != result.edgeBasedNode)
-            reply.content += "0,";
         else
-            reply.content += "207,";
-        reply.content += ("\"mapped_coordinate\":");
-        reply.content += "[";
-        if(UINT_MAX != result.edgeBasedNode) {
-            convertInternalLatLonToString(result.location.lat, tmp);
-            reply.content += tmp;
-            convertInternalLatLonToString(result.location.lon, tmp);
-            reply.content += ",";
-            reply.content += tmp;
+        {
+            reply.status = http::Reply::ok;
+            json_result.values["status"] = 0;
+            JSON::Array json_coordinate;
+            json_coordinate.values.push_back(phantom_node_vector.front().location.lat /
+                                             COORDINATE_PRECISION);
+            json_coordinate.values.push_back(phantom_node_vector.front().location.lon /
+                                             COORDINATE_PRECISION);
+            json_result.values["mapped_coordinate"] = json_coordinate;
+            std::string temp_string;
+            facade->GetName(phantom_node_vector.front().name_id, temp_string);
+            json_result.values["name"] = temp_string;
         }
-        reply.content += "],";
-        reply.content += "\"name\":\"";
-        if(UINT_MAX != result.edgeBasedNode)
-            reply.content += names[result.nodeBasedEdgeNameID];
-        reply.content += "\"";
-        reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\"";
-        reply.content += ("}");
-        reply.headers.resize(3);
-        if("" != routeParameters.jsonpParameter) {
-            reply.content += ")";
-            reply.headers[1].name = "Content-Type";
-            reply.headers[1].value = "text/javascript";
-            reply.headers[2].name = "Content-Disposition";
-            reply.headers[2].value = "attachment; filename=\"location.js\"";
-        } else {
-            reply.headers[1].name = "Content-Type";
-            reply.headers[1].value = "application/x-javascript";
-            reply.headers[2].name = "Content-Disposition";
-            reply.headers[2].value = "attachment; filename=\"location.json\"";
-        }
-        reply.headers[0].name = "Content-Length";
-        intToString(reply.content.size(), tmp);
-        reply.headers[0].value = tmp;
-    }
-private:
-    inline bool checkCoord(const _Coordinate & c) {
-        if(c.lat > 90*100000 || c.lat < -90*100000 || c.lon > 180*100000 || c.lon <-180*100000) {
-            return false;
-        }
-        return true;
+
+        JSON::render(reply.content, json_result);
     }
 
-    NodeInformationHelpDesk * nodeHelpDesk;
-    HashTable<std::string, unsigned> descriptorTable;
-    std::vector<std::string> & names;
+  private:
+    DataFacadeT *facade;
+    std::string descriptor_string;
 };
 
-#endif /* NearestPlugin_H_ */
+#endif /* NEAREST_PLUGIN_H */
diff --git a/Plugins/PluginMapFactory.h b/Plugins/PluginMapFactory.h
deleted file mode 100644
index 9027b18..0000000
--- a/Plugins/PluginMapFactory.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef PLUGINMAPFACTORY_H_
-#define PLUGINMAPFACTORY_H_
-
-//#include "../DataStructures/HashTable.h"
-//#include "../Plugins/BasePlugin.h"
-//
-//struct PluginMapFactory {
-//	static HashTable<std::string, BasePlugin *> * CreatePluginMap() {
-//		HashTable<std::string, BasePlugin *> * map = new HashTable<std::string, BasePlugin *>();
-//
-//	}
-//};
-
-#endif	/* PLUGINMAPFACTORY_H_ */
diff --git a/Plugins/RawRouteData.h b/Plugins/RawRouteData.h
deleted file mode 100644
index f0c1054..0000000
--- a/Plugins/RawRouteData.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef RAWROUTEDATA_H_
-#define RAWROUTEDATA_H_
-
-#include "../typedefs.h"
-
-struct _PathData {
-    _PathData(NodeID no, unsigned na, unsigned tu, unsigned dur) : node(no), nameID(na), durationOfSegment(dur), turnInstruction(tu) { }
-    NodeID node;
-    unsigned nameID;
-    unsigned durationOfSegment;
-    short turnInstruction;
-};
-
-struct RawRouteData {
-    std::vector< _PathData > computedShortestPath;
-    std::vector< _PathData > computedAlternativePath;
-    std::vector< PhantomNodes > segmentEndCoordinates;
-    std::vector< _Coordinate > rawViaNodeCoordinates;
-    unsigned checkSum;
-    int lengthOfShortestPath;
-    int lengthOfAlternativePath;
-    RawRouteData() : checkSum(UINT_MAX), lengthOfShortestPath(INT_MAX), lengthOfAlternativePath(INT_MAX) {}
-};
-
-#endif /* RAWROUTEDATA_H_ */
diff --git a/Plugins/RouteParameters.h b/Plugins/RouteParameters.h
deleted file mode 100644
index a718f96..0000000
--- a/Plugins/RouteParameters.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef ROUTE_PARAMETERS_H
-#define ROUTE_PARAMETERS_H
-
-#include <string>
-#include <vector>
-
-#include <boost/fusion/sequence/intrinsic.hpp>
-
-#include "../DataStructures/Coordinate.h"
-
-struct RouteParameters {
-    RouteParameters() : zoomLevel(18), printInstructions(false), alternateRoute(true), geometry(true), compression(true), deprecatedAPI(false), checkSum(-1) {}
-    short zoomLevel;
-    bool printInstructions;
-    bool alternateRoute;
-    bool geometry;
-    bool compression;
-    bool deprecatedAPI;
-    unsigned checkSum;
-    std::string service;
-    std::string outputFormat;
-    std::string jsonpParameter;
-    std::string language;
-    std::vector<std::string> hints;
-    std::vector<_Coordinate> coordinates;
-    typedef HashTable<std::string, std::string>::MyIterator OptionsIterator;
-
-    void setZoomLevel(const short i) {
-        if (18 > i && 0 < i)
-            zoomLevel = i;
-    }
-
-    void setAlternateRouteFlag(const bool b) {
-        alternateRoute = b;
-    }
-
-    void setDeprecatedAPIFlag(const std::string &) {
-        deprecatedAPI = true;
-    }
-
-    void setChecksum(const unsigned c) {
-        checkSum = c;
-    }
-
-    void setInstructionFlag(const bool b) {
-        printInstructions = b;
-    }
-
-    void setService( const std::string & s) {
-        service = s;
-    }
-
-    void setOutputFormat(const std::string & s) {
-        outputFormat = s;
-    }
-
-    void setJSONpParameter(const std::string & s) {
-        jsonpParameter = s;
-    }
-
-    void addHint(const std::string & s) {
-        hints.resize(coordinates.size());
-        hints.back() = s;
-    }
-
-    void setLanguage(const std::string & s) {
-        language = s;
-    }
-
-    void setGeometryFlag(const bool b) {
-        geometry = b;
-    }
-
-    void setCompressionFlag(const bool b) {
-        compression = b;
-    }
-
-    void addCoordinate(boost::fusion::vector < double, double > arg_) {
-        int lat = 100000.*boost::fusion::at_c < 0 > (arg_);
-        int lon = 100000.*boost::fusion::at_c < 1 > (arg_);
-        _Coordinate myCoordinate(lat, lon);
-        coordinates.push_back(_Coordinate(lat, lon));
-    }
-};
-
-
-#endif /*ROUTE_PARAMETERS_H*/
diff --git a/Plugins/TimestampPlugin.h b/Plugins/TimestampPlugin.h
index 33c606e..63f63b2 100644
--- a/Plugins/TimestampPlugin.h
+++ b/Plugins/TimestampPlugin.h
@@ -1,75 +1,59 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef TIMESTAMPPLUGIN_H_
-#define TIMESTAMPPLUGIN_H_
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <cassert>
+*/
 
-#include "BasePlugin.h"
-#include "RouteParameters.h"
+#ifndef TIMESTAMP_PLUGIN_H
+#define TIMESTAMP_PLUGIN_H
 
-class TimestampPlugin : public BasePlugin {
-public:
-    TimestampPlugin(QueryObjectsStorage * o) : objects(o) {
-    }
-    std::string GetDescriptor() const { return std::string("timestamp"); }
-    std::string GetVersionString() const { return std::string("0.3 (DL)"); }
-    void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
-        std::string tmp;
+#include "../DataStructures/JSONContainer.h"
+#include "BasePlugin.h"
 
-        //json
-        if("" != routeParameters.jsonpParameter) {
-            reply.content += routeParameters.jsonpParameter;
-            reply.content += "(";
-        }
+#include <string>
 
+template <class DataFacadeT> class TimestampPlugin : public BasePlugin
+{
+  public:
+    explicit TimestampPlugin(const DataFacadeT *facade)
+        : facade(facade), descriptor_string("timestamp")
+    {
+    }
+    const std::string GetDescriptor() const { return descriptor_string; }
+    void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
+    {
         reply.status = http::Reply::ok;
-        reply.content += ("{");
-        reply.content += ("\"version\":0.3,");
-        reply.content += ("\"status\":");
-            reply.content += "0,";
-        reply.content += ("\"timestamp\":\"");
-        reply.content += objects->timestamp;
-        reply.content += "\"";
-        reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON timestamp (v0.3)\"";
-        reply.content += ("}");
-        reply.headers.resize(3);
-        if("" != routeParameters.jsonpParameter) {
-            reply.content += ")";
-            reply.headers[1].name = "Content-Type";
-            reply.headers[1].value = "text/javascript";
-            reply.headers[2].name = "Content-Disposition";
-            reply.headers[2].value = "attachment; filename=\"timestamp.js\"";
-        } else {
-            reply.headers[1].name = "Content-Type";
-            reply.headers[1].value = "application/x-javascript";
-            reply.headers[2].name = "Content-Disposition";
-            reply.headers[2].value = "attachment; filename=\"timestamp.json\"";
-        }
-        reply.headers[0].name = "Content-Length";
-        intToString(reply.content.size(), tmp);
-        reply.headers[0].value = tmp;
+        JSON::Object json_result;
+        json_result.values["status"] = 0;
+        const std::string timestamp = facade->GetTimestamp();
+        json_result.values["timestamp"] = timestamp;
+        JSON::render(reply.content, json_result);
     }
-private:
-    QueryObjectsStorage * objects;
+
+  private:
+    const DataFacadeT *facade;
+    std::string descriptor_string;
 };
 
-#endif /* TIMESTAMPPLUGIN_H_ */
+#endif /* TIMESTAMP_PLUGIN_H */
diff --git a/Plugins/ViaRoutePlugin.h b/Plugins/ViaRoutePlugin.h
index 8249d99..b82d514 100644
--- a/Plugins/ViaRoutePlugin.h
+++ b/Plugins/ViaRoutePlugin.h
@@ -1,224 +1,173 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef VIAROUTEPLUGIN_H_
-#define VIAROUTEPLUGIN_H_
-
-#include <cstdlib>
-#include <fstream>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "BasePlugin.h"
-#include "RouteParameters.h"
-
-#include "../Algorithms/ObjectToBase64.h"
-
-#include "../Descriptors/BaseDescriptor.h"
-#include "../Descriptors/GPXDescriptor.h"
-#include "../Descriptors/JSONDescriptor.h"
-
-#include "../DataStructures/HashTable.h"
-#include "../DataStructures/QueryEdge.h"
-#include "../DataStructures/StaticGraph.h"
-#include "../DataStructures/SearchEngine.h"
-
-#include "../Util/StringUtil.h"
-
-#include "../Server/DataStructures/QueryObjectsStorage.h"
-
-class ViaRoutePlugin : public BasePlugin {
-private:
-    NodeInformationHelpDesk * nodeHelpDesk;
-    std::vector<std::string> & names;
-    StaticGraph<QueryEdge::EdgeData> * graph;
-    HashTable<std::string, unsigned> descriptorTable;
-    std::string pluginDescriptorString;
-    SearchEngine * searchEnginePtr;
-public:
-
-    ViaRoutePlugin(QueryObjectsStorage * objects, std::string psd = "viaroute") : names(objects->names), pluginDescriptorString(psd) {
-        nodeHelpDesk = objects->nodeHelpDesk;
-        graph = objects->graph;
-
-        searchEnginePtr = new SearchEngine(graph, nodeHelpDesk, names);
-
-        descriptorTable.Set("", 0); //default descriptor
-        descriptorTable.Set("json", 0);
-        descriptorTable.Set("gpx", 1);
-    }
-
-    virtual ~ViaRoutePlugin() {
-        delete searchEnginePtr;
-    }
-
-    std::string GetDescriptor() const { return pluginDescriptorString; }
-    std::string GetVersionString() const { return std::string("0.3 (DL)"); }
-    void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
-        //check number of parameters
-        if( 2 > routeParameters.coordinates.size() ) {
-            reply = http::Reply::stockReply(http::Reply::badRequest);
-            return;
-        }
-
-        RawRouteData rawRoute;
-        rawRoute.checkSum = nodeHelpDesk->GetCheckSum();
-        bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum);
-        std::vector<std::string> textCoord;
-        for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
-            if(false == checkCoord(routeParameters.coordinates[i])) {
-                reply = http::Reply::stockReply(http::Reply::badRequest);
-                return;
-            }
-            rawRoute.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]);
-        }
-        std::vector<PhantomNode> phantomNodeVector(rawRoute.rawViaNodeCoordinates.size());
-        for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); ++i) {
-            if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) {
-//                INFO("Decoding hint: " << routeParameters.hints[i] << " for location index " << i);
-                DecodeObjectFromBase64(phantomNodeVector[i], routeParameters.hints[i]);
-                if(phantomNodeVector[i].isValid(nodeHelpDesk->getNumberOfNodes())) {
-//                    INFO("Decoded hint " << i << " successfully");
-                    continue;
-                }
-            }
-//            INFO("Brute force lookup of coordinate " << i);
-            searchEnginePtr->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i], routeParameters.zoomLevel);
-        }
-
-        for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
-            PhantomNodes segmentPhantomNodes;
-            segmentPhantomNodes.startPhantom = phantomNodeVector[i];
-            segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
-            rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
-        }
-        if( ( routeParameters.alternateRoute ) && (1 == rawRoute.segmentEndCoordinates.size()) ) {
-//            INFO("Checking for alternative paths");
-            searchEnginePtr->alternativePaths(rawRoute.segmentEndCoordinates[0],  rawRoute);
-
-        } else {
-            searchEnginePtr->shortestPath(rawRoute.segmentEndCoordinates, rawRoute);
-        }
-
-
-        if(INT_MAX == rawRoute.lengthOfShortestPath ) {
-            DEBUG( "Error occurred, single path not found" );
-        }
-        reply.status = http::Reply::ok;
-
-        //TODO: Move to member as smart pointer
-        BaseDescriptor * desc;
-        if("" != routeParameters.jsonpParameter) {
-            reply.content += routeParameters.jsonpParameter;
-            reply.content += "(";
-        }
-
-        _DescriptorConfig descriptorConfig;
-        unsigned descriptorType = descriptorTable[routeParameters.outputFormat];
-        descriptorConfig.z = routeParameters.zoomLevel;
-        descriptorConfig.instructions = routeParameters.printInstructions;
-        descriptorConfig.geometry = routeParameters.geometry;
-        descriptorConfig.encodeGeometry = routeParameters.compression;
-
-        switch(descriptorType){
-        case 0:
-            desc = new JSONDescriptor();
-
-            break;
-        case 1:
-            desc = new GPXDescriptor();
-
-            break;
-        default:
-            desc = new JSONDescriptor();
-
-            break;
-        }
-
-        PhantomNodes phantomNodes;
-        phantomNodes.startPhantom = rawRoute.segmentEndCoordinates[0].startPhantom;
-//        INFO("Start location: " << phantomNodes.startPhantom.location)
-        phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom;
-//        INFO("TargetLocation: " << phantomNodes.targetPhantom.location);
-//        INFO("Number of segments: " << rawRoute.segmentEndCoordinates.size());
-        desc->SetConfig(descriptorConfig);
-
-        desc->Run(reply, rawRoute, phantomNodes, *searchEnginePtr);
-        if("" != routeParameters.jsonpParameter) {
-            reply.content += ")\n";
-        }
-        reply.headers.resize(3);
-        reply.headers[0].name = "Content-Length";
-        std::string tmp;
-        intToString(reply.content.size(), tmp);
-        reply.headers[0].value = tmp;
-        switch(descriptorType){
-        case 0:
-            if("" != routeParameters.jsonpParameter){
-                reply.headers[1].name = "Content-Type";
-                reply.headers[1].value = "text/javascript";
-                reply.headers[2].name = "Content-Disposition";
-                reply.headers[2].value = "attachment; filename=\"route.js\"";
-            } else {
-                reply.headers[1].name = "Content-Type";
-                reply.headers[1].value = "application/x-javascript";
-                reply.headers[2].name = "Content-Disposition";
-                reply.headers[2].value = "attachment; filename=\"route.json\"";
-            }
-
-            break;
-        case 1:
-            reply.headers[1].name = "Content-Type";
-            reply.headers[1].value = "application/gpx+xml; charset=UTF-8";
-            reply.headers[2].name = "Content-Disposition";
-            reply.headers[2].value = "attachment; filename=\"route.gpx\"";
-
-            break;
-        default:
-            if("" != routeParameters.jsonpParameter){
-                reply.headers[1].name = "Content-Type";
-                reply.headers[1].value = "text/javascript";
-                reply.headers[2].name = "Content-Disposition";
-                reply.headers[2].value = "attachment; filename=\"route.js\"";
-            } else {
-                reply.headers[1].name = "Content-Type";
-                reply.headers[1].value = "application/x-javascript";
-                reply.headers[2].name = "Content-Disposition";
-                reply.headers[2].value = "attachment; filename=\"route.json\"";
-            }
-
-            break;
-        }
-
-        delete desc;
-        return;
-    }
-private:
-    inline bool checkCoord(const _Coordinate & c) {
-        if(c.lat > 90*100000 || c.lat < -90*100000 || c.lon > 180*100000 || c.lon <-180*100000) {
-            return false;
-        }
-        return true;
-    }
-};
-
-
-#endif /* VIAROUTEPLUGIN_H_ */
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef VIA_ROUTE_PLUGIN_H
+#define VIA_ROUTE_PLUGIN_H
+
+#include "BasePlugin.h"
+
+#include "../Algorithms/ObjectToBase64.h"
+
+#include "../DataStructures/QueryEdge.h"
+#include "../DataStructures/SearchEngine.h"
+#include "../Descriptors/BaseDescriptor.h"
+#include "../Descriptors/GPXDescriptor.h"
+#include "../Descriptors/JSONDescriptor.h"
+#include "../Util/SimpleLogger.h"
+#include "../Util/StringUtil.h"
+#include "../Util/TimingUtil.h"
+
+#include <cstdlib>
+
+#include <algorithm>
+#include <memory>
+#include <unordered_map>
+#include <string>
+#include <vector>
+
+template <class DataFacadeT> class ViaRoutePlugin : public BasePlugin
+{
+  private:
+    std::unordered_map<std::string, unsigned> descriptor_table;
+    std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
+
+  public:
+    explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade)
+    {
+        search_engine_ptr = std::make_shared<SearchEngine<DataFacadeT>>(facade);
+
+        descriptor_table.emplace("json", 0);
+        descriptor_table.emplace("gpx", 1);
+        // descriptor_table.emplace("geojson", 2);
+    }
+
+    virtual ~ViaRoutePlugin() {}
+
+    const std::string GetDescriptor() const { return descriptor_string; }
+
+    void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
+    {
+        // check number of parameters
+        if (2 > route_parameters.coordinates.size() ||
+            std::any_of(begin(route_parameters.coordinates),
+                        end(route_parameters.coordinates),
+                        [&](FixedPointCoordinate coordinate)
+                        { return !coordinate.isValid(); }))
+        {
+            reply = http::Reply::StockReply(http::Reply::badRequest);
+            return;
+        }
+
+        RawRouteData raw_route;
+        raw_route.check_sum = facade->GetCheckSum();
+        for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
+        {
+            raw_route.raw_via_node_coordinates.emplace_back(coordinate);
+        }
+
+        std::vector<PhantomNode> phantom_node_vector(raw_route.raw_via_node_coordinates.size());
+        const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
+
+        for (unsigned i = 0; i < raw_route.raw_via_node_coordinates.size(); ++i)
+        {
+            if (checksum_OK && i < route_parameters.hints.size() &&
+                !route_parameters.hints[i].empty())
+            {
+                DecodeObjectFromBase64(route_parameters.hints[i], phantom_node_vector[i]);
+                if (phantom_node_vector[i].isValid(facade->GetNumberOfNodes()))
+                {
+                    continue;
+                }
+            }
+            facade->FindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
+                                                 phantom_node_vector[i],
+                                                 route_parameters.zoom_level);
+        }
+
+        PhantomNodes current_phantom_node_pair;
+        for (unsigned i = 0; i < phantom_node_vector.size() - 1; ++i)
+        {
+            current_phantom_node_pair.source_phantom = phantom_node_vector[i];
+            current_phantom_node_pair.target_phantom = phantom_node_vector[i + 1];
+            raw_route.segment_end_coordinates.emplace_back(current_phantom_node_pair);
+        }
+
+        const bool is_alternate_requested = route_parameters.alternate_route;
+        const bool is_only_one_segment = (1 == raw_route.segment_end_coordinates.size());
+        if (is_alternate_requested && is_only_one_segment)
+        {
+            search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
+                                                raw_route);
+        }
+        else
+        {
+            search_engine_ptr->shortest_path(raw_route.segment_end_coordinates, raw_route);
+        }
+
+        if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
+        {
+            SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
+        }
+        reply.status = http::Reply::ok;
+
+        DescriptorConfig descriptor_config;
+
+        auto iter = descriptor_table.find(route_parameters.output_format);
+        unsigned descriptor_type = (iter != descriptor_table.end() ? iter->second : 0);
+
+        descriptor_config.zoom_level = route_parameters.zoom_level;
+        descriptor_config.instructions = route_parameters.print_instructions;
+        descriptor_config.geometry = route_parameters.geometry;
+        descriptor_config.encode_geometry = route_parameters.compression;
+
+        std::shared_ptr<BaseDescriptor<DataFacadeT>> descriptor;
+        switch (descriptor_type)
+        {
+        // case 0:
+        //     descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>();
+        //     break;
+        case 1:
+            descriptor = std::make_shared<GPXDescriptor<DataFacadeT>>(facade);
+            break;
+        // case 2:
+        //      descriptor = std::make_shared<GEOJSONDescriptor<DataFacadeT>>();
+        //      break;
+        default:
+            descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>(facade);
+            break;
+        }
+
+        descriptor->SetConfig(descriptor_config);
+        descriptor->Run(raw_route, reply);
+    }
+
+  private:
+    std::string descriptor_string;
+    DataFacadeT *facade;
+};
+
+#endif // VIA_ROUTE_PLUGIN_H
diff --git a/README.TXT b/README.md
similarity index 52%
rename from README.TXT
rename to README.md
index a8ae177..1c77f72 100644
--- a/README.TXT
+++ b/README.md
@@ -1,3 +1,5 @@
+# Readme
+
 For instructions on how to compile and run OSRM, please consult the Wiki at
 
 https://github.com/DennisOSRM/Project-OSRM/wiki
@@ -6,8 +8,11 @@ or use our free and daily updated online service at
 
 http://map.project-osrm.org
 
-When using the code in a scientific publication, please cite
+## References in publications
+
+When using the code in a (scientific) publication, please cite
 
+```
 @inproceedings{luxen-vetter-2011,
  author = {Luxen, Dennis and Vetter, Christian},
  title = {Real-time routing with OpenStreetMap data},
@@ -23,5 +28,13 @@ When using the code in a scientific publication, please cite
  acmid = {2094062},
  publisher = {ACM},
  address = {New York, NY, USA},
-} 
+}
+```
+
+## Current build status
 
+| build config |  branch | status |
+|:-------------|:--------|:------------|
+| Project OSRM | master  | [![Build Status](https://travis-ci.org/DennisOSRM/Project-OSRM.png?branch=master)](https://travis-ci.org/DennisOSRM/Project-OSRM) |
+| Project OSRM | develop | [![Build Status](https://travis-ci.org/DennisOSRM/Project-OSRM.png?branch=develop)](https://travis-ci.org/DennisOSRM/Project-OSRM) |
+| LUAbind fork | master  | [![Build Status](https://travis-ci.org/DennisOSRM/luabind.png?branch=master)](https://travis-ci.org/DennisOSRM/luabind) |
diff --git a/Rakefile b/Rakefile
index ccbb0cb..1c2ce9d 100644
--- a/Rakefile
+++ b/Rakefile
@@ -6,7 +6,7 @@ require 'sys/proctable'
 
 BUILD_FOLDER = 'build'
 DATA_FOLDER = 'sandbox'
-PROFILE = 'bicycle'
+PROFILE = 'examples/postgis'
 OSRM_PORT = 5000
 PROFILES_FOLDER = '../profiles'
 
@@ -59,47 +59,27 @@ def wait_for_shutdown name
   raise "*** Could not terminate #{name}."
 end
 
-def write_server_ini osm_file
-  s=<<-EOF
-  Threads = 1
-  IP = 0.0.0.0
-  Port = #{OSRM_PORT}
-
-  hsgrData=#{osm_file}.osrm.hsgr
-  nodesData=#{osm_file}.osrm.nodes
-  edgesData=#{osm_file}.osrm.edges
-  ramIndex=#{osm_file}.osrm.ramIndex
-  fileIndex=#{osm_file}.osrm.fileIndex
-  namesData=#{osm_file}.osrm.names
-  timestamp=#{osm_file}.osrm.timestamp
-  EOF
-  File.open( 'server.ini', 'w') {|f| f.write( s ) }
-end
-
 
 desc "Rebuild and run tests."
 task :default => [:build]
 
 desc "Build using CMake."
 task :build do
-  Dir.chdir BUILD_FOLDER do
-    system "make"
+  if Dir.exists? BUILD_FOLDER
+    Dir.chdir BUILD_FOLDER do
+      system "make"
+    end
+  else
+    system "mkdir build; cd build; cmake ..; make"
   end
 end
 
 desc "Setup config files."
 task :setup do
-  Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}"
-  ['server.ini','extractor.ini','contractor.ini'].each do |file|
-    unless File.exist? "#{DATA_FOLDER}/#{file}"
-      puts "Copying #{file} template to #{DATA_FOLDER}/#{file}" 
-      FileUtils.cp file, "#{DATA_FOLDER}/#{file}"
-    end
-  end
 end
 
 desc "Download OSM data."
-task :download => :setup do
+task :download do
   Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}"
   puts "Downloading..."
   puts "curl http://download.geofabrik.de/europe/#{osm_data_country}-latest.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
@@ -118,26 +98,20 @@ task :crop do
 end
 
 desc "Reprocess OSM data."
-task :process => :setup do
-  Dir.chdir DATA_FOLDER do
-    raise "Error while extracting data." unless system "../#{BUILD_FOLDER}/osrm-extract #{osm_data_area_name}.osm.pbf #{PROFILES_FOLDER}/#{PROFILE}.lua"
-    puts
-    raise "Error while preparing data." unless system "../#{BUILD_FOLDER}/osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions #{PROFILES_FOLDER}/#{PROFILE}.lua"
-    puts
-  end
+task :process => [:extract,:prepare] do
 end
 
 desc "Extract OSM data."
-task :extract => :setup do
+task :extract do
   Dir.chdir DATA_FOLDER do
-    raise "Error while extracting data." unless system "../#{BUILD_FOLDER}/osrm-extract #{osm_data_area_name}.osm.pbf ../profiles/#{PROFILE}.lua"
+    raise "Error while extracting data." unless system "../#{BUILD_FOLDER}/osrm-extract #{osm_data_area_name}.osm.pbf --profile ../profiles/#{PROFILE}.lua"
   end
 end
 
 desc "Prepare OSM data."
-task :prepare => :setup do
+task :prepare do
   Dir.chdir DATA_FOLDER do
-    raise "Error while preparing data." unless system "../#{BUILD_FOLDER}/osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions ../profiles/#{PROFILE}.lua"
+    raise "Error while preparing data." unless system "../#{BUILD_FOLDER}/osrm-prepare #{osm_data_area_name}.osrm --profile ../profiles/#{PROFILE}.lua"
   end
 end
 
@@ -154,19 +128,17 @@ task :test do
 end
 
 desc "Run the routing server in the terminal. Press Ctrl-C to stop."
-task :run => :setup do
+task :run do
   Dir.chdir DATA_FOLDER do
-    write_server_ini osm_data_area_name
-    system "../#{BUILD_FOLDER}/osrm-routed"
+    system "../#{BUILD_FOLDER}/osrm-routed #{osm_data_area_name}.osrm --port #{OSRM_PORT}"
   end
 end
 
 desc "Launch the routing server in the background. Use rake:down to stop it."
-task :up => :setup do
+task :up do
   Dir.chdir DATA_FOLDER do
     abort("Already up.") if up?
-    write_server_ini osm_data_area_name
-    pipe = IO.popen("../#{BUILD_FOLDER}/osrm-routed 1>>osrm-routed.log 2>>osrm-routed.log")
+    pipe = IO.popen("../#{BUILD_FOLDER}/osrm-routed #{osm_data_area_name}.osrm --port #{OSRM_PORT} 1>>osrm-routed.log 2>>osrm-routed.log")
     timeout = 5
     (timeout*10).times do
       begin
diff --git a/RoutingAlgorithms/AlternativePathRouting.h b/RoutingAlgorithms/AlternativePathRouting.h
index 4cd256b..3506f93 100644
--- a/RoutingAlgorithms/AlternativePathRouting.h
+++ b/RoutingAlgorithms/AlternativePathRouting.h
@@ -1,535 +1,858 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef ALTERNATIVEROUTES_H_
-#define ALTERNATIVEROUTES_H_
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <boost/unordered_map.hpp>
-#include <vector>
-#include <cmath>
+*/
+
+#ifndef ALTERNATIVE_PATH_ROUTING_H
+#define ALTERNATIVE_PATH_ROUTING_H
 
 #include "BasicRoutingInterface.h"
+#include "../DataStructures/SearchEngineData.h"
+
+#include <boost/assert.hpp>
+
+#include <unordered_map>
+#include <vector>
 
-const double VIAPATH_ALPHA   = 0.15;
-const double VIAPATH_EPSILON = 0.10; //alternative at most 15% longer
-const double VIAPATH_GAMMA   = 0.75; //alternative shares at most 75% with the shortest.
+const double VIAPATH_ALPHA = 0.10;
+const double VIAPATH_EPSILON = 0.15; // alternative at most 15% longer
+const double VIAPATH_GAMMA = 0.75;   // alternative shares at most 75% with the shortest.
 
-template<class QueryDataT>
-class AlternativeRouting : private BasicRoutingInterface<QueryDataT> {
-    typedef BasicRoutingInterface<QueryDataT> super;
-    typedef typename QueryDataT::Graph SearchGraph;
-    typedef typename QueryDataT::QueryHeap QueryHeap;
+template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInterface<DataFacadeT>
+{
+    typedef BasicRoutingInterface<DataFacadeT> super;
+    typedef typename DataFacadeT::EdgeData EdgeData;
+    typedef SearchEngineData::QueryHeap QueryHeap;
     typedef std::pair<NodeID, NodeID> SearchSpaceEdge;
 
-    struct RankedCandidateNode {
-        RankedCandidateNode(const NodeID n, const int l, const int s) : node(n), length(l), sharing(s) {}
+    struct RankedCandidateNode
+    {
+        RankedCandidateNode(const NodeID node, const int length, const int sharing)
+            : node(node), length(length), sharing(sharing)
+        {
+        }
+
         NodeID node;
         int length;
         int sharing;
-        bool operator<(const RankedCandidateNode& other) const {
-            return (2*length + sharing) < (2*other.length + other.sharing);
+
+        bool operator<(const RankedCandidateNode &other) const
+        {
+            return (2 * length + sharing) < (2 * other.length + other.sharing);
         }
     };
+    DataFacadeT *facade;
+    SearchEngineData &engine_working_data;
 
-    const SearchGraph * search_graph;
-
-public:
-
-    AlternativeRouting(QueryDataT & qd) : super(qd), search_graph(qd.graph) { }
-
-    ~AlternativeRouting() {}
+  public:
+    AlternativeRouting(DataFacadeT *facade, SearchEngineData &engine_working_data)
+        : super(facade), facade(facade), engine_working_data(engine_working_data)
+    {
+    }
 
-    void operator()(const PhantomNodes & phantomNodePair, RawRouteData & rawRouteData) {
-        if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX() || phantomNodePair.PhantomNodesHaveEqualLocation()) {
-            rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
-            return;
-        }
+    virtual ~AlternativeRouting() {}
 
-        std::vector<NodeID> alternativePath;
-        std::vector<NodeID> viaNodeCandidates;
+    void operator()(const PhantomNodes &phantom_node_pair, RawRouteData &raw_route_data)
+    {
+        std::vector<NodeID> alternative_path;
+        std::vector<NodeID> via_node_candidate_list;
         std::vector<SearchSpaceEdge> forward_search_space;
         std::vector<SearchSpaceEdge> reverse_search_space;
 
-        //Initialize Queues, semi-expensive because access to TSS invokes a system call
-        super::_queryData.InitializeOrClearFirstThreadLocalStorage();
-        super::_queryData.InitializeOrClearSecondThreadLocalStorage();
-        super::_queryData.InitializeOrClearThirdThreadLocalStorage();
-
-        QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap);
-        QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap);
-        QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2);
-        QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2);
-
-        int upper_bound_to_shortest_path_distance = INT_MAX;
-        NodeID middle_node = UINT_MAX;
-        forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
-        if(phantomNodePair.startPhantom.isBidirected() ) {
-            forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
-        }
-        reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
-        if(phantomNodePair.targetPhantom.isBidirected() ) {
-        	reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
-        }
-
-        const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
-        const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0);
-
-        //exploration dijkstra from nodes s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
-        while(0 < (forward_heap1.Size() + reverse_heap1.Size())){
-            if(0 < forward_heap1.Size()){
-                AlternativeRoutingStep<true >(forward_heap1, reverse_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, forward_search_space, forward_offset);
+        // Init queues, semi-expensive because access to TSS invokes a sys-call
+        engine_working_data.InitializeOrClearFirstThreadLocalStorage(
+            super::facade->GetNumberOfNodes());
+        engine_working_data.InitializeOrClearSecondThreadLocalStorage(
+            super::facade->GetNumberOfNodes());
+        engine_working_data.InitializeOrClearThirdThreadLocalStorage(
+            super::facade->GetNumberOfNodes());
+
+        QueryHeap &forward_heap1 = *(engine_working_data.forwardHeap);
+        QueryHeap &reverse_heap1 = *(engine_working_data.backwardHeap);
+        QueryHeap &forward_heap2 = *(engine_working_data.forwardHeap2);
+        QueryHeap &reverse_heap2 = *(engine_working_data.backwardHeap2);
+
+        int upper_bound_to_shortest_path_distance = INVALID_EDGE_WEIGHT;
+        NodeID middle_node = SPECIAL_NODEID;
+        if (phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID)
+        {
+            // SimpleLogger().Write(logDEBUG) << "fwd-a insert: " <<
+            // phantom_node_pair.source_phantom.forward_node_id << ", w: " <<
+            // -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset();
+            forward_heap1.Insert(phantom_node_pair.source_phantom.forward_node_id,
+                                 -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
+                                 phantom_node_pair.source_phantom.forward_node_id);
+        }
+        if (phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID)
+        {
+            // SimpleLogger().Write(logDEBUG) << "fwd-b insert: " <<
+            // phantom_node_pair.source_phantom.reverse_node_id << ", w: " <<
+            // -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset();
+            forward_heap1.Insert(phantom_node_pair.source_phantom.reverse_node_id,
+                                 -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
+                                 phantom_node_pair.source_phantom.reverse_node_id);
+        }
+
+        if (phantom_node_pair.target_phantom.forward_node_id != SPECIAL_NODEID)
+        {
+            // SimpleLogger().Write(logDEBUG) << "rev-a insert: " <<
+            // phantom_node_pair.target_phantom.forward_node_id << ", w: " <<
+            // phantom_node_pair.target_phantom.GetForwardWeightPlusOffset();
+            reverse_heap1.Insert(phantom_node_pair.target_phantom.forward_node_id,
+                                 phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(),
+                                 phantom_node_pair.target_phantom.forward_node_id);
+        }
+        if (phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID)
+        {
+            // SimpleLogger().Write(logDEBUG) << "rev-b insert: " <<
+            // phantom_node_pair.target_phantom.reverse_node_id << ", w: " <<
+            // phantom_node_pair.target_phantom.GetReverseWeightPlusOffset();
+            reverse_heap1.Insert(phantom_node_pair.target_phantom.reverse_node_id,
+                                 phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(),
+                                 phantom_node_pair.target_phantom.reverse_node_id);
+        }
+
+        // search from s and t till new_min/(1+epsilon) > length_of_shortest_path
+        while (0 < (forward_heap1.Size() + reverse_heap1.Size()))
+        {
+            if (0 < forward_heap1.Size())
+            {
+                AlternativeRoutingStep<true>(forward_heap1,
+                                             reverse_heap1,
+                                             &middle_node,
+                                             &upper_bound_to_shortest_path_distance,
+                                             via_node_candidate_list,
+                                             forward_search_space);
             }
-            if(0 < reverse_heap1.Size()){
-                AlternativeRoutingStep<false>(reverse_heap1, forward_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, reverse_search_space, reverse_offset);
+            if (0 < reverse_heap1.Size())
+            {
+                AlternativeRoutingStep<false>(reverse_heap1,
+                                              forward_heap1,
+                                              &middle_node,
+                                              &upper_bound_to_shortest_path_distance,
+                                              via_node_candidate_list,
+                                              reverse_search_space);
             }
         }
-        sort_unique_resize(viaNodeCandidates);
+
+        if (INVALID_EDGE_WEIGHT == upper_bound_to_shortest_path_distance)
+        {
+            return;
+        }
+
+        sort_unique_resize(via_node_candidate_list);
 
         std::vector<NodeID> packed_forward_path;
         std::vector<NodeID> packed_reverse_path;
 
         super::RetrievePackedPathFromSingleHeap(forward_heap1, middle_node, packed_forward_path);
         super::RetrievePackedPathFromSingleHeap(reverse_heap1, middle_node, packed_reverse_path);
-        boost::unordered_map<NodeID, int> approximated_forward_sharing;
-        boost::unordered_map<NodeID, int> approximated_reverse_sharing;
+
+        std::unordered_map<NodeID, int> approximated_forward_sharing;
+        std::unordered_map<NodeID, int> approximated_reverse_sharing;
 
         unsigned index_into_forward_path = 0;
-        //sweep over search space, compute forward sharing for each current edge (u,v)
-        BOOST_FOREACH(const SearchSpaceEdge & current_edge, forward_search_space) {
-        	const NodeID u = current_edge.first;
-        	const NodeID v = current_edge.second;
-        	if(packed_forward_path.size() < index_into_forward_path && current_edge == forward_search_space[index_into_forward_path]) {
-        		//current_edge is on shortest path => sharing(u):=queue.GetKey(u);
-        		++index_into_forward_path;
-        		approximated_forward_sharing[v] = forward_heap1.GetKey(u);
-        	} else {
-        		//sharing (s) = sharing (t)
-        		approximated_forward_sharing[v] = approximated_forward_sharing[u];
-        	}
+        // sweep over search space, compute forward sharing for each current edge (u,v)
+        for (const SearchSpaceEdge &current_edge : forward_search_space)
+        {
+            const NodeID u = current_edge.first;
+            const NodeID v = current_edge.second;
+            if ((packed_forward_path.size() < index_into_forward_path) &&
+                (current_edge == forward_search_space[index_into_forward_path]))
+            {
+                // current_edge is on shortest path => sharing(u):=queue.GetKey(u);
+                ++index_into_forward_path;
+                approximated_forward_sharing[v] = forward_heap1.GetKey(u);
+            }
+            else
+            {
+                // sharing (s) = sharing (t)
+                approximated_forward_sharing[v] = approximated_forward_sharing[u];
+            }
         }
 
         unsigned index_into_reverse_path = 0;
-        //sweep over search space, compute backward sharing
-        BOOST_FOREACH(const SearchSpaceEdge & current_edge, reverse_search_space) {
-        	const NodeID u = current_edge.first;
-        	const NodeID v = current_edge.second;
-        	if(packed_reverse_path.size() < index_into_reverse_path && current_edge == reverse_search_space[index_into_reverse_path]) {
-        		//current_edge is on shortest path => sharing(u):=queue.GetKey(u);
-        		++index_into_reverse_path;
-        		approximated_reverse_sharing[v] = reverse_heap1.GetKey(u);
-        	} else {
-        		//sharing (s) = sharing (t)
-        		approximated_reverse_sharing[v] = approximated_reverse_sharing[u];
-        	}
-        }
-        std::vector<NodeID> nodes_that_passed_preselection;
-        BOOST_FOREACH(const NodeID node, viaNodeCandidates) {
-            int approximated_sharing = approximated_forward_sharing[node] + approximated_reverse_sharing[node];
-            int approximated_length = forward_heap1.GetKey(node)+reverse_heap1.GetKey(node);
-            bool lengthPassed = (approximated_length < upper_bound_to_shortest_path_distance*(1+VIAPATH_EPSILON));
-            bool sharingPassed = (approximated_sharing <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA);
-            bool stretchPassed = approximated_length - approximated_sharing < (1.+VIAPATH_EPSILON)*(upper_bound_to_shortest_path_distance-approximated_sharing);
-
-            if(lengthPassed && sharingPassed && stretchPassed) {
-                nodes_that_passed_preselection.push_back(node);
+        // sweep over search space, compute backward sharing
+        for (const SearchSpaceEdge &current_edge : reverse_search_space)
+        {
+            const NodeID u = current_edge.first;
+            const NodeID v = current_edge.second;
+            if ((packed_reverse_path.size() < index_into_reverse_path) &&
+                (current_edge == reverse_search_space[index_into_reverse_path]))
+            {
+                // current_edge is on shortest path => sharing(u):=queue.GetKey(u);
+                ++index_into_reverse_path;
+                approximated_reverse_sharing[v] = reverse_heap1.GetKey(u);
+            }
+            else
+            {
+                // sharing (s) = sharing (t)
+                const auto rev_iterator = approximated_reverse_sharing.find(u);
+                const int rev_sharing =
+                    (rev_iterator != approximated_reverse_sharing.end()) ? rev_iterator->second : 0;
+                approximated_reverse_sharing[v] = rev_sharing;
             }
         }
 
-        std::vector<NodeID> & packedShortestPath = packed_forward_path;
-        std::reverse(packedShortestPath.begin(), packedShortestPath.end());
-        packedShortestPath.push_back(middle_node);
-        packedShortestPath.insert(packedShortestPath.end(),packed_reverse_path.begin(), packed_reverse_path.end());
-        std::vector<RankedCandidateNode > rankedCandidates;
-
-        //prioritizing via nodes for deep inspection
-        BOOST_FOREACH(const NodeID node, nodes_that_passed_preselection) {
-            int lengthOfViaPath = 0, sharingOfViaPath = 0;
-            computeLengthAndSharingOfViaPath(node, &lengthOfViaPath, &sharingOfViaPath, forward_offset+reverse_offset, packedShortestPath);
-            if(sharingOfViaPath <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA) {
-                rankedCandidates.push_back(RankedCandidateNode(node, lengthOfViaPath, sharingOfViaPath));
+        // SimpleLogger().Write(logDEBUG) << "fwd_search_space size: " <<
+        // forward_search_space.size() << ", marked " << approximated_forward_sharing.size() << "
+        // nodes";
+        // SimpleLogger().Write(logDEBUG) << "rev_search_space size: " <<
+        // reverse_search_space.size() << ", marked " << approximated_reverse_sharing.size() << "
+        // nodes";
+
+        std::vector<NodeID> preselected_node_list;
+        for (const NodeID node : via_node_candidate_list)
+        {
+            const auto fwd_iterator = approximated_forward_sharing.find(node);
+            const int fwd_sharing =
+                (fwd_iterator != approximated_forward_sharing.end()) ? fwd_iterator->second : 0;
+            const auto rev_iterator = approximated_reverse_sharing.find(node);
+            const int rev_sharing =
+                (rev_iterator != approximated_reverse_sharing.end()) ? rev_iterator->second : 0;
+
+            const int approximated_sharing = fwd_sharing + rev_sharing;
+            const int approximated_length = forward_heap1.GetKey(node) + reverse_heap1.GetKey(node);
+            const bool length_passes =
+                (approximated_length <
+                 upper_bound_to_shortest_path_distance * (1 + VIAPATH_EPSILON));
+            const bool sharing_passes =
+                (approximated_sharing <= upper_bound_to_shortest_path_distance * VIAPATH_GAMMA);
+            const bool stretch_passes =
+                (approximated_length - approximated_sharing) <
+                ((1. + VIAPATH_ALPHA) *
+                 (upper_bound_to_shortest_path_distance - approximated_sharing));
+
+            if (length_passes && sharing_passes && stretch_passes)
+            {
+                preselected_node_list.emplace_back(node);
             }
         }
-        std::sort(rankedCandidates.begin(), rankedCandidates.end());
 
-        NodeID selectedViaNode = UINT_MAX;
-        int lengthOfViaPath = INT_MAX;
-        NodeID s_v_middle = UINT_MAX, v_t_middle = UINT_MAX;
-        BOOST_FOREACH(const RankedCandidateNode & candidate, rankedCandidates){
-            if(viaNodeCandidatePasses_T_Test(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, candidate, forward_offset+reverse_offset, upper_bound_to_shortest_path_distance, &lengthOfViaPath, &s_v_middle, &v_t_middle)) {
+        // SimpleLogger().Write() << preselected_node_list.size() << " passed preselection";
+
+        std::vector<NodeID> &packed_shortest_path = packed_forward_path;
+        std::reverse(packed_shortest_path.begin(), packed_shortest_path.end());
+        packed_shortest_path.emplace_back(middle_node);
+        packed_shortest_path.insert(
+            packed_shortest_path.end(), packed_reverse_path.begin(), packed_reverse_path.end());
+        std::vector<RankedCandidateNode> ranked_candidates_list;
+
+        // prioritizing via nodes for deep inspection
+        for (const NodeID node : preselected_node_list)
+        {
+            int length_of_via_path = 0, sharing_of_via_path = 0;
+            ComputeLengthAndSharingOfViaPath(
+                node, &length_of_via_path, &sharing_of_via_path, packed_shortest_path);
+            const int maximum_allowed_sharing = static_cast<int>(
+                upper_bound_to_shortest_path_distance * VIAPATH_GAMMA);
+            if (sharing_of_via_path <= maximum_allowed_sharing &&
+                length_of_via_path <= upper_bound_to_shortest_path_distance * (1 + VIAPATH_EPSILON))
+            {
+                ranked_candidates_list.emplace_back(node, length_of_via_path, sharing_of_via_path);
+            }
+        }
+        std::sort(ranked_candidates_list.begin(), ranked_candidates_list.end());
+
+        NodeID selected_via_node = SPECIAL_NODEID;
+        int length_of_via_path = INVALID_EDGE_WEIGHT;
+        NodeID s_v_middle = SPECIAL_NODEID, v_t_middle = SPECIAL_NODEID;
+        for (const RankedCandidateNode &candidate : ranked_candidates_list)
+        {
+            if (ViaNodeCandidatePassesTTest(forward_heap1,
+                                            reverse_heap1,
+                                            forward_heap2,
+                                            reverse_heap2,
+                                            candidate,
+                                            upper_bound_to_shortest_path_distance,
+                                            &length_of_via_path,
+                                            &s_v_middle,
+                                            &v_t_middle))
+            {
                 // select first admissable
-                selectedViaNode = candidate.node;
+                selected_via_node = candidate.node;
                 break;
             }
         }
 
-        //Unpack shortest path and alternative, if they exist
-        if(INT_MAX != upper_bound_to_shortest_path_distance) {
-            super::UnpackPath(packedShortestPath, rawRouteData.computedShortestPath);
-            rawRouteData.lengthOfShortestPath = upper_bound_to_shortest_path_distance;
+        // Unpack shortest path and alternative, if they exist
+        if (INVALID_EDGE_WEIGHT != upper_bound_to_shortest_path_distance)
+        {
+            BOOST_ASSERT(!packed_shortest_path.empty());
+            raw_route_data.unpacked_path_segments.resize(1);
+            raw_route_data.source_traversed_in_reverse.push_back(
+                (packed_shortest_path.front() != phantom_node_pair.source_phantom.forward_node_id));
+            raw_route_data.target_traversed_in_reverse.push_back(
+                (packed_shortest_path.back() != phantom_node_pair.target_phantom.forward_node_id));
+
+            super::UnpackPath(
+                // -- packed input
+                packed_shortest_path,
+                // -- start of route
+                phantom_node_pair,
+                // -- unpacked output
+                raw_route_data.unpacked_path_segments.front());
+            raw_route_data.shortest_path_length = upper_bound_to_shortest_path_distance;
+        }
+
+        if (SPECIAL_NODEID != selected_via_node)
+        {
+            std::vector<NodeID> packed_alternate_path;
+            // retrieve alternate path
+            RetrievePackedAlternatePath(forward_heap1,
+                                        reverse_heap1,
+                                        forward_heap2,
+                                        reverse_heap2,
+                                        s_v_middle,
+                                        v_t_middle,
+                                        packed_alternate_path);
+
+            raw_route_data.alt_source_traversed_in_reverse.push_back(
+                (packed_alternate_path.front() != phantom_node_pair.source_phantom.forward_node_id));
+            raw_route_data.alt_target_traversed_in_reverse.push_back(
+                (packed_alternate_path.back() != phantom_node_pair.target_phantom.forward_node_id));
+
+            // unpack the alternate path
+            super::UnpackPath(
+                packed_alternate_path, phantom_node_pair, raw_route_data.unpacked_alternative);
+
+            raw_route_data.alternative_path_length = length_of_via_path;
         } else {
-            rawRouteData.lengthOfShortestPath = INT_MAX;
-        }
-
-        if(selectedViaNode != UINT_MAX) {
-            retrievePackedViaPath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, s_v_middle, v_t_middle, rawRouteData.computedAlternativePath);
-            rawRouteData.lengthOfAlternativePath = lengthOfViaPath;
-        } else {
-            rawRouteData.lengthOfAlternativePath = INT_MAX;
+            BOOST_ASSERT(raw_route_data.alternative_path_length == INVALID_EDGE_WEIGHT);
         }
     }
 
-private:
-    //unpack <s,..,v,..,t> by exploring search spaces from v
-    inline void retrievePackedViaPath(QueryHeap & _forwardHeap1, QueryHeap & _backwardHeap1, QueryHeap & _forwardHeap2, QueryHeap & _backwardHeap2,
-            const NodeID s_v_middle, const NodeID v_t_middle, std::vector<_PathData> & unpackedPath) {
-        //unpack [s,v)
-        std::vector<NodeID> packed_s_v_path, packed_v_t_path;
-        super::RetrievePackedPathFromHeap(_forwardHeap1, _backwardHeap2, s_v_middle, packed_s_v_path);
-        packed_s_v_path.resize(packed_s_v_path.size()-1);
-        //unpack [v,t]
-        super::RetrievePackedPathFromHeap(_forwardHeap2, _backwardHeap1, v_t_middle, packed_v_t_path);
-        packed_s_v_path.insert(packed_s_v_path.end(),packed_v_t_path.begin(), packed_v_t_path.end() );
-        super::UnpackPath(packed_s_v_path, unpackedPath);
+  private:
+    // unpack alternate <s,..,v,..,t> by exploring search spaces from v
+    inline void RetrievePackedAlternatePath(const QueryHeap &forward_heap1,
+                                            const QueryHeap &reverse_heap1,
+                                            const QueryHeap &forward_heap2,
+                                            const QueryHeap &reverse_heap2,
+                                            const NodeID s_v_middle,
+                                            const NodeID v_t_middle,
+                                            std::vector<NodeID> &packed_path) const
+    {
+        // fetch packed path [s,v)
+        std::vector<NodeID> packed_v_t_path;
+        super::RetrievePackedPathFromHeap(forward_heap1, reverse_heap2, s_v_middle, packed_path);
+        packed_path.pop_back(); // remove middle node. It's in both half-paths
+
+        // fetch patched path [v,t]
+        super::RetrievePackedPathFromHeap(
+            forward_heap2, reverse_heap1, v_t_middle, packed_v_t_path);
+
+        packed_path.insert(packed_path.end(), packed_v_t_path.begin(), packed_v_t_path.end());
     }
 
-    inline void computeLengthAndSharingOfViaPath(const NodeID via_node, int *real_length_of_via_path, int *sharing_of_via_path,
-            const int offset, const std::vector<NodeID> & packed_shortest_path) {
-        //compute and unpack <s,..,v> and <v,..,t> by exploring search spaces from v and intersecting against queues
-        //only half-searches have to be done at this stage
-        super::_queryData.InitializeOrClearSecondThreadLocalStorage();
-
-        QueryHeap & existingForwardHeap  = *super::_queryData.forwardHeap;
-        QueryHeap & existingBackwardHeap = *super::_queryData.backwardHeap;
-        QueryHeap & newForwardHeap       = *super::_queryData.forwardHeap2;
-        QueryHeap & newBackwardHeap      = *super::_queryData.backwardHeap2;
-
-        std::vector < NodeID > packed_s_v_path;
-        std::vector < NodeID > packed_v_t_path;
-
-        std::vector<NodeID> partiallyUnpackedShortestPath;
-        std::vector<NodeID> partiallyUnpackedViaPath;
-
-        NodeID s_v_middle = UINT_MAX;
-        int upperBoundFor_s_v_Path = INT_MAX;//compute path <s,..,v> by reusing forward search from s
-        newBackwardHeap.Insert(via_node, 0, via_node);
-        while (0 < newBackwardHeap.Size()) {
-            super::RoutingStep(newBackwardHeap, existingForwardHeap, &s_v_middle, &upperBoundFor_s_v_Path, 2 * offset, false);
-        }
-        //compute path <v,..,t> by reusing backward search from node t
-        NodeID v_t_middle = UINT_MAX;
-        int upperBoundFor_v_t_Path = INT_MAX;
-        newForwardHeap.Insert(via_node, 0, via_node);
-        while (0 < newForwardHeap.Size() ) {
-            super::RoutingStep(newForwardHeap, existingBackwardHeap, &v_t_middle, &upperBoundFor_v_t_Path, 2 * offset, true);
-        }
-        *real_length_of_via_path = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path;
-
-        if(UINT_MAX == s_v_middle || UINT_MAX == v_t_middle)
+    // TODO: reorder parameters
+    // compute and unpack <s,..,v> and <v,..,t> by exploring search spaces
+    // from v and intersecting against queues. only half-searches have to be
+    // done at this stage
+    inline void ComputeLengthAndSharingOfViaPath(const NodeID via_node,
+                                                 int *real_length_of_via_path,
+                                                 int *sharing_of_via_path,
+                                                 const std::vector<NodeID> &packed_shortest_path)
+    {
+        engine_working_data.InitializeOrClearSecondThreadLocalStorage(
+            super::facade->GetNumberOfNodes());
+
+        QueryHeap &existing_forward_heap = *engine_working_data.forwardHeap;
+        QueryHeap &existing_reverse_heap = *engine_working_data.backwardHeap;
+        QueryHeap &new_forward_heap = *engine_working_data.forwardHeap2;
+        QueryHeap &new_reverse_heap = *engine_working_data.backwardHeap2;
+
+        std::vector<NodeID> packed_s_v_path;
+        std::vector<NodeID> packed_v_t_path;
+
+        std::vector<NodeID> partially_unpacked_shortest_path;
+        std::vector<NodeID> partially_unpacked_via_path;
+
+        NodeID s_v_middle = SPECIAL_NODEID;
+        int upper_bound_s_v_path_length = INVALID_EDGE_WEIGHT;
+        new_reverse_heap.Insert(via_node, 0, via_node);
+        // compute path <s,..,v> by reusing forward search from s
+        while (!new_reverse_heap.Empty())
+        {
+            super::RoutingStep(new_reverse_heap,
+                               existing_forward_heap,
+                               &s_v_middle,
+                               &upper_bound_s_v_path_length,
+                               false);
+        }
+        // compute path <v,..,t> by reusing backward search from node t
+        NodeID v_t_middle = SPECIAL_NODEID;
+        int upper_bound_of_v_t_path_length = INVALID_EDGE_WEIGHT;
+        new_forward_heap.Insert(via_node, 0, via_node);
+        while (!new_forward_heap.Empty())
+        {
+            super::RoutingStep(new_forward_heap,
+                               existing_reverse_heap,
+                               &v_t_middle,
+                               &upper_bound_of_v_t_path_length,
+                               true);
+        }
+        *real_length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length;
+
+        if (SPECIAL_NODEID == s_v_middle || SPECIAL_NODEID == v_t_middle)
+        {
             return;
+        }
 
-        //retrieve packed paths
-        super::RetrievePackedPathFromHeap(existingForwardHeap, newBackwardHeap, s_v_middle, packed_s_v_path);
-        super::RetrievePackedPathFromHeap(newForwardHeap, existingBackwardHeap, v_t_middle, packed_v_t_path);
-
-        //partial unpacking, compute sharing
-        //First partially unpack s-->v until paths deviate, note length of common path.
-        for (unsigned i = 0, lengthOfPackedPath = std::min( packed_s_v_path.size(), packed_shortest_path.size()) - 1; (i < lengthOfPackedPath); ++i) {
-            if (packed_s_v_path[i] == packed_shortest_path[i] && packed_s_v_path[i + 1] == packed_shortest_path[i + 1]) {
-                typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
-                *sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
-            } else {
-                if (packed_s_v_path[i] == packed_shortest_path[i]) {
-                    super::UnpackEdge(packed_s_v_path[i], packed_s_v_path[i+1], partiallyUnpackedViaPath);
-                    super::UnpackEdge(packed_shortest_path[i], packed_shortest_path[i+1], partiallyUnpackedShortestPath);
+        // retrieve packed paths
+        super::RetrievePackedPathFromHeap(
+            existing_forward_heap, new_reverse_heap, s_v_middle, packed_s_v_path);
+        super::RetrievePackedPathFromHeap(
+            new_forward_heap, existing_reverse_heap, v_t_middle, packed_v_t_path);
+
+        // partial unpacking, compute sharing
+        // First partially unpack s-->v until paths deviate, note length of common path.
+        const unsigned s_v_min_path_size =
+            std::min(packed_s_v_path.size(), packed_shortest_path.size()) - 1;
+        for (unsigned i = 0; i < s_v_min_path_size; ++i)
+        {
+            if (packed_s_v_path[i] == packed_shortest_path[i] &&
+                packed_s_v_path[i + 1] == packed_shortest_path[i + 1])
+            {
+                EdgeID edgeID =
+                    facade->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
+                *sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
+            }
+            else
+            {
+                if (packed_s_v_path[i] == packed_shortest_path[i])
+                {
+                    super::UnpackEdge(
+                        packed_s_v_path[i], packed_s_v_path[i + 1], partially_unpacked_via_path);
+                    super::UnpackEdge(packed_shortest_path[i],
+                                      packed_shortest_path[i + 1],
+                                      partially_unpacked_shortest_path);
                     break;
                 }
             }
         }
-        //traverse partially unpacked edge and note common prefix
-        for (int i = 0, lengthOfPackedPath = std::min( partiallyUnpackedViaPath.size(), partiallyUnpackedShortestPath.size()) - 1; (i < lengthOfPackedPath) && (partiallyUnpackedViaPath[i] == partiallyUnpackedShortestPath[i] && partiallyUnpackedViaPath[i+1] == partiallyUnpackedShortestPath[i+1]); ++i) {
-            typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]);
-            *sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
-        }
-
-        //Second, partially unpack v-->t in reverse order until paths deviate and note lengths
-        int viaPathIndex = packed_v_t_path.size() - 1;
-        int shortestPathIndex = packed_shortest_path.size() - 1;
-        for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex ) {
-            if (packed_v_t_path[viaPathIndex - 1] == packed_shortest_path[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
-                typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]);
-                *sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
-            } else {
-                if (packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
-                    super::UnpackEdge(packed_v_t_path[viaPathIndex-1], packed_v_t_path[viaPathIndex], partiallyUnpackedViaPath);
-                    super::UnpackEdge(packed_shortest_path[shortestPathIndex-1] , packed_shortest_path[shortestPathIndex], partiallyUnpackedShortestPath);
+        // traverse partially unpacked edge and note common prefix
+        for (int i = 0,
+                 packed_path_length = std::min(partially_unpacked_via_path.size(),
+                                               partially_unpacked_shortest_path.size()) -
+                                      1;
+             (i < packed_path_length) &&
+                 (partially_unpacked_via_path[i] == partially_unpacked_shortest_path[i] &&
+                  partially_unpacked_via_path[i + 1] == partially_unpacked_shortest_path[i + 1]);
+             ++i)
+        {
+            EdgeID edgeID = facade->FindEdgeInEitherDirection(partially_unpacked_via_path[i],
+                                                              partially_unpacked_via_path[i + 1]);
+            *sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
+        }
+
+        // Second, partially unpack v-->t in reverse order until paths deviate and note lengths
+        int via_path_index = packed_v_t_path.size() - 1;
+        int shortest_path_index = packed_shortest_path.size() - 1;
+        for (; via_path_index > 0 && shortest_path_index > 0;
+             --via_path_index, --shortest_path_index)
+        {
+            if (packed_v_t_path[via_path_index - 1] ==
+                    packed_shortest_path[shortest_path_index - 1] &&
+                packed_v_t_path[via_path_index] == packed_shortest_path[shortest_path_index])
+            {
+                EdgeID edgeID = facade->FindEdgeInEitherDirection(
+                    packed_v_t_path[via_path_index - 1], packed_v_t_path[via_path_index]);
+                *sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
+            }
+            else
+            {
+                if (packed_v_t_path[via_path_index] == packed_shortest_path[shortest_path_index])
+                {
+                    super::UnpackEdge(packed_v_t_path[via_path_index - 1],
+                                      packed_v_t_path[via_path_index],
+                                      partially_unpacked_via_path);
+                    super::UnpackEdge(packed_shortest_path[shortest_path_index - 1],
+                                      packed_shortest_path[shortest_path_index],
+                                      partially_unpacked_shortest_path);
                     break;
                 }
             }
         }
 
-        viaPathIndex = partiallyUnpackedViaPath.size() - 1;
-        shortestPathIndex = partiallyUnpackedShortestPath.size() - 1;
-        for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex) {
-            if (partiallyUnpackedViaPath[viaPathIndex - 1] == partiallyUnpackedShortestPath[shortestPathIndex - 1] && partiallyUnpackedViaPath[viaPathIndex] == partiallyUnpackedShortestPath[shortestPathIndex]) {
-                typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]);
-                *sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
-            } else {
+        via_path_index = partially_unpacked_via_path.size() - 1;
+        shortest_path_index = partially_unpacked_shortest_path.size() - 1;
+        for (; via_path_index > 0 && shortest_path_index > 0;
+             --via_path_index, --shortest_path_index)
+        {
+            if (partially_unpacked_via_path[via_path_index - 1] ==
+                    partially_unpacked_shortest_path[shortest_path_index - 1] &&
+                partially_unpacked_via_path[via_path_index] ==
+                    partially_unpacked_shortest_path[shortest_path_index])
+            {
+                EdgeID edgeID = facade->FindEdgeInEitherDirection(
+                    partially_unpacked_via_path[via_path_index - 1],
+                    partially_unpacked_via_path[via_path_index]);
+                *sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
+            }
+            else
+            {
                 break;
             }
         }
-        //finished partial unpacking spree! Amount of sharing is stored to appropriate pointer variable
-    }
-
-    inline int approximateAmountOfSharing(const NodeID middleNodeIDOfAlternativePath, QueryHeap & _forwardHeap, QueryHeap & _backwardHeap, const std::vector<NodeID> & packedShortestPath) {
-        std::vector<NodeID> packedAlternativePath;
-        super::RetrievePackedPathFromHeap(_forwardHeap, _backwardHeap, middleNodeIDOfAlternativePath, packedAlternativePath);
-
-        if(packedShortestPath.size() < 2 || packedAlternativePath.size() < 2)
-            return 0;
-
-        int sharing = 0;
-        int aindex = 0;
-        //compute forward sharing
-        while( (packedAlternativePath[aindex] == packedShortestPath[aindex]) && (packedAlternativePath[aindex+1] == packedShortestPath[aindex+1]) ) {
-            //            INFO("retrieving edge (" << packedAlternativePath[aindex] << "," << packedAlternativePath[aindex+1] << ")");
-            typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]);
-            sharing += search_graph->GetEdgeData(edgeID).distance;
-            ++aindex;
-        }
-
-        aindex = packedAlternativePath.size()-1;
-        int bindex = packedShortestPath.size()-1;
-        //compute backward sharing
-        while( aindex > 0 && bindex > 0 && (packedAlternativePath[aindex] == packedShortestPath[bindex]) && (packedAlternativePath[aindex-1] == packedShortestPath[bindex-1]) ) {
-            typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]);
-            sharing += search_graph->GetEdgeData(edgeID).distance;
-            --aindex; --bindex;
-        }
-        return sharing;
+        // finished partial unpacking spree! Amount of sharing is stored to appropriate pointer
+        // variable
     }
 
-    template<bool forwardDirection>
-    inline void AlternativeRoutingStep(
-    		QueryHeap & _forward_heap,
-    		QueryHeap & _reverse_heap,
-    		NodeID *middle_node,
-    		int *upper_bound_to_shortest_path_distance,
-    		std::vector<NodeID>& searchSpaceIntersection,
-    		std::vector<SearchSpaceEdge> & search_space,
-    		const int edgeBasedOffset
-    		) const {
-        const NodeID node = _forward_heap.DeleteMin();
-        const int distance = _forward_heap.GetKey(node);
-        int scaledDistance = (distance-edgeBasedOffset)/(1.+VIAPATH_EPSILON);
-        if(scaledDistance > *upper_bound_to_shortest_path_distance){
-            _forward_heap.DeleteAll();
+    // inline int approximateAmountOfSharing(
+    //     const NodeID alternate_path_middle_node_id,
+    //     QueryHeap & forward_heap,
+    //     QueryHeap & reverse_heap,
+    //     const std::vector<NodeID> & packed_shortest_path
+    // ) const {
+    //     std::vector<NodeID> packed_alternate_path;
+    //     super::RetrievePackedPathFromHeap(
+    //         forward_heap,
+    //         reverse_heap,
+    //         alternate_path_middle_node_id,
+    //         packed_alternate_path
+    //     );
+
+    //     if(packed_shortest_path.size() < 2 || packed_alternate_path.size() < 2) {
+    //         return 0;
+    //     }
+
+    //     int sharing = 0;
+    //     int aindex = 0;
+    //     //compute forward sharing
+    //     while( (packed_alternate_path[aindex] == packed_shortest_path[aindex]) &&
+    //     (packed_alternate_path[aindex+1] == packed_shortest_path[aindex+1]) ) {
+    //         //            SimpleLogger().Write() << "retrieving edge (" <<
+    //         packed_alternate_path[aindex] << "," << packed_alternate_path[aindex+1] << ")";
+    //         EdgeID edgeID = facade->FindEdgeInEitherDirection(packed_alternate_path[aindex],
+    //         packed_alternate_path[aindex+1]);
+    //         sharing += facade->GetEdgeData(edgeID).distance;
+    //         ++aindex;
+    //     }
+
+    //     aindex = packed_alternate_path.size()-1;
+    //     int bindex = packed_shortest_path.size()-1;
+    //     //compute backward sharing
+    //     while( aindex > 0 && bindex > 0 && (packed_alternate_path[aindex] ==
+    //     packed_shortest_path[bindex]) && (packed_alternate_path[aindex-1] ==
+    //     packed_shortest_path[bindex-1]) ) {
+    //         EdgeID edgeID = facade->FindEdgeInEitherDirection(packed_alternate_path[aindex],
+    //         packed_alternate_path[aindex-1]);
+    //         sharing += facade->GetEdgeData(edgeID).distance;
+    //         --aindex; --bindex;
+    //     }
+    //     return sharing;
+    // }
+
+    // todo: reorder parameters
+    template <bool is_forward_directed>
+    inline void AlternativeRoutingStep(QueryHeap &forward_heap,
+                                       QueryHeap &reverse_heap,
+                                       NodeID *middle_node,
+                                       int *upper_bound_to_shortest_path_distance,
+                                       std::vector<NodeID> &search_space_intersection,
+                                       std::vector<SearchSpaceEdge> &search_space) const
+    {
+        const NodeID node = forward_heap.DeleteMin();
+        const int distance = forward_heap.GetKey(node);
+        const int scaled_distance = static_cast<int>(distance / (1. + VIAPATH_EPSILON));
+        if ((INVALID_EDGE_WEIGHT != *upper_bound_to_shortest_path_distance) &&
+            (scaled_distance > *upper_bound_to_shortest_path_distance))
+        {
+            forward_heap.DeleteAll();
             return;
         }
 
-        search_space.push_back(std::make_pair(_forward_heap.GetData( node ).parent, node));
+        search_space.emplace_back(forward_heap.GetData(node).parent, node);
 
-        if(_reverse_heap.WasInserted(node) ){
-            searchSpaceIntersection.push_back(node);
+        if (reverse_heap.WasInserted(node))
+        {
+            search_space_intersection.emplace_back(node);
 
-            const int newDistance = _reverse_heap.GetKey(node) + distance;
-            if(newDistance < *upper_bound_to_shortest_path_distance ){
-                if(newDistance>=0 ) {
+            const int new_distance = reverse_heap.GetKey(node) + distance;
+            if (new_distance < *upper_bound_to_shortest_path_distance)
+            {
+                if (new_distance >= 0)
+                {
                     *middle_node = node;
-                    *upper_bound_to_shortest_path_distance = newDistance;
+                    *upper_bound_to_shortest_path_distance = new_distance;
                 }
             }
         }
 
-        for ( typename SearchGraph::EdgeIterator edge = search_graph->BeginEdges( node ); edge < search_graph->EndEdges(node); edge++ ) {
-            const typename SearchGraph::EdgeData & data = search_graph->GetEdgeData(edge);
-            bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
-            if(forwardDirectionFlag) {
+        for (auto edge : facade->GetAdjacentEdgeRange(node))
+        {
+            const EdgeData &data = facade->GetEdgeData(edge);
+            const bool edge_is_forward_directed =
+                (is_forward_directed ? data.forward : data.backward);
+            if (edge_is_forward_directed)
+            {
 
-                const NodeID to = search_graph->GetTarget(edge);
-                const int edgeWeight = data.distance;
+                const NodeID to = facade->GetTarget(edge);
+                const int edge_weight = data.distance;
 
-                assert( edgeWeight > 0 );
-                const int toDistance = distance + edgeWeight;
-
-                //New Node discovered -> Add to Heap + Node Info Storage
-                if ( !_forward_heap.WasInserted( to ) ) {
-                    _forward_heap.Insert( to, toDistance, node );
+                BOOST_ASSERT(edge_weight > 0);
+                const int to_distance = distance + edge_weight;
 
+                // New Node discovered -> Add to Heap + Node Info Storage
+                if (!forward_heap.WasInserted(to))
+                {
+                    forward_heap.Insert(to, to_distance, node);
                 }
-                //Found a shorter Path -> Update distance
-                else if ( toDistance < _forward_heap.GetKey( to ) ) {
-                    _forward_heap.GetData( to ).parent = node;
-                    _forward_heap.DecreaseKey( to, toDistance );
-                    //new parent
+                // Found a shorter Path -> Update distance
+                else if (to_distance < forward_heap.GetKey(to))
+                {
+                    // new parent
+                    forward_heap.GetData(to).parent = node;
+                    // decreased distance
+                    forward_heap.DecreaseKey(to, to_distance);
                 }
             }
         }
     }
 
-    //conduct T-Test
-    inline bool viaNodeCandidatePasses_T_Test( QueryHeap& existingForwardHeap, QueryHeap& existingBackwardHeap, QueryHeap& newForwardHeap, QueryHeap& newBackwardHeap, const RankedCandidateNode& candidate, const int offset, const int lengthOfShortestPath, int * lengthOfViaPath, NodeID * s_v_middle, NodeID * v_t_middle) {
-    	newForwardHeap.Clear();
-    	newBackwardHeap.Clear();
-        std::vector < NodeID > packed_s_v_path;
-        std::vector < NodeID > packed_v_t_path;
+    // conduct T-Test
+    inline bool ViaNodeCandidatePassesTTest(QueryHeap &existing_forward_heap,
+                                            QueryHeap &existing_reverse_heap,
+                                            QueryHeap &new_forward_heap,
+                                            QueryHeap &new_reverse_heap,
+                                            const RankedCandidateNode &candidate,
+                                            const int length_of_shortest_path,
+                                            int *length_of_via_path,
+                                            NodeID *s_v_middle,
+                                            NodeID *v_t_middle) const
+    {
+        new_forward_heap.Clear();
+        new_reverse_heap.Clear();
+        std::vector<NodeID> packed_s_v_path;
+        std::vector<NodeID> packed_v_t_path;
+
+        *s_v_middle = SPECIAL_NODEID;
+        int upper_bound_s_v_path_length = INVALID_EDGE_WEIGHT;
+        // compute path <s,..,v> by reusing forward search from s
+        new_reverse_heap.Insert(candidate.node, 0, candidate.node);
+        while (new_reverse_heap.Size() > 0)
+        {
+            super::RoutingStep(new_reverse_heap,
+                               existing_forward_heap,
+                               s_v_middle,
+                               &upper_bound_s_v_path_length,
+                               false);
+        }
+
+        if (INVALID_EDGE_WEIGHT == upper_bound_s_v_path_length)
+        {
+            return false;
+        }
 
-        *s_v_middle = UINT_MAX;
-        int upperBoundFor_s_v_Path = INT_MAX;
-        //compute path <s,..,v> by reusing forward search from s
-        newBackwardHeap.Insert(candidate.node, 0, candidate.node);
-        while (newBackwardHeap.Size() > 0) {
-            super::RoutingStep(newBackwardHeap, existingForwardHeap, s_v_middle, &upperBoundFor_s_v_Path, 2*offset, false);
+        // compute path <v,..,t> by reusing backward search from t
+        *v_t_middle = SPECIAL_NODEID;
+        int upper_bound_of_v_t_path_length = INVALID_EDGE_WEIGHT;
+        new_forward_heap.Insert(candidate.node, 0, candidate.node);
+        while (new_forward_heap.Size() > 0)
+        {
+            super::RoutingStep(new_forward_heap,
+                               existing_reverse_heap,
+                               v_t_middle,
+                               &upper_bound_of_v_t_path_length,
+                               true);
         }
 
-        if(INT_MAX == upperBoundFor_s_v_Path)
+        if (INVALID_EDGE_WEIGHT == upper_bound_of_v_t_path_length)
+        {
             return false;
-
-        //compute path <v,..,t> by reusing backward search from t
-        *v_t_middle = UINT_MAX;
-        int upperBoundFor_v_t_Path = INT_MAX;
-        newForwardHeap.Insert(candidate.node, 0, candidate.node);
-        while (newForwardHeap.Size() > 0) {
-            super::RoutingStep(newForwardHeap, existingBackwardHeap, v_t_middle, &upperBoundFor_v_t_Path, 2*offset, true);
         }
 
-        if(INT_MAX == upperBoundFor_v_t_Path)
-            return false;
+        *length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length;
 
-        *lengthOfViaPath = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path;
+        // retrieve packed paths
+        super::RetrievePackedPathFromHeap(
+            existing_forward_heap, new_reverse_heap, *s_v_middle, packed_s_v_path);
 
-        //retrieve packed paths
-        super::RetrievePackedPathFromHeap(existingForwardHeap, newBackwardHeap, *s_v_middle, packed_s_v_path);
-        super::RetrievePackedPathFromHeap(newForwardHeap, existingBackwardHeap, *v_t_middle, packed_v_t_path);
+        super::RetrievePackedPathFromHeap(
+            new_forward_heap, existing_reverse_heap, *v_t_middle, packed_v_t_path);
 
         NodeID s_P = *s_v_middle, t_P = *v_t_middle;
-        if(UINT_MAX == s_P) {
+        if (SPECIAL_NODEID == s_P)
+        {
             return false;
         }
 
-        if(UINT_MAX == t_P) {
+        if (SPECIAL_NODEID == t_P)
+        {
             return false;
         }
-        const int T_threshold = VIAPATH_EPSILON * lengthOfShortestPath;
-        int unpackedUntilDistance = 0;
-
-        std::stack<SearchSpaceEdge> unpackStack;
-        //Traverse path s-->v
-        for (unsigned i = packed_s_v_path.size() - 1; (i > 0) && unpackStack.empty(); --i) {
-            typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]);
-            int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance;
-            if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
-                unpackStack.push(std::make_pair(packed_s_v_path[i - 1], packed_s_v_path[i]));
-            } else {
-                unpackedUntilDistance += lengthOfCurrentEdge;
+        const int T_threshold = static_cast<int>(VIAPATH_EPSILON * length_of_shortest_path);
+        int unpacked_until_distance = 0;
+
+        std::stack<SearchSpaceEdge> unpack_stack;
+        // Traverse path s-->v
+        for (std::size_t i = packed_s_v_path.size() - 1; (i > 0) && unpack_stack.empty(); --i)
+        {
+            const EdgeID current_edge_id =
+                facade->FindEdgeInEitherDirection(packed_s_v_path[i - 1], packed_s_v_path[i]);
+            const int length_of_current_edge = facade->GetEdgeData(current_edge_id).distance;
+            if ((length_of_current_edge + unpacked_until_distance) >= T_threshold)
+            {
+                unpack_stack.emplace(packed_s_v_path[i - 1], packed_s_v_path[i]);
+            }
+            else
+            {
+                unpacked_until_distance += length_of_current_edge;
                 s_P = packed_s_v_path[i - 1];
             }
         }
 
-        while (!unpackStack.empty()) {
-            const SearchSpaceEdge viaPathEdge = unpackStack.top();
-            unpackStack.pop();
-            typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
-            if(UINT_MAX == edgeIDInViaPath)
+        while (!unpack_stack.empty())
+        {
+            const SearchSpaceEdge via_path_edge = unpack_stack.top();
+            unpack_stack.pop();
+            EdgeID edge_in_via_path_id =
+                facade->FindEdgeInEitherDirection(via_path_edge.first, via_path_edge.second);
+
+            if (SPECIAL_EDGEID == edge_in_via_path_id)
+            {
                 return false;
-            typename SearchGraph::EdgeData currentEdgeData = search_graph->GetEdgeData(edgeIDInViaPath);
-            bool IsViaEdgeShortCut = currentEdgeData.shortcut;
-            if (IsViaEdgeShortCut) {
-                const NodeID middleOfViaPath = currentEdgeData.id;
-                typename SearchGraph::EdgeIterator edgeIDOfSecondSegment = search_graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
-                int lengthOfSecondSegment = search_graph->GetEdgeData(edgeIDOfSecondSegment).distance;
-                //attention: !unpacking in reverse!
-                //Check if second segment is the one to go over treshold? if yes add second segment to stack, else push first segment to stack and add distance of second one.
-                if (unpackedUntilDistance + lengthOfSecondSegment >= T_threshold) {
-                    unpackStack.push(std::make_pair(middleOfViaPath, viaPathEdge.second));
-                } else {
-                    unpackedUntilDistance += lengthOfSecondSegment;
-                    unpackStack.push(std::make_pair(viaPathEdge.first, middleOfViaPath));
+            }
+
+            const EdgeData &current_edge_data = facade->GetEdgeData(edge_in_via_path_id);
+            const bool current_edge_is_shortcut = current_edge_data.shortcut;
+            if (current_edge_is_shortcut)
+            {
+                const NodeID via_path_middle_node_id = current_edge_data.id;
+                const EdgeID second_segment_edge_id = facade->FindEdgeInEitherDirection(
+                    via_path_middle_node_id, via_path_edge.second);
+                const int second_segment_length =
+                    facade->GetEdgeData(second_segment_edge_id).distance;
+                // attention: !unpacking in reverse!
+                // Check if second segment is the one to go over treshold? if yes add second segment
+                // to stack, else push first segment to stack and add distance of second one.
+                if (unpacked_until_distance + second_segment_length >= T_threshold)
+                {
+                    unpack_stack.emplace(via_path_middle_node_id, via_path_edge.second);
                 }
-            } else {
+                else
+                {
+                    unpacked_until_distance += second_segment_length;
+                    unpack_stack.emplace(via_path_edge.first, via_path_middle_node_id);
+                }
+            }
+            else
+            {
                 // edge is not a shortcut, set the start node for T-Test to end of edge.
-                unpackedUntilDistance += currentEdgeData.distance;
-                s_P = viaPathEdge.first;
+                unpacked_until_distance += current_edge_data.distance;
+                s_P = via_path_edge.first;
             }
         }
 
-        int lengthOfPathT_Test_Path = unpackedUntilDistance;
-        unpackedUntilDistance = 0;
-        //Traverse path s-->v
-        for (unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size() - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) {
-            typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]);
-            int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance;
-            if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
-                unpackStack.push( std::make_pair(packed_v_t_path[i], packed_v_t_path[i + 1]));
-            } else {
-                unpackedUntilDistance += lengthOfCurrentEdge;
+        int t_test_path_length = unpacked_until_distance;
+        unpacked_until_distance = 0;
+        // Traverse path s-->v
+        BOOST_ASSERT(!packed_v_t_path.empty());
+        for (unsigned i = 0, packed_path_length = static_cast<unsigned>(packed_v_t_path.size() - 1);
+             (i < packed_path_length) && unpack_stack.empty();
+             ++i)
+        {
+            const EdgeID edgeID =
+                facade->FindEdgeInEitherDirection(packed_v_t_path[i], packed_v_t_path[i + 1]);
+            int length_of_current_edge = facade->GetEdgeData(edgeID).distance;
+            if (length_of_current_edge + unpacked_until_distance >= T_threshold)
+            {
+                unpack_stack.emplace(packed_v_t_path[i], packed_v_t_path[i + 1]);
+            }
+            else
+            {
+                unpacked_until_distance += length_of_current_edge;
                 t_P = packed_v_t_path[i + 1];
             }
         }
 
-        while (!unpackStack.empty()) {
-            const SearchSpaceEdge viaPathEdge = unpackStack.top();
-            unpackStack.pop();
-            typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
-            if(UINT_MAX == edgeIDInViaPath)
+        while (!unpack_stack.empty())
+        {
+            const SearchSpaceEdge via_path_edge = unpack_stack.top();
+            unpack_stack.pop();
+            EdgeID edge_in_via_path_id =
+                facade->FindEdgeInEitherDirection(via_path_edge.first, via_path_edge.second);
+            if (SPECIAL_EDGEID == edge_in_via_path_id)
+            {
                 return false;
-            typename SearchGraph::EdgeData currentEdgeData = search_graph->GetEdgeData(edgeIDInViaPath);
-            const bool IsViaEdgeShortCut = currentEdgeData.shortcut;
-            if (IsViaEdgeShortCut) {
-                const NodeID middleOfViaPath = currentEdgeData.id;
-                typename SearchGraph::EdgeIterator edgeIDOfFirstSegment = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
-                int lengthOfFirstSegment = search_graph->GetEdgeData( edgeIDOfFirstSegment).distance;
-                //Check if first segment is the one to go over treshold? if yes first segment to stack, else push second segment to stack and add distance of first one.
-                if (unpackedUntilDistance + lengthOfFirstSegment >= T_threshold) {
-                    unpackStack.push( std::make_pair(viaPathEdge.first, middleOfViaPath));
-                } else {
-                    unpackedUntilDistance += lengthOfFirstSegment;
-                    unpackStack.push( std::make_pair(middleOfViaPath, viaPathEdge.second));
+            }
+
+            const EdgeData &current_edge_data = facade->GetEdgeData(edge_in_via_path_id);
+            const bool IsViaEdgeShortCut = current_edge_data.shortcut;
+            if (IsViaEdgeShortCut)
+            {
+                const NodeID middleOfViaPath = current_edge_data.id;
+                EdgeID edgeIDOfFirstSegment =
+                    facade->FindEdgeInEitherDirection(via_path_edge.first, middleOfViaPath);
+                int lengthOfFirstSegment = facade->GetEdgeData(edgeIDOfFirstSegment).distance;
+                // Check if first segment is the one to go over treshold? if yes first segment to
+                // stack, else push second segment to stack and add distance of first one.
+                if (unpacked_until_distance + lengthOfFirstSegment >= T_threshold)
+                {
+                    unpack_stack.emplace(via_path_edge.first, middleOfViaPath);
+                }
+                else
+                {
+                    unpacked_until_distance += lengthOfFirstSegment;
+                    unpack_stack.emplace(middleOfViaPath, via_path_edge.second);
                 }
-            } else {
+            }
+            else
+            {
                 // edge is not a shortcut, set the start node for T-Test to end of edge.
-                unpackedUntilDistance += currentEdgeData.distance;
-                t_P = viaPathEdge.second;
+                unpacked_until_distance += current_edge_data.distance;
+                t_P = via_path_edge.second;
             }
         }
 
-        lengthOfPathT_Test_Path += unpackedUntilDistance;
-        //Run actual T-Test query and compare if distances equal.
-        super::_queryData.InitializeOrClearThirdThreadLocalStorage();
+        t_test_path_length += unpacked_until_distance;
+        // Run actual T-Test query and compare if distances equal.
+        engine_working_data.InitializeOrClearThirdThreadLocalStorage(
+            super::facade->GetNumberOfNodes());
+
+        QueryHeap &forward_heap3 = *engine_working_data.forwardHeap3;
+        QueryHeap &reverse_heap3 = *engine_working_data.backwardHeap3;
+        int upper_bound = INVALID_EDGE_WEIGHT;
+        NodeID middle = SPECIAL_NODEID;
 
-        QueryHeap& forward_heap3 = *super::_queryData.forwardHeap3;
-        QueryHeap& backward_heap3 = *super::_queryData.backwardHeap3;
-        int _upperBound = INT_MAX;
-        NodeID middle = UINT_MAX;
         forward_heap3.Insert(s_P, 0, s_P);
-        backward_heap3.Insert(t_P, 0, t_P);
-        //exploration from s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
-        while (forward_heap3.Size() + backward_heap3.Size() > 0) {
-            if (forward_heap3.Size() > 0) {
-                super::RoutingStep(forward_heap3, backward_heap3, &middle, &_upperBound, offset, true);
+        reverse_heap3.Insert(t_P, 0, t_P);
+        // exploration from s and t until deletemin/(1+epsilon) > _lengt_oO_sShortest_path
+        while ((forward_heap3.Size() + reverse_heap3.Size()) > 0)
+        {
+            if (!forward_heap3.Empty())
+            {
+                super::RoutingStep(forward_heap3, reverse_heap3, &middle, &upper_bound, true);
             }
-            if (backward_heap3.Size() > 0) {
-                super::RoutingStep(backward_heap3, forward_heap3, &middle, &_upperBound, offset, false);
+            if (!reverse_heap3.Empty())
+            {
+                super::RoutingStep(reverse_heap3, forward_heap3, &middle, &upper_bound, false);
             }
         }
-        return (_upperBound <= lengthOfPathT_Test_Path);
+        return (upper_bound <= t_test_path_length);
     }
 };
 
-#endif /* ALTERNATIVEROUTES_H_ */
+#endif /* ALTERNATIVE_PATH_ROUTING_H */
diff --git a/RoutingAlgorithms/BasicRoutingInterface.h b/RoutingAlgorithms/BasicRoutingInterface.h
index caef97a..464c088 100644
--- a/RoutingAlgorithms/BasicRoutingInterface.h
+++ b/RoutingAlgorithms/BasicRoutingInterface.h
@@ -1,225 +1,411 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-
-
-#ifndef BASICROUTINGINTERFACE_H_
-#define BASICROUTINGINTERFACE_H_
-
-#include "../Plugins/RawRouteData.h"
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef BASIC_ROUTING_INTERFACE_H
+#define BASIC_ROUTING_INTERFACE_H
+
+#include "../DataStructures/RawRouteData.h"
+#include "../DataStructures/SearchEngineData.h"
+#include "../DataStructures/TurnInstructions.h"
 #include "../Util/ContainerUtils.h"
+#include "../Util/SimpleLogger.h"
 
-#include <boost/noncopyable.hpp>
-
-#include <cassert>
-#include <climits>
+#include <boost/assert.hpp>
 
 #include <stack>
 
-template<class QueryDataT>
-class BasicRoutingInterface : boost::noncopyable{
-protected:
-    QueryDataT & _queryData;
-public:
-    BasicRoutingInterface(QueryDataT & qd) : _queryData(qd) { }
-    virtual ~BasicRoutingInterface(){ };
-
-    inline void RoutingStep(typename QueryDataT::QueryHeap & _forwardHeap, typename QueryDataT::QueryHeap & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const {
-        const NodeID node = _forwardHeap.DeleteMin();
-        const int distance = _forwardHeap.GetKey(node);
-        //INFO("Settled (" << _forwardHeap.GetData( node ).parent << "," << node << ")=" << distance);
-        if(_backwardHeap.WasInserted(node) ){
-            const int newDistance = _backwardHeap.GetKey(node) + distance;
-            if(newDistance < *_upperbound ){
-                if(newDistance>=0 ) {
-                    *middle = node;
-                    *_upperbound = newDistance;
-                } else {
+SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap;
+SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap;
+SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap2;
+SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap2;
+SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap3;
+SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap3;
+
+template <class DataFacadeT> class BasicRoutingInterface
+{
+  private:
+    typedef typename DataFacadeT::EdgeData EdgeData;
+
+  protected:
+    DataFacadeT *facade;
+
+  public:
+    BasicRoutingInterface() = delete;
+    BasicRoutingInterface(const BasicRoutingInterface &) = delete;
+    explicit BasicRoutingInterface(DataFacadeT *facade) : facade(facade) {}
+    virtual ~BasicRoutingInterface() {};
+
+    inline void RoutingStep(SearchEngineData::QueryHeap &forward_heap,
+                            SearchEngineData::QueryHeap &reverse_heap,
+                            NodeID *middle_node_id,
+                            int *upper_bound,
+                            const bool forward_direction) const
+    {
+        const NodeID node = forward_heap.DeleteMin();
+        const int distance = forward_heap.GetKey(node);
+        if (reverse_heap.WasInserted(node))
+        {
+            const int new_distance = reverse_heap.GetKey(node) + distance;
+            if (new_distance < *upper_bound)
+            {
+                if (new_distance >= 0)
+                {
+                    *middle_node_id = node;
+                    *upper_bound = new_distance;
                 }
             }
         }
 
-        if(distance-edgeBasedOffset > *_upperbound){
-            _forwardHeap.DeleteAll();
+        if (distance > *upper_bound)
+        {
+            forward_heap.DeleteAll();
             return;
         }
 
-        //Stalling
-        for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) {
-            const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
-            bool backwardDirectionFlag = (!forwardDirection) ? data.forward : data.backward;
-            if(backwardDirectionFlag) {
-                const NodeID to = _queryData.graph->GetTarget(edge);
-                const int edgeWeight = data.distance;
-
-                assert( edgeWeight > 0 );
-
-                if(_forwardHeap.WasInserted( to )) {
-                    if(_forwardHeap.GetKey( to ) + edgeWeight < distance) {
+        // Stalling
+        for (auto edge : facade->GetAdjacentEdgeRange(node))
+        {
+            const EdgeData &data = facade->GetEdgeData(edge);
+            const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
+            if (reverse_flag)
+            {
+                const NodeID to = facade->GetTarget(edge);
+                const int edge_weight = data.distance;
+
+                BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
+
+                if (forward_heap.WasInserted(to))
+                {
+                    if (forward_heap.GetKey(to) + edge_weight < distance)
+                    {
                         return;
                     }
                 }
             }
         }
 
-        for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) {
-            const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
-            bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
-            if(forwardDirectionFlag) {
+        for (auto edge : facade->GetAdjacentEdgeRange(node))
+        {
+            const EdgeData &data = facade->GetEdgeData(edge);
+            bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
+            if (forward_directionFlag)
+            {
 
-                const NodeID to = _queryData.graph->GetTarget(edge);
-                const int edgeWeight = data.distance;
+                const NodeID to = facade->GetTarget(edge);
+                const int edge_weight = data.distance;
 
-                assert( edgeWeight > 0 );
-                const int toDistance = distance + edgeWeight;
+                BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
+                const int to_distance = distance + edge_weight;
 
-                //New Node discovered -> Add to Heap + Node Info Storage
-                if ( !_forwardHeap.WasInserted( to ) ) {
-                    _forwardHeap.Insert( to, toDistance, node );
+                // New Node discovered -> Add to Heap + Node Info Storage
+                if (!forward_heap.WasInserted(to))
+                {
+                    forward_heap.Insert(to, to_distance, node);
                 }
-                //Found a shorter Path -> Update distance
-                else if ( toDistance < _forwardHeap.GetKey( to ) ) {
-                    _forwardHeap.GetData( to ).parent = node;
-                    _forwardHeap.DecreaseKey( to, toDistance );
-                    //new parent
+                // Found a shorter Path -> Update distance
+                else if (to_distance < forward_heap.GetKey(to))
+                {
+                    // new parent
+                    forward_heap.GetData(to).parent = node;
+                    forward_heap.DecreaseKey(to, to_distance);
                 }
             }
         }
     }
 
-    inline void UnpackPath(const std::vector<NodeID> & packedPath, std::vector<_PathData> & unpackedPath) const {
-        const unsigned sizeOfPackedPath = packedPath.size();
-        std::stack<std::pair<NodeID, NodeID> > recursionStack;
-
-        //We have to push the path in reverse order onto the stack because it's LIFO.
-        for(unsigned i = sizeOfPackedPath-1; i > 0; --i){
-            recursionStack.push(std::make_pair(packedPath[i-1], packedPath[i]));
+    inline void UnpackPath(const std::vector<NodeID> &packed_path,
+                           const PhantomNodes &phantom_node_pair,
+                           std::vector<PathData> &unpacked_path) const
+    {
+        const bool start_traversed_in_reverse =
+            (packed_path.front() != phantom_node_pair.source_phantom.forward_node_id);
+        const bool target_traversed_in_reverse =
+            (packed_path.back() != phantom_node_pair.target_phantom.forward_node_id);
+
+        const unsigned packed_path_size = static_cast<unsigned>(packed_path.size());
+        std::stack<std::pair<NodeID, NodeID>> recursion_stack;
+
+        // We have to push the path in reverse order onto the stack because it's LIFO.
+        for (unsigned i = packed_path_size - 1; i > 0; --i)
+        {
+            recursion_stack.emplace(packed_path[i - 1], packed_path[i]);
         }
 
         std::pair<NodeID, NodeID> edge;
-        while(!recursionStack.empty()) {
-            edge = recursionStack.top();
-            recursionStack.pop();
-
-            typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
-            int smallestWeight = INT_MAX;
-            for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){
-                const int weight = _queryData.graph->GetEdgeData(eit).distance;
-                if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
-                    smallestEdge = eit;
-                    smallestWeight = weight;
+        while (!recursion_stack.empty())
+        {
+            /*
+            Graphical representation of variables:
+
+            edge.first         edge.second
+                *------------------>*
+                       edge_id
+            */
+            edge = recursion_stack.top();
+            recursion_stack.pop();
+
+            // facade->FindEdge does not suffice here in case of shortcuts.
+            // The above explanation unclear? Think!
+            EdgeID smaller_edge_id = SPECIAL_EDGEID;
+            int edge_weight = INT_MAX;
+            for (auto edge_id : facade->GetAdjacentEdgeRange(edge.first))
+            {
+                const int weight = facade->GetEdgeData(edge_id).distance;
+                if ((facade->GetTarget(edge_id) == edge.second) && (weight < edge_weight) &&
+                    facade->GetEdgeData(edge_id).forward)
+                {
+                    smaller_edge_id = edge_id;
+                    edge_weight = weight;
                 }
             }
 
-            if(smallestEdge == SPECIAL_EDGEID){
-                for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){
-                    const int weight = _queryData.graph->GetEdgeData(eit).distance;
-                    if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
-                        smallestEdge = eit;
-                        smallestWeight = weight;
+            /*
+                Graphical representation of variables:
+
+                edge.first         edge.second
+                    *<------------------*
+                           edge_id
+            */
+            if (SPECIAL_EDGEID == smaller_edge_id)
+            {
+                for (auto edge_id : facade->GetAdjacentEdgeRange(edge.second))
+                {
+                    const int weight = facade->GetEdgeData(edge_id).distance;
+                    if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) &&
+                        facade->GetEdgeData(edge_id).backward)
+                    {
+                        smaller_edge_id = edge_id;
+                        edge_weight = weight;
+                    }
+                }
+            }
+            BOOST_ASSERT_MSG(edge_weight != INVALID_EDGE_WEIGHT, "edge id invalid");
+
+            const EdgeData &ed = facade->GetEdgeData(smaller_edge_id);
+            if (ed.shortcut)
+            { // unpack
+                const NodeID middle_node_id = ed.id;
+                // again, we need to this in reversed order
+                recursion_stack.emplace(middle_node_id, edge.second);
+                recursion_stack.emplace(edge.first, middle_node_id);
+            }
+            else
+            {
+                BOOST_ASSERT_MSG(!ed.shortcut, "original edge flagged as shortcut");
+                unsigned name_index = facade->GetNameIndexFromEdgeID(ed.id);
+                const TurnInstruction turn_instruction = facade->GetTurnInstructionForEdgeID(ed.id);
+
+                if (!facade->EdgeIsCompressed(ed.id))
+                {
+                    BOOST_ASSERT(!facade->EdgeIsCompressed(ed.id));
+                    unpacked_path.emplace_back(facade->GetGeometryIndexForEdgeID(ed.id),
+                                               name_index,
+                                               turn_instruction,
+                                               ed.distance);
+                }
+                else
+                {
+                    std::vector<unsigned> id_vector;
+                    facade->GetUncompressedGeometry(facade->GetGeometryIndexForEdgeID(ed.id),
+                                                    id_vector);
+
+                    const int start_index =
+                        (unpacked_path.empty()
+                             ? ((start_traversed_in_reverse)
+                                    ? id_vector.size() -
+                                          phantom_node_pair.source_phantom.fwd_segment_position - 1
+                                    : phantom_node_pair.source_phantom.fwd_segment_position)
+                             : 0);
+                    const int end_index = id_vector.size();
+
+                    BOOST_ASSERT(start_index >= 0);
+                    BOOST_ASSERT(start_index <= end_index);
+                    for (int i = start_index; i < end_index; ++i)
+                    {
+                        unpacked_path.emplace_back(id_vector[i], name_index, TurnInstruction::NoTurn, 0);
                     }
+                    unpacked_path.back().turn_instruction = turn_instruction;
+                    unpacked_path.back().segment_duration = ed.distance;
                 }
             }
-            assert(smallestWeight != INT_MAX);
+        }
+        if (SPECIAL_EDGEID != phantom_node_pair.target_phantom.packed_geometry_id)
+        {
+            std::vector<unsigned> id_vector;
+            facade->GetUncompressedGeometry(phantom_node_pair.target_phantom.packed_geometry_id,
+                                            id_vector);
+            if (target_traversed_in_reverse)
+            {
+                std::reverse(id_vector.begin(), id_vector.end());
+            }
+            const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id ==
+                                        phantom_node_pair.target_phantom.packed_geometry_id) &&
+                                       unpacked_path.empty();
+
+            int start_index = 0;
+            int end_index = phantom_node_pair.target_phantom.fwd_segment_position;
+            if (target_traversed_in_reverse)
+            {
+                end_index =
+                    id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
+            }
+            if (is_local_path)
+            {
+                start_index = phantom_node_pair.source_phantom.fwd_segment_position;
+                end_index = phantom_node_pair.target_phantom.fwd_segment_position;
+                if (target_traversed_in_reverse)
+                {
+                    start_index =
+                        id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position;
+                    end_index =
+                        id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
+                }
+            }
+
+            BOOST_ASSERT(start_index >= 0);
+            for (int i = start_index; i != end_index; (start_index < end_index ? ++i : --i))
+            {
+                BOOST_ASSERT(i >= -1);
+                unpacked_path.emplace_back(PathData{id_vector[i],
+                                           phantom_node_pair.target_phantom.name_id,
+                                           TurnInstruction::NoTurn,
+                                           0});
+            }
+        }
 
-            const typename QueryDataT::Graph::EdgeData& ed = _queryData.graph->GetEdgeData(smallestEdge);
-            if(ed.shortcut) {//unpack
-                const NodeID middle = ed.id;
-                //again, we need to this in reversed order
-                recursionStack.push(std::make_pair(middle, edge.second));
-                recursionStack.push(std::make_pair(edge.first, middle));
-            } else {
-                assert(!ed.shortcut);
-                unpackedPath.push_back(_PathData(ed.id, _queryData.nodeHelpDesk->getNameIndexFromEdgeID(ed.id), _queryData.nodeHelpDesk->getTurnInstructionFromEdgeID(ed.id), ed.distance) );
+        // there is no equivalent to a node-based node in an edge-expanded graph.
+        // two equivalent routes may start (or end) at different node-based edges
+        // as they are added with the offset how much "distance" on the edge
+        // has already been traversed. Depending on offset one needs to remove
+        // the last node.
+        if (unpacked_path.size() > 1)
+        {
+            const unsigned last_index = unpacked_path.size() - 1;
+            const unsigned second_to_last_index = last_index - 1;
+
+            // looks like a trivially true check but tests for underflow
+            BOOST_ASSERT(last_index > second_to_last_index);
+
+            if (unpacked_path[last_index].node == unpacked_path[second_to_last_index].node)
+            {
+                unpacked_path.pop_back();
             }
+            BOOST_ASSERT(!unpacked_path.empty());
         }
     }
 
-    inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpackedPath) const {
-        std::stack<std::pair<NodeID, NodeID> > recursionStack;
-        recursionStack.push(std::make_pair(s,t));
+    inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> &unpacked_path) const
+    {
+        std::stack<std::pair<NodeID, NodeID>> recursion_stack;
+        recursion_stack.emplace(s, t);
 
         std::pair<NodeID, NodeID> edge;
-        while(!recursionStack.empty()) {
-            edge = recursionStack.top();
-            recursionStack.pop();
-
-            typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
-            int smallestWeight = INT_MAX;
-            for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){
-                const int weight = _queryData.graph->GetEdgeData(eit).distance;
-                if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
-                    smallestEdge = eit;
-                    smallestWeight = weight;
+        while (!recursion_stack.empty())
+        {
+            edge = recursion_stack.top();
+            recursion_stack.pop();
+
+            EdgeID smaller_edge_id = SPECIAL_EDGEID;
+            int edge_weight = INT_MAX;
+            for (auto edge_id : facade->GetAdjacentEdgeRange(edge.first))
+            {
+                const int weight = facade->GetEdgeData(edge_id).distance;
+                if ((facade->GetTarget(edge_id) == edge.second) && (weight < edge_weight) &&
+                    facade->GetEdgeData(edge_id).forward)
+                {
+                    smaller_edge_id = edge_id;
+                    edge_weight = weight;
                 }
             }
 
-            if(smallestEdge == SPECIAL_EDGEID){
-                for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){
-                    const int weight = _queryData.graph->GetEdgeData(eit).distance;
-                    if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
-                        smallestEdge = eit;
-                        smallestWeight = weight;
+            if (SPECIAL_EDGEID == smaller_edge_id)
+            {
+                for (auto edge_id : facade->GetAdjacentEdgeRange(edge.second))
+                {
+                    const int weight = facade->GetEdgeData(edge_id).distance;
+                    if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) &&
+                        facade->GetEdgeData(edge_id).backward)
+                    {
+                        smaller_edge_id = edge_id;
+                        edge_weight = weight;
                     }
                 }
             }
-            assert(smallestWeight != INT_MAX);
-
-            const typename QueryDataT::Graph::EdgeData& ed = _queryData.graph->GetEdgeData(smallestEdge);
-            if(ed.shortcut) {//unpack
-                const NodeID middle = ed.id;
-                //again, we need to this in reversed order
-                recursionStack.push(std::make_pair(middle, edge.second));
-                recursionStack.push(std::make_pair(edge.first, middle));
-            } else {
-                assert(!ed.shortcut);
-                unpackedPath.push_back(edge.first );
+            BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge weight invalid");
+
+            const EdgeData &ed = facade->GetEdgeData(smaller_edge_id);
+            if (ed.shortcut)
+            { // unpack
+                const NodeID middle_node_id = ed.id;
+                // again, we need to this in reversed order
+                recursion_stack.emplace(middle_node_id, edge.second);
+                recursion_stack.emplace(edge.first, middle_node_id);
+            }
+            else
+            {
+                BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut");
+                unpacked_path.emplace_back(edge.first);
             }
         }
-        unpackedPath.push_back(t);
+        unpacked_path.emplace_back(t);
     }
 
-    inline void RetrievePackedPathFromHeap(typename QueryDataT::QueryHeap & _fHeap, typename QueryDataT::QueryHeap & _bHeap, const NodeID middle, std::vector<NodeID>& packedPath) const {
-        NodeID pathNode = middle;
-        while(pathNode != _fHeap.GetData(pathNode).parent) {
-            pathNode = _fHeap.GetData(pathNode).parent;
-            packedPath.push_back(pathNode);
+    inline void RetrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap,
+                                           const SearchEngineData::QueryHeap &reverse_heap,
+                                           const NodeID middle_node_id,
+                                           std::vector<NodeID> &packed_path) const
+    {
+        NodeID current_node_id = middle_node_id;
+        while (current_node_id != forward_heap.GetData(current_node_id).parent)
+        {
+            current_node_id = forward_heap.GetData(current_node_id).parent;
+            packed_path.emplace_back(current_node_id);
+        }
+        std::reverse(packed_path.begin(), packed_path.end());
+        packed_path.emplace_back(middle_node_id);
+        current_node_id = middle_node_id;
+        while (current_node_id != reverse_heap.GetData(current_node_id).parent)
+        {
+            current_node_id = reverse_heap.GetData(current_node_id).parent;
+            packed_path.emplace_back(current_node_id);
         }
-
-        std::reverse(packedPath.begin(), packedPath.end());
-        packedPath.push_back(middle);
-        pathNode = middle;
-        while (pathNode != _bHeap.GetData(pathNode).parent){
-            pathNode = _bHeap.GetData(pathNode).parent;
-            packedPath.push_back(pathNode);
-    	}
     }
 
-    inline void RetrievePackedPathFromSingleHeap(typename QueryDataT::QueryHeap & search_heap, const NodeID middle, std::vector<NodeID>& packed_path) const {
-        NodeID pathNode = middle;
-        while(pathNode != search_heap.GetData(pathNode).parent) {
-            pathNode = search_heap.GetData(pathNode).parent;
-            packed_path.push_back(pathNode);
+    inline void RetrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap,
+                                                 const NodeID middle_node_id,
+                                                 std::vector<NodeID> &packed_path) const
+    {
+        NodeID current_node_id = middle_node_id;
+        while (current_node_id != search_heap.GetData(current_node_id).parent)
+        {
+            current_node_id = search_heap.GetData(current_node_id).parent;
+            packed_path.emplace_back(current_node_id);
         }
     }
 };
 
-
-#endif /* BASICROUTINGINTERFACE_H_ */
+#endif // BASIC_ROUTING_INTERFACE_H
diff --git a/RoutingAlgorithms/ManyToManyRouting.h b/RoutingAlgorithms/ManyToManyRouting.h
new file mode 100644
index 0000000..7819c67
--- /dev/null
+++ b/RoutingAlgorithms/ManyToManyRouting.h
@@ -0,0 +1,264 @@
+/*
+
+Copyright (c) 2014, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef MANY_TO_MANY_ROUTING_H
+#define MANY_TO_MANY_ROUTING_H
+
+#include "BasicRoutingInterface.h"
+#include "../DataStructures/SearchEngineData.h"
+#include "../typedefs.h"
+
+#include <boost/assert.hpp>
+
+#include <limits>
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+template <class DataFacadeT> class ManyToManyRouting : public BasicRoutingInterface<DataFacadeT>
+{
+    typedef BasicRoutingInterface<DataFacadeT> super;
+    typedef SearchEngineData::QueryHeap QueryHeap;
+    SearchEngineData &engine_working_data;
+
+    struct NodeBucket
+    {
+        unsigned target_id; // essentially a row in the distance matrix
+        EdgeWeight distance;
+        NodeBucket(const unsigned target_id, const EdgeWeight distance)
+            : target_id(target_id), distance(distance)
+        {
+        }
+    };
+    typedef std::unordered_map<NodeID, std::vector<NodeBucket>> SearchSpaceWithBuckets;
+
+  public:
+    ManyToManyRouting(DataFacadeT *facade, SearchEngineData &engine_working_data)
+        : super(facade), engine_working_data(engine_working_data)
+    {
+    }
+
+    ~ManyToManyRouting() {}
+
+    std::shared_ptr<std::vector<EdgeWeight>> operator()(const PhantomNodeArray &phantom_nodes_array)
+        const
+    {
+        const unsigned number_of_locations = static_cast<unsigned>(phantom_nodes_array.size());
+        std::shared_ptr<std::vector<EdgeWeight>> result_table =
+            std::make_shared<std::vector<EdgeWeight>>(number_of_locations * number_of_locations,
+                                                      std::numeric_limits<EdgeWeight>::max());
+
+        engine_working_data.InitializeOrClearFirstThreadLocalStorage(
+            super::facade->GetNumberOfNodes());
+
+        QueryHeap &query_heap = *(engine_working_data.forwardHeap);
+
+        SearchSpaceWithBuckets search_space_with_buckets;
+
+        unsigned target_id = 0;
+        for (const std::vector<PhantomNode> &phantom_node_vector : phantom_nodes_array)
+        {
+            query_heap.Clear();
+            // insert target(s) at distance 0
+
+            for (const PhantomNode &phantom_node : phantom_node_vector)
+            {
+                if (SPECIAL_NODEID != phantom_node.forward_node_id)
+                {
+                    query_heap.Insert(phantom_node.forward_node_id,
+                                      phantom_node.GetForwardWeightPlusOffset(),
+                                      phantom_node.forward_node_id);
+                }
+                if (SPECIAL_NODEID != phantom_node.reverse_node_id)
+                {
+                    query_heap.Insert(phantom_node.reverse_node_id,
+                                      phantom_node.GetReverseWeightPlusOffset(),
+                                      phantom_node.reverse_node_id);
+                }
+            }
+
+            // explore search space
+            while (!query_heap.Empty())
+            {
+                BackwardRoutingStep(target_id, query_heap, search_space_with_buckets);
+            }
+            ++target_id;
+        }
+
+        // for each source do forward search
+        unsigned source_id = 0;
+        for (const std::vector<PhantomNode> &phantom_node_vector : phantom_nodes_array)
+        {
+            query_heap.Clear();
+            for (const PhantomNode &phantom_node : phantom_node_vector)
+            {
+                // insert sources at distance 0
+                if (SPECIAL_NODEID != phantom_node.forward_node_id)
+                {
+                    query_heap.Insert(phantom_node.forward_node_id,
+                                      -phantom_node.GetForwardWeightPlusOffset(),
+                                      phantom_node.forward_node_id);
+                }
+                if (SPECIAL_NODEID != phantom_node.reverse_node_id)
+                {
+                    query_heap.Insert(phantom_node.reverse_node_id,
+                                      -phantom_node.GetReverseWeightPlusOffset(),
+                                      phantom_node.reverse_node_id);
+                }
+            }
+
+            // explore search space
+            while (!query_heap.Empty())
+            {
+                ForwardRoutingStep(source_id,
+                                   number_of_locations,
+                                   query_heap,
+                                   search_space_with_buckets,
+                                   result_table);
+            }
+
+            ++source_id;
+        }
+        BOOST_ASSERT(source_id == target_id);
+        return result_table;
+    }
+
+    void ForwardRoutingStep(const unsigned source_id,
+                            const unsigned number_of_locations,
+                            QueryHeap &query_heap,
+                            const SearchSpaceWithBuckets &search_space_with_buckets,
+                            std::shared_ptr<std::vector<EdgeWeight>> result_table) const
+    {
+        const NodeID node = query_heap.DeleteMin();
+        const int source_distance = query_heap.GetKey(node);
+
+        // check if each encountered node has an entry
+        const auto bucket_iterator = search_space_with_buckets.find(node);
+        // iterate bucket if there exists one
+        if (bucket_iterator != search_space_with_buckets.end())
+        {
+            const std::vector<NodeBucket> &bucket_list = bucket_iterator->second;
+            for (const NodeBucket &current_bucket : bucket_list)
+            {
+                // get target id from bucket entry
+                const unsigned target_id = current_bucket.target_id;
+                const int target_distance = current_bucket.distance;
+                const EdgeWeight current_distance =
+                    (*result_table)[source_id * number_of_locations + target_id];
+                // check if new distance is better
+                const EdgeWeight new_distance = source_distance + target_distance;
+                if (new_distance >= 0 && new_distance < current_distance)
+                {
+                    (*result_table)[source_id * number_of_locations + target_id] =
+                        (source_distance + target_distance);
+                }
+            }
+        }
+        if (StallAtNode<true>(node, source_distance, query_heap))
+        {
+            return;
+        }
+        RelaxOutgoingEdges<true>(node, source_distance, query_heap);
+    }
+
+    void BackwardRoutingStep(const unsigned target_id,
+                             QueryHeap &query_heap,
+                             SearchSpaceWithBuckets &search_space_with_buckets) const
+    {
+        const NodeID node = query_heap.DeleteMin();
+        const int target_distance = query_heap.GetKey(node);
+
+        // store settled nodes in search space bucket
+        search_space_with_buckets[node].emplace_back(target_id, target_distance);
+
+        if (StallAtNode<false>(node, target_distance, query_heap))
+        {
+            return;
+        }
+
+        RelaxOutgoingEdges<false>(node, target_distance, query_heap);
+    }
+
+    template <bool forward_direction>
+    inline void
+    RelaxOutgoingEdges(const NodeID node, const EdgeWeight distance, QueryHeap &query_heap) const
+    {
+        for (auto edge : super::facade->GetAdjacentEdgeRange(node))
+        {
+            const auto &data = super::facade->GetEdgeData(edge);
+            const bool direction_flag = (forward_direction ? data.forward : data.backward);
+            if (direction_flag)
+            {
+                const NodeID to = super::facade->GetTarget(edge);
+                const int edge_weight = data.distance;
+
+                BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
+                const int to_distance = distance + edge_weight;
+
+                // New Node discovered -> Add to Heap + Node Info Storage
+                if (!query_heap.WasInserted(to))
+                {
+                    query_heap.Insert(to, to_distance, node);
+                }
+                // Found a shorter Path -> Update distance
+                else if (to_distance < query_heap.GetKey(to))
+                {
+                    // new parent
+                    query_heap.GetData(to).parent = node;
+                    query_heap.DecreaseKey(to, to_distance);
+                }
+            }
+        }
+    }
+
+    // Stalling
+    template <bool forward_direction>
+    inline bool StallAtNode(const NodeID node, const EdgeWeight distance, QueryHeap &query_heap)
+        const
+    {
+        for (auto edge : super::facade->GetAdjacentEdgeRange(node))
+        {
+            const auto &data = super::facade->GetEdgeData(edge);
+            const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
+            if (reverse_flag)
+            {
+                const NodeID to = super::facade->GetTarget(edge);
+                const int edge_weight = data.distance;
+                BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
+                if (query_heap.WasInserted(to))
+                {
+                    if (query_heap.GetKey(to) + edge_weight < distance)
+                    {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+};
+#endif
diff --git a/RoutingAlgorithms/ShortestPathRouting.h b/RoutingAlgorithms/ShortestPathRouting.h
index 472e7dd..cc5afe5 100644
--- a/RoutingAlgorithms/ShortestPathRouting.h
+++ b/RoutingAlgorithms/ShortestPathRouting.h
@@ -1,201 +1,318 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+*/
 
-#ifndef SHORTESTPATHROUTING_H_
-#define SHORTESTPATHROUTING_H_
+#ifndef SHORTEST_PATH_ROUTING_H
+#define SHORTEST_PATH_ROUTING_H
+
+#include <boost/assert.hpp>
 
 #include "BasicRoutingInterface.h"
+#include "../DataStructures/SearchEngineData.h"
+#include "../typedefs.h"
+
+template <class DataFacadeT> class ShortestPathRouting : public BasicRoutingInterface<DataFacadeT>
+{
+    typedef BasicRoutingInterface<DataFacadeT> super;
+    typedef SearchEngineData::QueryHeap QueryHeap;
+    SearchEngineData &engine_working_data;
 
-template<class QueryDataT>
-class ShortestPathRouting : public BasicRoutingInterface<QueryDataT>{
-    typedef BasicRoutingInterface<QueryDataT> super;
-    typedef typename QueryDataT::QueryHeap QueryHeap;
-public:
-    ShortestPathRouting( QueryDataT & qd) : super(qd) {}
+  public:
+    ShortestPathRouting(DataFacadeT *facade, SearchEngineData &engine_working_data)
+        : super(facade), engine_working_data(engine_working_data)
+    {
+    }
 
     ~ShortestPathRouting() {}
 
-    void operator()(std::vector<PhantomNodes> & phantomNodesVector,  RawRouteData & rawRouteData) const {
-        BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
-            if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX()) {
-                rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
-                return;
-            }
-        }
+    void operator()(const std::vector<PhantomNodes> &phantom_nodes_vector,
+                    RawRouteData &raw_route_data) const
+    {
         int distance1 = 0;
         int distance2 = 0;
-
-        bool searchFrom1stStartNode = true;
-        bool searchFrom2ndStartNode = true;
+        bool search_from_1st_node = true;
+        bool search_from_2nd_node = true;
         NodeID middle1 = UINT_MAX;
         NodeID middle2 = UINT_MAX;
-        std::vector<NodeID> packedPath1;
-        std::vector<NodeID> packedPath2;
+        std::vector<std::vector<NodeID>> packed_legs1(phantom_nodes_vector.size());
+        std::vector<std::vector<NodeID>> packed_legs2(phantom_nodes_vector.size());
 
-        super::_queryData.InitializeOrClearFirstThreadLocalStorage();
-        super::_queryData.InitializeOrClearSecondThreadLocalStorage();
-        super::_queryData.InitializeOrClearThirdThreadLocalStorage();
+        engine_working_data.InitializeOrClearFirstThreadLocalStorage(
+            super::facade->GetNumberOfNodes());
+        engine_working_data.InitializeOrClearSecondThreadLocalStorage(
+            super::facade->GetNumberOfNodes());
+        engine_working_data.InitializeOrClearThirdThreadLocalStorage(
+            super::facade->GetNumberOfNodes());
 
-        QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap);
-        QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap);
-        QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2);
-        QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2);
+        QueryHeap &forward_heap1 = *(engine_working_data.forwardHeap);
+        QueryHeap &reverse_heap1 = *(engine_working_data.backwardHeap);
+        QueryHeap &forward_heap2 = *(engine_working_data.forwardHeap2);
+        QueryHeap &reverse_heap2 = *(engine_working_data.backwardHeap2);
 
-        //Get distance to next pair of target nodes.
-        BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
-            forward_heap1.Clear();	forward_heap2.Clear();
-            reverse_heap1.Clear();	reverse_heap2.Clear();
-            int _localUpperbound1 = INT_MAX;
-            int _localUpperbound2 = INT_MAX;
+        int current_leg = 0;
+        // Get distance to next pair of target nodes.
+        for (const PhantomNodes &phantom_node_pair : phantom_nodes_vector)
+        {
+            forward_heap1.Clear();
+            forward_heap2.Clear();
+            reverse_heap1.Clear();
+            reverse_heap2.Clear();
+            int local_upper_bound1 = INT_MAX;
+            int local_upper_bound2 = INT_MAX;
 
             middle1 = UINT_MAX;
             middle2 = UINT_MAX;
 
-            //insert new starting nodes into forward heap, adjusted by previous distances.
-            if(searchFrom1stStartNode) {
-                forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
-                INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
-                forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
-                INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
-           }
-            if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) {
-                forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
-                INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
-                forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
-                INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
-            }
-
-            //insert new backward nodes into backward heap, unadjusted.
-            reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
-            INFO("rv1: " << phantomNodePair.targetPhantom.edgeBasedNode << ", w;" << phantomNodePair.targetPhantom.weight1 );
-            if(phantomNodePair.targetPhantom.isBidirected() ) {
-                reverse_heap2.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
-                INFO("rv2: " << phantomNodePair.targetPhantom.edgeBasedNode+1 << ", w;" << phantomNodePair.targetPhantom.weight2 );
-           }
-            const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
-            const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0);
-
-            //run two-Target Dijkstra routing step.
-            while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){
-                if(0 < forward_heap1.Size()){
-                    super::RoutingStep(forward_heap1, reverse_heap1, &middle1, &_localUpperbound1, forward_offset, true);
+            // insert new starting nodes into forward heap, adjusted by previous distances.
+            if (search_from_1st_node &&
+                phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID)
+            {
+                forward_heap1.Insert(
+                    phantom_node_pair.source_phantom.forward_node_id,
+                    distance1 - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
+                    phantom_node_pair.source_phantom.forward_node_id);
+                forward_heap2.Insert(
+                    phantom_node_pair.source_phantom.forward_node_id,
+                    distance1 - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
+                    phantom_node_pair.source_phantom.forward_node_id);
+            }
+            if (search_from_2nd_node &&
+                phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID)
+            {
+                forward_heap1.Insert(
+                    phantom_node_pair.source_phantom.reverse_node_id,
+                    distance2 - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
+                    phantom_node_pair.source_phantom.reverse_node_id);
+                forward_heap2.Insert(
+                    phantom_node_pair.source_phantom.reverse_node_id,
+                    distance2 - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
+                    phantom_node_pair.source_phantom.reverse_node_id);
+            }
+
+            // insert new backward nodes into backward heap, unadjusted.
+            if (phantom_node_pair.target_phantom.forward_node_id != SPECIAL_NODEID)
+            {
+                reverse_heap1.Insert(phantom_node_pair.target_phantom.forward_node_id,
+                                     phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(),
+                                     phantom_node_pair.target_phantom.forward_node_id);
+            }
+
+            if (phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID)
+            {
+                reverse_heap2.Insert(phantom_node_pair.target_phantom.reverse_node_id,
+                                     phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(),
+                                     phantom_node_pair.target_phantom.reverse_node_id);
+            }
+
+            // run two-Target Dijkstra routing step.
+            while (0 < (forward_heap1.Size() + reverse_heap1.Size()))
+            {
+                if (0 < forward_heap1.Size())
+                {
+                    super::RoutingStep(
+                        forward_heap1, reverse_heap1, &middle1, &local_upper_bound1, true);
                 }
-                if(0 < reverse_heap1.Size() ){
-                    super::RoutingStep(reverse_heap1, forward_heap1, &middle1, &_localUpperbound1, reverse_offset, false);
+                if (0 < reverse_heap1.Size())
+                {
+                    super::RoutingStep(
+                        reverse_heap1, forward_heap1, &middle1, &local_upper_bound1, false);
                 }
             }
-            if(0 < reverse_heap2.Size()) {
-                while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
-                    if(0 < forward_heap2.Size()){
-                        super::RoutingStep(forward_heap2, reverse_heap2, &middle2, &_localUpperbound2, forward_offset, true);
+
+            if (!reverse_heap2.Empty())
+            {
+                while (0 < (forward_heap2.Size() + reverse_heap2.Size()))
+                {
+                    if (0 < forward_heap2.Size())
+                    {
+                        super::RoutingStep(
+                            forward_heap2, reverse_heap2, &middle2, &local_upper_bound2, true);
                     }
-                    if(0 < reverse_heap2.Size()){
-                        super::RoutingStep(reverse_heap2, forward_heap2, &middle2, &_localUpperbound2, reverse_offset, false);
+                    if (0 < reverse_heap2.Size())
+                    {
+                        super::RoutingStep(
+                            reverse_heap2, forward_heap2, &middle2, &local_upper_bound2, false);
                     }
                 }
             }
 
-            //No path found for both target nodes?
-            if((INT_MAX == _localUpperbound1) && (INT_MAX == _localUpperbound2)) {
-                rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
+            // No path found for both target nodes?
+            if ((INVALID_EDGE_WEIGHT == local_upper_bound1) &&
+                (INVALID_EDGE_WEIGHT == local_upper_bound2))
+            {
+                raw_route_data.shortest_path_length = INVALID_EDGE_WEIGHT;
+                raw_route_data.alternative_path_length = INVALID_EDGE_WEIGHT;
                 return;
             }
-            if(UINT_MAX == middle1) {
-                searchFrom1stStartNode = false;
+
+            search_from_1st_node = true;
+            search_from_2nd_node = true;
+            if (SPECIAL_NODEID == middle1)
+            {
+                search_from_1st_node = false;
             }
-            if(UINT_MAX == middle2) {
-                searchFrom2ndStartNode = false;
+            if (SPECIAL_NODEID == middle2)
+            {
+                search_from_2nd_node = false;
             }
 
-            //Was at most one of the two paths not found?
-            assert(!(INT_MAX == distance1 && INT_MAX == distance2));
+            // Was at most one of the two paths not found?
+            BOOST_ASSERT_MSG((INT_MAX != distance1 || INT_MAX != distance2), "no path found");
+
+            // Unpack paths if they exist
+            std::vector<NodeID> temporary_packed_leg1;
+            std::vector<NodeID> temporary_packed_leg2;
 
-            //Unpack paths if they exist
-            std::vector<NodeID> temporaryPackedPath1;
-            std::vector<NodeID> temporaryPackedPath2;
-            if(INT_MAX != _localUpperbound1) {
-                super::RetrievePackedPathFromHeap(forward_heap1, reverse_heap1, middle1, temporaryPackedPath1);
+            BOOST_ASSERT((unsigned)current_leg < packed_legs1.size());
+            BOOST_ASSERT((unsigned)current_leg < packed_legs2.size());
+
+            if (INVALID_EDGE_WEIGHT != local_upper_bound1)
+            {
+                super::RetrievePackedPathFromHeap(
+                    forward_heap1, reverse_heap1, middle1, temporary_packed_leg1);
             }
 
-            if(INT_MAX != _localUpperbound2) {
-                super::RetrievePackedPathFromHeap(forward_heap2, reverse_heap2, middle2, temporaryPackedPath2);
+            if (INVALID_EDGE_WEIGHT != local_upper_bound2)
+            {
+                super::RetrievePackedPathFromHeap(
+                    forward_heap2, reverse_heap2, middle2, temporary_packed_leg2);
             }
 
-            //if one of the paths was not found, replace it with the other one.
-            if(0 == temporaryPackedPath1.size()) {
-                temporaryPackedPath1.insert(temporaryPackedPath1.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
-                _localUpperbound1 = _localUpperbound2;
+            // if one of the paths was not found, replace it with the other one.
+            if (temporary_packed_leg1.empty())
+            {
+                temporary_packed_leg1.insert(temporary_packed_leg1.end(),
+                                             temporary_packed_leg2.begin(),
+                                             temporary_packed_leg2.end());
+                local_upper_bound1 = local_upper_bound2;
             }
-            if(0 == temporaryPackedPath2.size()) {
-                temporaryPackedPath2.insert(temporaryPackedPath2.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
-                _localUpperbound2 = _localUpperbound1;
+            if (temporary_packed_leg2.empty())
+            {
+                temporary_packed_leg2.insert(temporary_packed_leg2.end(),
+                                             temporary_packed_leg1.begin(),
+                                             temporary_packed_leg1.end());
+                local_upper_bound2 = local_upper_bound1;
             }
 
-            assert(0 < temporaryPackedPath1.size() && 0 < temporaryPackedPath2.size());
+            BOOST_ASSERT_MSG(!temporary_packed_leg1.empty() || !temporary_packed_leg2.empty(),
+                             "tempory packed paths empty");
+
+            BOOST_ASSERT((0 == current_leg) || !packed_legs1[current_leg - 1].empty());
+            BOOST_ASSERT((0 == current_leg) || !packed_legs2[current_leg - 1].empty());
 
-            //Plug paths together, s.t. end of packed path is begin of temporary packed path
-            if(0 < packedPath1.size() && 0 < packedPath2.size() ) {
-                if( *(temporaryPackedPath1.begin()) == *(temporaryPackedPath2.begin())) {
-                    //both new route segments start with the same node, thus one of the packedPath must go.
-                    assert( (packedPath1.size() == packedPath2.size() ) || (*(packedPath1.end()-1) != *(packedPath2.end()-1)) );
-                    if( *(packedPath1.end()-1) == *(temporaryPackedPath1.begin())) {
-                        packedPath2.clear();
-                        packedPath2.insert(packedPath2.end(), packedPath1.begin(), packedPath1.end());
-                        distance2 = distance1;
-                    } else {
-                        packedPath1.clear();
-                        packedPath1.insert(packedPath1.end(), packedPath2.begin(), packedPath2.end());
-                        distance1 = distance2;
+            if (0 < current_leg)
+            {
+                const NodeID end_id_of_segment1 = packed_legs1[current_leg - 1].back();
+                const NodeID end_id_of_segment2 = packed_legs2[current_leg - 1].back();
+                BOOST_ASSERT(!temporary_packed_leg1.empty());
+                const NodeID start_id_of_leg1 = temporary_packed_leg1.front();
+                const NodeID start_id_of_leg2 = temporary_packed_leg2.front();
+                if ((end_id_of_segment1 != start_id_of_leg1) &&
+                    (end_id_of_segment2 != start_id_of_leg2))
+                {
+                    std::swap(temporary_packed_leg1, temporary_packed_leg2);
+                    std::swap(local_upper_bound1, local_upper_bound2);
+                }
+            }
+
+            // remove the shorter path if both legs end at the same segment
+            if (0 < current_leg)
+            {
+                const NodeID start_id_of_leg1 = temporary_packed_leg1.front();
+                const NodeID start_id_of_leg2 = temporary_packed_leg2.front();
+                if (start_id_of_leg1 == start_id_of_leg2)
+                {
+                    const NodeID last_id_of_packed_legs1 = packed_legs1[current_leg - 1].back();
+                    const NodeID last_id_of_packed_legs2 = packed_legs2[current_leg - 1].back();
+                    if (start_id_of_leg1 != last_id_of_packed_legs1)
+                    {
+                        packed_legs1 = packed_legs2;
+                        BOOST_ASSERT(start_id_of_leg1 == temporary_packed_leg1.front());
                     }
-                } else  {
-                    //packed paths 1 and 2 may need to switch.
-                    if(*(packedPath1.end()-1) != *(temporaryPackedPath1.begin())) {
-                        packedPath1.swap(packedPath2);
-                        std::swap(distance1, distance2);
+                    else if (start_id_of_leg2 != last_id_of_packed_legs2)
+                    {
+                        packed_legs2 = packed_legs1;
+                        BOOST_ASSERT(start_id_of_leg2 == temporary_packed_leg2.front());
                     }
                 }
             }
-            packedPath1.insert(packedPath1.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
-            packedPath2.insert(packedPath2.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
+            BOOST_ASSERT(packed_legs1.size() == packed_legs2.size());
 
-            if( (packedPath1.back() == packedPath2.back()) && phantomNodePair.targetPhantom.isBidirected() ) {
+            packed_legs1[current_leg].insert(packed_legs1[current_leg].end(),
+                                             temporary_packed_leg1.begin(),
+                                             temporary_packed_leg1.end());
+            BOOST_ASSERT(packed_legs1[current_leg].size() == temporary_packed_leg1.size());
+            packed_legs2[current_leg].insert(packed_legs2[current_leg].end(),
+                                             temporary_packed_leg2.begin(),
+                                             temporary_packed_leg2.end());
+            BOOST_ASSERT(packed_legs2[current_leg].size() == temporary_packed_leg2.size());
 
-                NodeID lastNodeID = packedPath2.back();
-                searchFrom1stStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode+1);
-                searchFrom2ndStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode);
+            if ((packed_legs1[current_leg].back() == packed_legs2[current_leg].back()) &&
+                phantom_node_pair.target_phantom.isBidirected())
+            {
+                const NodeID last_node_id = packed_legs2[current_leg].back();
+                search_from_1st_node &=
+                    !(last_node_id == phantom_node_pair.target_phantom.reverse_node_id);
+                search_from_2nd_node &=
+                    !(last_node_id == phantom_node_pair.target_phantom.forward_node_id);
+                BOOST_ASSERT(search_from_1st_node != search_from_2nd_node);
             }
 
-            distance1 += _localUpperbound1;
-            distance2 += _localUpperbound2;
+            distance1 = local_upper_bound1;
+            distance2 = local_upper_bound2;
+            ++current_leg;
+        }
+
+        if (distance1 > distance2)
+        {
+            std::swap(packed_legs1, packed_legs2);
         }
+        raw_route_data.unpacked_path_segments.resize(packed_legs1.size());
+
+        for (unsigned i = 0; i < packed_legs1.size(); ++i)
+        {
+            BOOST_ASSERT(!phantom_nodes_vector.empty());
+            BOOST_ASSERT(packed_legs1.size() == raw_route_data.unpacked_path_segments.size());
+
+            PhantomNodes unpack_phantom_node_pair = phantom_nodes_vector[i];
+            super::UnpackPath(
+                // -- packed input
+                packed_legs1[i],
+                // -- start and end of (sub-)route
+                unpack_phantom_node_pair,
+                // -- unpacked output
+                raw_route_data.unpacked_path_segments[i]);
 
-        if(distance1 > distance2){
-            std::swap(packedPath1, packedPath2);
+            raw_route_data.source_traversed_in_reverse.push_back(
+            (packed_legs1[i].front() != phantom_nodes_vector[i].source_phantom.forward_node_id));
+            raw_route_data.target_traversed_in_reverse.push_back(
+            (packed_legs1[i].back() != phantom_nodes_vector[i].target_phantom.forward_node_id));
         }
-        remove_consecutive_duplicates_from_vector(packedPath1);
-        super::UnpackPath(packedPath1, rawRouteData.computedShortestPath);
-        rawRouteData.lengthOfShortestPath = std::min(distance1, distance2);
-        return;
+        raw_route_data.shortest_path_length = std::min(distance1, distance2);
     }
 };
 
-#endif /* SHORTESTPATHROUTING_H_ */
+#endif /* SHORTEST_PATH_ROUTING_H */
diff --git a/Server/APIGrammar.h b/Server/APIGrammar.h
index 3b87941..4c339d0 100644
--- a/Server/APIGrammar.h
+++ b/Server/APIGrammar.h
@@ -1,24 +1,29 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+*/
 
 #ifndef APIGRAMMAR_H_
 #define APIGRAMMAR_H_
@@ -30,15 +35,17 @@ or see http://www.gnu.org/licenses/agpl.txt.
 namespace qi = boost::spirit::qi;
 
 template <typename Iterator, class HandlerT>
-struct APIGrammar : qi::grammar<Iterator> {
-    APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) {
+struct APIGrammar : qi::grammar<Iterator>
+{
+    explicit APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h)
+    {
         api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query);
         query    = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | geometry | alt_route | old_API) ) ;
 
         zoom        = (-qi::lit('&')) >> qi::lit('z')            >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)];
         output      = (-qi::lit('&')) >> qi::lit("output")       >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)];
-        jsonp       = (-qi::lit('&')) >> qi::lit("jsonp")        >> '=' >> stringwithDot[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)];
-        checksum    = (-qi::lit('&')) >> qi::lit("checksum")     >> '=' >> qi::int_[boost::bind(&HandlerT::setChecksum, handler, ::_1)];
+        jsonp       = (-qi::lit('&')) >> qi::lit("jsonp")        >> '=' >> stringwithPercent[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)];
+        checksum    = (-qi::lit('&')) >> qi::lit("checksum")     >> '=' >> qi::uint_[boost::bind(&HandlerT::setChecksum, handler, ::_1)];
         instruction = (-qi::lit('&')) >> qi::lit("instructions") >> '=' >> qi::bool_[boost::bind(&HandlerT::setInstructionFlag, handler, ::_1)];
         geometry    = (-qi::lit('&')) >> qi::lit("geometry")     >> '=' >> qi::bool_[boost::bind(&HandlerT::setGeometryFlag, handler, ::_1)];
         cmp         = (-qi::lit('&')) >> qi::lit("compression")  >> '=' >> qi::bool_[boost::bind(&HandlerT::setCompressionFlag, handler, ::_1)];
@@ -48,16 +55,17 @@ struct APIGrammar : qi::grammar<Iterator> {
         alt_route   = (-qi::lit('&')) >> qi::lit("alt")          >> '=' >> qi::bool_[boost::bind(&HandlerT::setAlternateRouteFlag, handler, ::_1)];
         old_API     = (-qi::lit('&')) >> qi::lit("geomformat")   >> '=' >> string[boost::bind(&HandlerT::setDeprecatedAPIFlag, handler, ::_1)];
 
-        string        = +(qi::char_("a-zA-Z"));
-        stringwithDot = +(qi::char_("a-zA-Z0-9_.-"));
+        string            = +(qi::char_("a-zA-Z"));
+        stringwithDot     = +(qi::char_("a-zA-Z0-9_.-"));
+        stringwithPercent = +(qi::char_("a-zA-Z0-9_.-") | qi::char_('[') | qi::char_(']') | (qi::char_('%') >> qi::char_("0-9A-Z") >> qi::char_("0-9A-Z") ));
     }
+
     qi::rule<Iterator> api_call, query;
     qi::rule<Iterator, std::string()> service, zoom, output, string, jsonp, checksum, location, hint,
-                                      stringwithDot, language, instruction, geometry,
+                                      stringwithDot, stringwithPercent, language, instruction, geometry,
                                       cmp, alt_route, old_API;
 
     HandlerT * handler;
 };
 
-
 #endif /* APIGRAMMAR_H_ */
diff --git a/Server/BasicDatastructures.h b/Server/BasicDatastructures.h
deleted file mode 100644
index 366abae..0000000
--- a/Server/BasicDatastructures.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
-*/
-
-#ifndef BASIC_DATASTRUCTURES_H
-#define BASIC_DATASTRUCTURES_H
-#include <string>
-#include <sstream>
-#include <boost/foreach.hpp>
-
-#include "../Util/StringUtil.h"
-
-namespace http {
-
-const std::string okString 					= "HTTP/1.0 200 OK\r\n";
-const std::string badRequestString 			= "HTTP/1.0 400 Bad Request\r\n";
-const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
-
-const char okHTML[] 				 = "";
-const char badRequestHTML[] 		 = "<html><head><title>Bad Request</title></head><body><h1>400 Bad Request</h1></body></html>";
-const char internalServerErrorHTML[] = "<html><head><title>Internal Server Error</title></head><body><h1>500 Internal Server Error</h1></body></html>";
-const char seperators[]  			 = { ':', ' ' };
-const char crlf[]		             = { '\r', '\n' };
-
-struct Header {
-  std::string name;
-  std::string value;
-  void Clear() {
-      name.clear();
-      value.clear();
-  }
-};
-
-enum CompressionType {
-    noCompression,
-    gzipRFC1952,
-    deflateRFC1951
-} Compression;
-
-struct Request {
-	std::string uri;
-	std::string referrer;
-	std::string agent;
-	boost::asio::ip::address endpoint;
-};
-
-struct Reply {
-    Reply() : status(ok) { content.reserve(2 << 20); }
-	enum status_type {
-		ok 					= 200,
-		badRequest 		    = 400,
-		internalServerError = 500
-	} status;
-
-	std::vector<Header> headers;
-    std::vector<boost::asio::const_buffer> toBuffers();
-    std::vector<boost::asio::const_buffer> HeaderstoBuffers();
-	std::string content;
-	static Reply stockReply(status_type status);
-	void setSize(const unsigned size) {
-		BOOST_FOREACH ( Header& h,  headers) {
-			if("Content-Length" == h.name) {
-				std::string sizeString;
-				intToString(size,h.value );
-			}
-		}
-	}
-};
-
-boost::asio::const_buffer ToBuffer(Reply::status_type status) {
-	switch (status) {
-	case Reply::ok:
-		return boost::asio::buffer(okString);
-	case Reply::internalServerError:
-		return boost::asio::buffer(internalServerErrorString);
-	default:
-		return boost::asio::buffer(badRequestString);
-	}
-}
-
-std::string ToString(Reply::status_type status) {
-	switch (status) {
-	case Reply::ok:
-		return okHTML;
-	case Reply::badRequest:
-		return badRequestHTML;
-	default:
-		return internalServerErrorHTML;
-	}
-}
-
-std::vector<boost::asio::const_buffer> Reply::toBuffers(){
-	std::vector<boost::asio::const_buffer> buffers;
-	buffers.push_back(ToBuffer(status));
-	for (std::size_t i = 0; i < headers.size(); ++i) {
-		Header& h = headers[i];
-		buffers.push_back(boost::asio::buffer(h.name));
-		buffers.push_back(boost::asio::buffer(seperators));
-		buffers.push_back(boost::asio::buffer(h.value));
-		buffers.push_back(boost::asio::buffer(crlf));
-	}
-	buffers.push_back(boost::asio::buffer(crlf));
-	buffers.push_back(boost::asio::buffer(content));
-	return buffers;
-}
-
-std::vector<boost::asio::const_buffer> Reply::HeaderstoBuffers(){
-    std::vector<boost::asio::const_buffer> buffers;
-    buffers.push_back(ToBuffer(status));
-    for (std::size_t i = 0; i < headers.size(); ++i) {
-        Header& h = headers[i];
-//        std::cout << h.name << ": " << h.value << std::endl;
-        buffers.push_back(boost::asio::buffer(h.name));
-        buffers.push_back(boost::asio::buffer(seperators));
-        buffers.push_back(boost::asio::buffer(h.value));
-        buffers.push_back(boost::asio::buffer(crlf));
-    }
-    buffers.push_back(boost::asio::buffer(crlf));
-    return buffers;
-}
-
-Reply Reply::stockReply(Reply::status_type status) {
-	Reply rep;
-	rep.status = status;
-	rep.content = ToString(status);
-	rep.headers.resize(3);	
-	rep.headers[0].name = "Access-Control-Allow-Origin";
-	rep.headers[0].value = "*";
-	rep.headers[1].name = "Content-Length";
-
-    std::string s;
-    intToString(rep.content.size(), s);
-
-    rep.headers[1].value = s;
-	rep.headers[2].name = "Content-Type";
-	rep.headers[2].value = "text/html";
-	return rep;
-}
-} // namespace http
-
-#endif //BASIC_DATASTRUCTURES_H
diff --git a/Server/Connection.cpp b/Server/Connection.cpp
new file mode 100644
index 0000000..674fe62
--- /dev/null
+++ b/Server/Connection.cpp
@@ -0,0 +1,174 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "Connection.h"
+#include "RequestHandler.h"
+#include "RequestParser.h"
+
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/iostreams/filter/gzip.hpp>
+
+#include <string>
+#include <vector>
+
+namespace http
+{
+
+Connection::Connection(boost::asio::io_service &io_service, RequestHandler &handler)
+    : strand(io_service), TCP_socket(io_service), request_handler(handler)
+{
+}
+
+boost::asio::ip::tcp::socket &Connection::socket() { return TCP_socket; }
+
+/// Start the first asynchronous operation for the connection.
+void Connection::start()
+{
+    TCP_socket.async_read_some(
+        boost::asio::buffer(incoming_data_buffer),
+        strand.wrap(boost::bind(&Connection::handle_read,
+                                this->shared_from_this(),
+                                boost::asio::placeholders::error,
+                                boost::asio::placeholders::bytes_transferred)));
+}
+
+void Connection::handle_read(const boost::system::error_code &error, std::size_t bytes_transferred)
+{
+    if (error)
+    {
+        return;
+    }
+
+    // no error detected, let's parse the request
+    CompressionType compression_type(noCompression);
+    boost::tribool result;
+    boost::tie(result, boost::tuples::ignore) =
+        request_parser.Parse(request,
+                              incoming_data_buffer.data(),
+                              incoming_data_buffer.data() + bytes_transferred,
+                              &compression_type);
+
+    // the request has been parsed
+    if (result)
+    {
+        request.endpoint = TCP_socket.remote_endpoint().address();
+        request_handler.handle_request(request, reply);
+
+        // Header compression_header;
+        std::vector<char> compressed_output;
+        std::vector<boost::asio::const_buffer> output_buffer;
+
+        // compress the result w/ gzip/deflate if requested
+        switch (compression_type)
+        {
+        case deflateRFC1951:
+            // use deflate for compression
+            reply.headers.insert(reply.headers.begin(), {"Content-Encoding", "deflate"});
+            CompressBufferCollection(reply.content, compression_type, compressed_output);
+            reply.SetSize(static_cast<unsigned>(compressed_output.size()));
+            output_buffer = reply.HeaderstoBuffers();
+            output_buffer.push_back(boost::asio::buffer(compressed_output));
+            break;
+        case gzipRFC1952:
+            // use gzip for compression
+            reply.headers.insert(reply.headers.begin(), {"Content-Encoding", "gzip"});
+            CompressBufferCollection(reply.content, compression_type, compressed_output);
+            reply.SetSize(static_cast<unsigned>(compressed_output.size()));
+            output_buffer = reply.HeaderstoBuffers();
+            output_buffer.push_back(boost::asio::buffer(compressed_output));
+            break;
+        case noCompression:
+            // don't use any compression
+            reply.SetUncompressedSize();
+            output_buffer = reply.ToBuffers();
+            break;
+        }
+        // write result to stream
+        boost::asio::async_write(TCP_socket,
+                                 output_buffer,
+                                 strand.wrap(boost::bind(&Connection::handle_write,
+                                                         this->shared_from_this(),
+                                                         boost::asio::placeholders::error)));
+    }
+    else if (!result)
+    { // request is not parseable
+        reply = Reply::StockReply(Reply::badRequest);
+
+        boost::asio::async_write(TCP_socket,
+                                 reply.ToBuffers(),
+                                 strand.wrap(boost::bind(&Connection::handle_write,
+                                                         this->shared_from_this(),
+                                                         boost::asio::placeholders::error)));
+    }
+    else
+    {
+        // we don't have a result yet, so continue reading
+        TCP_socket.async_read_some(
+            boost::asio::buffer(incoming_data_buffer),
+            strand.wrap(boost::bind(&Connection::handle_read,
+                                    this->shared_from_this(),
+                                    boost::asio::placeholders::error,
+                                    boost::asio::placeholders::bytes_transferred)));
+    }
+}
+
+/// Handle completion of a write operation.
+void Connection::handle_write(const boost::system::error_code &error)
+{
+    if (!error)
+    {
+        // Initiate graceful connection closure.
+        boost::system::error_code ignore_error;
+        TCP_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignore_error);
+    }
+}
+
+void Connection::CompressBufferCollection(std::vector<char> uncompressed_data,
+                                          CompressionType compression_type,
+                                          std::vector<char> &compressed_data)
+{
+    boost::iostreams::gzip_params compression_parameters;
+
+    // there's a trade-off between speed and size. speed wins
+    compression_parameters.level = boost::iostreams::zlib::best_speed;
+    // check which compression flavor is used
+    if (deflateRFC1951 == compression_type)
+    {
+        compression_parameters.noheader = true;
+    }
+
+    BOOST_ASSERT(compressed_data.empty());
+    // plug data into boost's compression stream
+    boost::iostreams::filtering_ostream gzip_stream;
+    gzip_stream.push(boost::iostreams::gzip_compressor(compression_parameters));
+    gzip_stream.push(boost::iostreams::back_inserter(compressed_data));
+    gzip_stream.write(&uncompressed_data[0], uncompressed_data.size());
+    boost::iostreams::close(gzip_stream);
+}
+}
diff --git a/Server/Connection.h b/Server/Connection.h
index 5dd4b79..bc03c15 100644
--- a/Server/Connection.h
+++ b/Server/Connection.h
@@ -1,179 +1,104 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef CONNECTION_H
 #define CONNECTION_H
 
-#include <vector>
+#include "RequestParser.h"
+#include "Http/CompressionType.h"
+#include "Http/Request.h"
+
+#include <osrm/Reply.h>
 
-#include <boost/asio.hpp>
 #include <boost/array.hpp>
-#include <boost/bind.hpp>
-#include <boost/noncopyable.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/enable_shared_from_this.hpp>
+#include <boost/asio.hpp>
+#include <boost/config.hpp>
+#include <boost/version.hpp>
+
+ #include <memory>
+ #include <string>
+ #include <vector>
+
+//workaround for incomplete std::shared_ptr compatibility in old boost versions
+#if BOOST_VERSION < 105300 || defined BOOST_NO_CXX11_SMART_PTR
+
+namespace boost {
+template<class T>
+const T* get_pointer(std::shared_ptr<T> const& p)
+{
+    return p.get();
+}
+
+template<class T>
+T* get_pointer(std::shared_ptr<T>& p)
+{
+    return p.get();
+}
+} // namespace boost
+
+#endif
+
 
-#include "BasicDatastructures.h"
-#include "RequestHandler.h"
-#include "RequestParser.h"
 
-#include "zlib.h"
+class RequestHandler;
 
-namespace http {
+namespace http
+{
 
 /// Represents a single connection from a client.
-class Connection : public boost::enable_shared_from_this<Connection>, private boost::noncopyable {
-public:
-	explicit Connection(boost::asio::io_service& io_service, RequestHandler& handler) : strand(io_service), TCPsocket(io_service), requestHandler(handler) {}
-
-	boost::asio::ip::tcp::socket& socket() {
-		return TCPsocket;
-	}
-
-	/// Start the first asynchronous operation for the connection.
-	void start() {
-	    TCPsocket.async_read_some(boost::asio::buffer(incomingDataBuffer), strand.wrap( boost::bind(&Connection::handleRead, this->shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
-	}
-
-private:
-	void handleRead(const boost::system::error_code& e, std::size_t bytes_transferred) {
-		if (!e) {
-			CompressionType compressionType(noCompression);
-			boost::tribool result;
-			boost::tie(result, boost::tuples::ignore) = requestParser.Parse( request, incomingDataBuffer.data(), incomingDataBuffer.data() + bytes_transferred, &compressionType);
-
-			if (result) {
-				//                std::cout << "----" << std::endl;
-				//				if(compressionType == gzipRFC1952)
-				//					std::cout << "[debug] using gzip" << std::endl;
-				//				if(compressionType == deflateRFC1951)
-				//					std::cout << "[debug] using deflate" << std::endl;
-				//				if(compressionType == noCompression)
-				//					std::cout << "[debug] no compression" << std::endl;
-			    request.endpoint = TCPsocket.remote_endpoint().address();
-				requestHandler.handle_request(request, reply);
-
-				Header compressionHeader;
-				std::vector<unsigned char> compressed;
-				std::vector<boost::asio::const_buffer> outputBuffer;
-				switch(compressionType) {
-				case deflateRFC1951:
-					compressionHeader.name = "Content-Encoding";
-					compressionHeader.value = "deflate";
-					reply.headers.insert(reply.headers.begin(), compressionHeader);   //push_back(compressionHeader);
-					compressCharArray(reply.content.c_str(), reply.content.length(), compressed, compressionType);
-					reply.setSize(compressed.size());
-					outputBuffer = reply.HeaderstoBuffers();
-					outputBuffer.push_back(boost::asio::buffer(compressed));
-					boost::asio::async_write(TCPsocket, outputBuffer, strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));
-					break;
-				case gzipRFC1952:
-					compressionHeader.name = "Content-Encoding";
-					compressionHeader.value = "gzip";
-					reply.headers.insert(reply.headers.begin(), compressionHeader);
-					compressCharArray(reply.content.c_str(), reply.content.length(), compressed, compressionType);
-					reply.setSize(compressed.size());
-					outputBuffer = reply.HeaderstoBuffers();
-					outputBuffer.push_back(boost::asio::buffer(compressed));
-					boost::asio::async_write(TCPsocket, outputBuffer, strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));break;
-				case noCompression:
-					boost::asio::async_write(TCPsocket, reply.toBuffers(), strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));
-					break;
-				}
-
-			} else if (!result) {
-				reply = Reply::stockReply(Reply::badRequest);
-				boost::asio::async_write(TCPsocket, reply.toBuffers(), strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));
-			} else {
-				TCPsocket.async_read_some(boost::asio::buffer(incomingDataBuffer), strand.wrap( boost::bind(&Connection::handleRead, this->shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
-			}
-		}
-	}
-
-	/// Handle completion of a write operation.
-	void handleWrite(const boost::system::error_code& e) {
-		if (!e) {
-			// Initiate graceful connection closure.
-			boost::system::error_code ignoredEC;
-			TCPsocket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignoredEC);
-		}
-		// No new asynchronous operations are started. This means that all shared_ptr
-		// references to the connection object will disappear and the object will be
-		// destroyed automatically after this handler returns. The connection class's
-		// destructor closes the socket.
-	}
-
-	void compressCharArray(const void *in_data, size_t in_data_size, std::vector<unsigned char> &buffer, CompressionType type) {
-		const size_t BUFSIZE = 128 * 1024;
-		unsigned char temp_buffer[BUFSIZE];
-
-		z_stream strm;
-		strm.zalloc = Z_NULL;
-		strm.zfree = Z_NULL;
-		strm.opaque = Z_NULL;
-		strm.total_out = 0;
-		strm.next_in = (unsigned char *)(in_data);
-		strm.avail_in = in_data_size;
-		strm.next_out = temp_buffer;
-		strm.avail_out = BUFSIZE;
-		strm.data_type = Z_ASCII;
-
-		switch(type){
-		case deflateRFC1951:
-			deflateInit(&strm, Z_BEST_SPEED);
-			break;
-		case gzipRFC1952:
-			/*
-			 * Big thanks to deusty who explains how to have gzip compression turned on by the right call to deflateInit2():
-			 * http://deusty.blogspot.com/2007/07/gzip-compressiondecompression.html
-			 */
-			deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 9, Z_DEFAULT_STRATEGY);
-			break;
-		default:
-			assert(false);
-			break;
-		}
-
-		int deflate_res = Z_OK;
-		do {
-			if (strm.avail_out == 0) {
-				buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE);
-				strm.next_out = temp_buffer;
-				strm.avail_out = BUFSIZE;
-			}
-			deflate_res = deflate(&strm, Z_FINISH);
-
-		} while (deflate_res == Z_OK);
-
-		assert(deflate_res == Z_STREAM_END);
-		buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE - strm.avail_out);
-		deflateEnd(&strm);
-	}
-
-	boost::asio::io_service::strand strand;
-	boost::asio::ip::tcp::socket TCPsocket;
-	RequestHandler& requestHandler;
-	boost::array<char, 8192> incomingDataBuffer;
-	Request request;
-	RequestParser requestParser;
-	Reply reply;
+class Connection : public std::enable_shared_from_this<Connection>
+{
+  public:
+    explicit Connection(boost::asio::io_service &io_service, RequestHandler &handler);
+    Connection(const Connection &) = delete;
+    Connection() = delete;
+
+    boost::asio::ip::tcp::socket &socket();
+
+    /// Start the first asynchronous operation for the connection.
+    void start();
+
+  private:
+    void handle_read(const boost::system::error_code &e, std::size_t bytes_transferred);
+
+    /// Handle completion of a write operation.
+    void handle_write(const boost::system::error_code &e);
+
+    void CompressBufferCollection(std::vector<char> uncompressed_data,
+                                  CompressionType compression_type,
+                                  std::vector<char> &compressed_data);
+
+    boost::asio::io_service::strand strand;
+    boost::asio::ip::tcp::socket TCP_socket;
+    RequestHandler &request_handler;
+    boost::array<char, 8192> incoming_data_buffer;
+    Request request;
+    RequestParser request_parser;
+    Reply reply;
 };
 
 } // namespace http
diff --git a/Server/DataStructures/BaseDataFacade.h b/Server/DataStructures/BaseDataFacade.h
new file mode 100644
index 0000000..7897ca4
--- /dev/null
+++ b/Server/DataStructures/BaseDataFacade.h
@@ -0,0 +1,125 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef BASE_DATA_FACADE_H
+#define BASE_DATA_FACADE_H
+
+// Exposes all data access interfaces to the algorithms via base class ptr
+
+#include "../../DataStructures/EdgeBasedNode.h"
+#include "../../DataStructures/ImportNode.h"
+#include "../../DataStructures/PhantomNodes.h"
+#include "../../DataStructures/TurnInstructions.h"
+#include "../../Util/OSRMException.h"
+#include "../../Util/StringUtil.h"
+#include "../../typedefs.h"
+
+#include <boost/range/irange.hpp>
+
+#include <osrm/Coordinate.h>
+
+#include <string>
+
+typedef decltype(boost::irange(0u,0u)) EdgeRange;
+
+template <class EdgeDataT> class BaseDataFacade
+{
+  public:
+    typedef EdgeBasedNode RTreeLeaf;
+    typedef EdgeDataT EdgeData;
+    BaseDataFacade() {}
+    virtual ~BaseDataFacade() {}
+
+    // search graph access
+    virtual unsigned GetNumberOfNodes() const = 0;
+
+    virtual unsigned GetNumberOfEdges() const = 0;
+
+    virtual unsigned GetOutDegree(const NodeID n) const = 0;
+
+    virtual NodeID GetTarget(const EdgeID e) const = 0;
+
+    virtual EdgeDataT &GetEdgeData(const EdgeID e) = 0;
+
+    // virtual const EdgeDataT &GetEdgeData( const EdgeID e ) const = 0;
+
+    virtual EdgeID BeginEdges(const NodeID n) const = 0;
+
+    virtual EdgeID EndEdges(const NodeID n) const = 0;
+
+    virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0;
+
+    // searches for a specific edge
+    virtual EdgeID FindEdge(const NodeID from, const NodeID to) const = 0;
+
+    virtual EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const = 0;
+
+    virtual EdgeID
+    FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const = 0;
+
+    // node and edge information access
+    virtual FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const = 0;
+
+    virtual bool EdgeIsCompressed(const unsigned id) const = 0;
+
+    virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const = 0;
+
+    virtual void GetUncompressedGeometry(const unsigned id,
+                                         std::vector<unsigned> &result_nodes) const = 0;
+
+    virtual TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const = 0;
+
+    virtual bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
+                                                    FixedPointCoordinate &result,
+                                                    const unsigned zoom_level = 18) const = 0;
+
+    virtual bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
+                                              PhantomNode &resulting_phantom_node,
+                                              const unsigned zoom_level) const = 0;
+
+    virtual bool IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
+                                              std::vector<PhantomNode> &resulting_phantom_node_vector,
+                                              const unsigned zoom_level,
+                                              const unsigned number_of_results) const = 0;
+
+    virtual unsigned GetCheckSum() const = 0;
+
+    virtual unsigned GetNameIndexFromEdgeID(const unsigned id) const = 0;
+
+    virtual void GetName(const unsigned name_id, std::string &result) const = 0;
+
+    std::string GetEscapedNameForNameID(const unsigned name_id) const
+    {
+        std::string temporary_string;
+        GetName(name_id, temporary_string);
+        return EscapeJSONString(temporary_string);
+    }
+
+    virtual std::string GetTimestamp() const = 0;
+};
+
+#endif // BASE_DATA_FACADE_H
diff --git a/Server/DataStructures/InternalDataFacade.h b/Server/DataStructures/InternalDataFacade.h
new file mode 100644
index 0000000..c2055bb
--- /dev/null
+++ b/Server/DataStructures/InternalDataFacade.h
@@ -0,0 +1,430 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef INTERNAL_DATA_FACADE
+#define INTERNAL_DATA_FACADE
+
+// implements all data storage when shared memory is _NOT_ used
+
+#include "BaseDataFacade.h"
+
+#include "../../DataStructures/OriginalEdgeData.h"
+#include "../../DataStructures/QueryNode.h"
+#include "../../DataStructures/QueryEdge.h"
+#include "../../DataStructures/SharedMemoryVectorWrapper.h"
+#include "../../DataStructures/StaticGraph.h"
+#include "../../DataStructures/StaticRTree.h"
+#include "../../DataStructures/RangeTable.h"
+#include "../../Util/BoostFileSystemFix.h"
+#include "../../Util/GraphLoader.h"
+#include "../../Util/ProgramOptions.h"
+#include "../../Util/SimpleLogger.h"
+
+#include <osrm/Coordinate.h>
+
+template <class EdgeDataT> class InternalDataFacade : public BaseDataFacade<EdgeDataT>
+{
+
+  private:
+    typedef BaseDataFacade<EdgeDataT> super;
+    typedef StaticGraph<typename super::EdgeData> QueryGraph;
+    typedef typename QueryGraph::InputEdge InputEdge;
+    typedef typename super::RTreeLeaf RTreeLeaf;
+
+    InternalDataFacade() {}
+
+    unsigned m_check_sum;
+    unsigned m_number_of_nodes;
+    QueryGraph *m_query_graph;
+    std::string m_timestamp;
+
+    std::shared_ptr<ShM<FixedPointCoordinate, false>::vector> m_coordinate_list;
+    ShM<NodeID, false>::vector m_via_node_list;
+    ShM<unsigned, false>::vector m_name_ID_list;
+    ShM<TurnInstruction, false>::vector m_turn_instruction_list;
+    ShM<char, false>::vector m_names_char_list;
+    ShM<bool, false>::vector m_egde_is_compressed;
+    ShM<unsigned, false>::vector m_geometry_indices;
+    ShM<unsigned, false>::vector m_geometry_list;
+
+    std::shared_ptr<StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, false>::vector, false>>
+    m_static_rtree;
+    RangeTable<16, false> m_name_table;
+
+    void LoadTimestamp(const boost::filesystem::path &timestamp_path)
+    {
+        if (boost::filesystem::exists(timestamp_path))
+        {
+            SimpleLogger().Write() << "Loading Timestamp";
+            boost::filesystem::ifstream timestamp_stream(timestamp_path);
+            if (!timestamp_stream)
+            {
+                SimpleLogger().Write(logWARNING) << timestamp_path << " not found";
+            }
+            getline(timestamp_stream, m_timestamp);
+            timestamp_stream.close();
+        }
+        if (m_timestamp.empty())
+        {
+            m_timestamp = "n/a";
+        }
+        if (25 < m_timestamp.length())
+        {
+            m_timestamp.resize(25);
+        }
+    }
+
+    void LoadGraph(const boost::filesystem::path &hsgr_path)
+    {
+        typename ShM<typename QueryGraph::NodeArrayEntry, false>::vector node_list;
+        typename ShM<typename QueryGraph::EdgeArrayEntry, false>::vector edge_list;
+
+        SimpleLogger().Write() << "loading graph from " << hsgr_path.string();
+
+        m_number_of_nodes = readHSGRFromStream(hsgr_path, node_list, edge_list, &m_check_sum);
+
+        BOOST_ASSERT_MSG(0 != node_list.size(), "node list empty");
+        // BOOST_ASSERT_MSG(0 != edge_list.size(), "edge list empty");
+        SimpleLogger().Write() << "loaded " << node_list.size() << " nodes and " << edge_list.size()
+                               << " edges";
+        m_query_graph = new QueryGraph(node_list, edge_list);
+
+        BOOST_ASSERT_MSG(0 == node_list.size(), "node list not flushed");
+        BOOST_ASSERT_MSG(0 == edge_list.size(), "edge list not flushed");
+        SimpleLogger().Write() << "Data checksum is " << m_check_sum;
+    }
+
+    void LoadNodeAndEdgeInformation(const boost::filesystem::path &nodes_file,
+                                    const boost::filesystem::path &edges_file)
+    {
+        boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary);
+
+        NodeInfo current_node;
+        unsigned number_of_coordinates = 0;
+        nodes_input_stream.read((char *)&number_of_coordinates, sizeof(unsigned));
+        m_coordinate_list =
+            std::make_shared<std::vector<FixedPointCoordinate>>(number_of_coordinates);
+        for (unsigned i = 0; i < number_of_coordinates; ++i)
+        {
+            nodes_input_stream.read((char *)&current_node, sizeof(NodeInfo));
+            m_coordinate_list->at(i) = FixedPointCoordinate(current_node.lat, current_node.lon);
+            BOOST_ASSERT((std::abs(m_coordinate_list->at(i).lat) >> 30) == 0);
+            BOOST_ASSERT((std::abs(m_coordinate_list->at(i).lon) >> 30) == 0);
+        }
+        nodes_input_stream.close();
+
+        boost::filesystem::ifstream edges_input_stream(edges_file, std::ios::binary);
+        unsigned number_of_edges = 0;
+        edges_input_stream.read((char *)&number_of_edges, sizeof(unsigned));
+        m_via_node_list.resize(number_of_edges);
+        m_name_ID_list.resize(number_of_edges);
+        m_turn_instruction_list.resize(number_of_edges);
+        m_egde_is_compressed.resize(number_of_edges);
+
+        unsigned compressed = 0;
+
+        OriginalEdgeData current_edge_data;
+        for (unsigned i = 0; i < number_of_edges; ++i)
+        {
+            edges_input_stream.read((char *)&(current_edge_data), sizeof(OriginalEdgeData));
+            m_via_node_list[i] = current_edge_data.via_node;
+            m_name_ID_list[i] = current_edge_data.name_id;
+            m_turn_instruction_list[i] = current_edge_data.turn_instruction;
+            m_egde_is_compressed[i] = current_edge_data.compressed_geometry;
+            if (m_egde_is_compressed[i])
+            {
+                ++compressed;
+            }
+        }
+
+        edges_input_stream.close();
+    }
+
+    void LoadGeometries(const boost::filesystem::path &geometry_file)
+    {
+        std::ifstream geometry_stream(geometry_file.string().c_str(), std::ios::binary);
+        unsigned number_of_indices = 0;
+        unsigned number_of_compressed_geometries = 0;
+
+        geometry_stream.read((char *)&number_of_indices, sizeof(unsigned));
+
+        m_geometry_indices.resize(number_of_indices);
+        if (number_of_indices > 0)
+        {
+            geometry_stream.read((char *)&(m_geometry_indices[0]),
+                                 number_of_indices * sizeof(unsigned));
+        }
+
+        geometry_stream.read((char *)&number_of_compressed_geometries, sizeof(unsigned));
+
+        BOOST_ASSERT(m_geometry_indices.back() == number_of_compressed_geometries);
+        m_geometry_list.resize(number_of_compressed_geometries);
+
+        if (number_of_compressed_geometries > 0)
+        {
+            geometry_stream.read((char *)&(m_geometry_list[0]),
+                                 number_of_compressed_geometries * sizeof(unsigned));
+        }
+        geometry_stream.close();
+    }
+
+    void LoadRTree(const boost::filesystem::path &ram_index_path,
+                   const boost::filesystem::path &file_index_path)
+    {
+        BOOST_ASSERT_MSG(!m_coordinate_list->empty(), "coordinates must be loaded before r-tree");
+
+        m_static_rtree = std::make_shared<StaticRTree<RTreeLeaf>>(
+            ram_index_path, file_index_path, m_coordinate_list);
+    }
+
+    void LoadStreetNames(const boost::filesystem::path &names_file)
+    {
+        boost::filesystem::ifstream name_stream(names_file, std::ios::binary);
+
+        name_stream >> m_name_table;
+
+        unsigned number_of_chars = 0;
+        name_stream.read((char *)&number_of_chars, sizeof(unsigned));
+        BOOST_ASSERT_MSG(0 != number_of_chars, "name file broken");
+        m_names_char_list.resize(number_of_chars + 1); //+1 gives sentinel element
+        name_stream.read((char *)&m_names_char_list[0], number_of_chars * sizeof(char));
+        if (0 == m_names_char_list.size())
+        {
+            SimpleLogger().Write(logWARNING) << "list of street names is empty";
+        }
+        name_stream.close();
+    }
+
+  public:
+    ~InternalDataFacade()
+    {
+        delete m_query_graph;
+        m_static_rtree.reset();
+    }
+
+    explicit InternalDataFacade(const ServerPaths &server_paths)
+    {
+        // generate paths of data files
+        if (server_paths.find("hsgrdata") == server_paths.end())
+        {
+            throw OSRMException("no hsgr file given in ini file");
+        }
+        if (server_paths.find("ramindex") == server_paths.end())
+        {
+            throw OSRMException("no ram index file given in ini file");
+        }
+        if (server_paths.find("fileindex") == server_paths.end())
+        {
+            throw OSRMException("no leaf index file given in ini file");
+        }
+        if (server_paths.find("geometries") == server_paths.end())
+        {
+            throw OSRMException("no geometries file given in ini file");
+        }
+        if (server_paths.find("nodesdata") == server_paths.end())
+        {
+            throw OSRMException("no nodes file given in ini file");
+        }
+        if (server_paths.find("edgesdata") == server_paths.end())
+        {
+            throw OSRMException("no edges file given in ini file");
+        }
+        if (server_paths.find("namesdata") == server_paths.end())
+        {
+            throw OSRMException("no names file given in ini file");
+        }
+
+        ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata");
+        BOOST_ASSERT(server_paths.end() != paths_iterator);
+        const boost::filesystem::path &hsgr_path = paths_iterator->second;
+        paths_iterator = server_paths.find("timestamp");
+        BOOST_ASSERT(server_paths.end() != paths_iterator);
+        const boost::filesystem::path &timestamp_path = paths_iterator->second;
+        paths_iterator = server_paths.find("ramindex");
+        BOOST_ASSERT(server_paths.end() != paths_iterator);
+        const boost::filesystem::path &ram_index_path = paths_iterator->second;
+        paths_iterator = server_paths.find("fileindex");
+        BOOST_ASSERT(server_paths.end() != paths_iterator);
+        const boost::filesystem::path &file_index_path = paths_iterator->second;
+        paths_iterator = server_paths.find("nodesdata");
+        BOOST_ASSERT(server_paths.end() != paths_iterator);
+        const boost::filesystem::path &nodes_data_path = paths_iterator->second;
+        paths_iterator = server_paths.find("edgesdata");
+        BOOST_ASSERT(server_paths.end() != paths_iterator);
+        const boost::filesystem::path &edges_data_path = paths_iterator->second;
+        paths_iterator = server_paths.find("namesdata");
+        BOOST_ASSERT(server_paths.end() != paths_iterator);
+        const boost::filesystem::path &names_data_path = paths_iterator->second;
+        paths_iterator = server_paths.find("geometries");
+        BOOST_ASSERT(server_paths.end() != paths_iterator);
+        const boost::filesystem::path &geometries_path = paths_iterator->second;
+
+        // load data
+        SimpleLogger().Write() << "loading graph data";
+        AssertPathExists(hsgr_path);
+        LoadGraph(hsgr_path);
+        SimpleLogger().Write() << "loading egde information";
+        AssertPathExists(nodes_data_path);
+        AssertPathExists(edges_data_path);
+        LoadNodeAndEdgeInformation(nodes_data_path, edges_data_path);
+        SimpleLogger().Write() << "loading geometries";
+        AssertPathExists(geometries_path);
+        LoadGeometries(geometries_path);
+        SimpleLogger().Write() << "loading r-tree";
+        AssertPathExists(ram_index_path);
+        AssertPathExists(file_index_path);
+        LoadRTree(ram_index_path, file_index_path);
+        SimpleLogger().Write() << "loading timestamp";
+        LoadTimestamp(timestamp_path);
+        SimpleLogger().Write() << "loading street names";
+        AssertPathExists(names_data_path);
+        LoadStreetNames(names_data_path);
+    }
+
+    // search graph access
+    unsigned GetNumberOfNodes() const { return m_query_graph->GetNumberOfNodes(); }
+
+    unsigned GetNumberOfEdges() const { return m_query_graph->GetNumberOfEdges(); }
+
+    unsigned GetOutDegree(const NodeID n) const { return m_query_graph->GetOutDegree(n); }
+
+    NodeID GetTarget(const EdgeID e) const { return m_query_graph->GetTarget(e); }
+
+    EdgeDataT &GetEdgeData(const EdgeID e) { return m_query_graph->GetEdgeData(e); }
+
+    const EdgeDataT &GetEdgeData(const EdgeID e) const { return m_query_graph->GetEdgeData(e); }
+
+    EdgeID BeginEdges(const NodeID n) const { return m_query_graph->BeginEdges(n); }
+
+    EdgeID EndEdges(const NodeID n) const { return m_query_graph->EndEdges(n); }
+
+    EdgeRange GetAdjacentEdgeRange(const NodeID node) const
+    {
+        return m_query_graph->GetAdjacentEdgeRange(node);
+    };
+
+    // searches for a specific edge
+    EdgeID FindEdge(const NodeID from, const NodeID to) const
+    {
+        return m_query_graph->FindEdge(from, to);
+    }
+
+    EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const
+    {
+        return m_query_graph->FindEdgeInEitherDirection(from, to);
+    }
+
+    EdgeID FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const
+    {
+        return m_query_graph->FindEdgeIndicateIfReverse(from, to, result);
+    }
+
+    // node and edge information access
+    FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const
+    {
+        return m_coordinate_list->at(id);
+    };
+
+    bool EdgeIsCompressed(const unsigned id) const { return m_egde_is_compressed.at(id); }
+
+    TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const
+    {
+        return m_turn_instruction_list.at(id);
+    }
+
+    bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
+                                            FixedPointCoordinate &result,
+                                            const unsigned zoom_level = 18) const
+    {
+        return m_static_rtree->LocateClosestEndPointForCoordinate(
+            input_coordinate, result, zoom_level);
+    }
+
+    bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
+                                      PhantomNode &resulting_phantom_node,
+                                      const unsigned zoom_level) const
+    {
+        return m_static_rtree->FindPhantomNodeForCoordinate(
+            input_coordinate, resulting_phantom_node, zoom_level);
+    }
+
+    bool
+    IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
+                                            std::vector<PhantomNode> &resulting_phantom_node_vector,
+                                            const unsigned zoom_level,
+                                            const unsigned number_of_results) const
+    {
+        return m_static_rtree->IncrementalFindPhantomNodeForCoordinate(
+            input_coordinate, resulting_phantom_node_vector, zoom_level, number_of_results);
+    }
+
+    unsigned GetCheckSum() const { return m_check_sum; }
+
+    unsigned GetNameIndexFromEdgeID(const unsigned id) const
+    {
+        return m_name_ID_list.at(id);
+    };
+
+    void GetName(const unsigned name_id, std::string &result) const
+    {
+        if (UINT_MAX == name_id)
+        {
+            result = "";
+            return;
+        }
+        auto range = m_name_table.GetRange(name_id);
+
+        result.clear();
+        if (range.begin() != range.end())
+        {
+            result.resize(range.back() - range.front() + 1);
+            std::copy(m_names_char_list.begin() + range.front(),
+                      m_names_char_list.begin() + range.back() + 1,
+                      result.begin());
+        }
+    }
+
+    virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const
+    {
+        return m_via_node_list.at(id);
+    }
+
+    virtual void GetUncompressedGeometry(const unsigned id, std::vector<unsigned> &result_nodes)
+        const
+    {
+        const unsigned begin = m_geometry_indices.at(id);
+        const unsigned end = m_geometry_indices.at(id + 1);
+
+        result_nodes.clear();
+        result_nodes.insert(
+            result_nodes.begin(), m_geometry_list.begin() + begin, m_geometry_list.begin() + end);
+    }
+
+    std::string GetTimestamp() const { return m_timestamp; }
+};
+
+#endif // INTERNAL_DATA_FACADE
diff --git a/Server/DataStructures/QueryObjectsStorage.cpp b/Server/DataStructures/QueryObjectsStorage.cpp
deleted file mode 100644
index df15f53..0000000
--- a/Server/DataStructures/QueryObjectsStorage.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-
-#include "QueryObjectsStorage.h"
-#include "../../Util/GraphLoader.h"
-
-QueryObjectsStorage::QueryObjectsStorage(
-	std::string hsgrPath,
-	std::string ramIndexPath,
-	std::string fileIndexPath,
-	std::string nodesPath,
-	std::string edgesPath,
-	std::string namesPath,
-	std::string timestampPath
-) {
-	INFO("loading graph data");
-	std::ifstream hsgrInStream(hsgrPath.c_str(), std::ios::binary);
-    if(!hsgrInStream) { ERR(hsgrPath <<  " not found"); }
-	//Deserialize road network graph
-	std::vector< QueryGraph::_StrNode> nodeList;
-	std::vector< QueryGraph::_StrEdge> edgeList;
-	const int n = readHSGRFromStream(
-		hsgrInStream,
-		nodeList,
-		edgeList,
-		&checkSum
-	);
-
-	INFO("Data checksum is " << checkSum);
-	graph = new QueryGraph(nodeList, edgeList);
-	assert(0 == nodeList.size());
-	assert(0 == edgeList.size());
-
-	if(timestampPath.length()) {
-	    INFO("Loading Timestamp");
-	    std::ifstream timestampInStream(timestampPath.c_str());
-	    if(!timestampInStream) { WARN(timestampPath <<  " not found"); }
-
-	    getline(timestampInStream, timestamp);
-	    timestampInStream.close();
-	}
-	if(!timestamp.length())
-	    timestamp = "n/a";
-	if(25 < timestamp.length())
-	    timestamp.resize(25);
-
-    INFO("Loading auxiliary information");
-    //Init nearest neighbor data structure
-	std::ifstream nodesInStream(nodesPath.c_str(), std::ios::binary);
-	if(!nodesInStream) { ERR(nodesPath <<  " not found"); }
-    std::ifstream edgesInStream(edgesPath.c_str(), std::ios::binary);
-    if(!edgesInStream) { ERR(edgesPath <<  " not found"); }
-	nodeHelpDesk = new NodeInformationHelpDesk(ramIndexPath.c_str(), fileIndexPath.c_str(), n, checkSum);
-	nodeHelpDesk->initNNGrid(nodesInStream, edgesInStream);
-
-	//deserialize street name list
-	INFO("Loading names index");
-	std::ifstream namesInStream(namesPath.c_str(), std::ios::binary);
-    if(!namesInStream) { ERR(namesPath <<  " not found"); }
-	unsigned size(0);
-	namesInStream.read((char *)&size, sizeof(unsigned));
-	//        names = new std::vector<std::string>();
-
-	char buf[1024];
-	for(unsigned i = 0; i < size; ++i) {
-		unsigned sizeOfString = 0;
-		namesInStream.read((char *)&sizeOfString, sizeof(unsigned));
-		buf[sizeOfString] = '\0'; // instead of memset
-		namesInStream.read(buf, sizeOfString);
-		names.push_back(buf);
-	}
-	std::vector<std::string>(names).swap(names);
-	hsgrInStream.close();
-	namesInStream.close();
-	INFO("All query data structures loaded");
-}
-
-QueryObjectsStorage::~QueryObjectsStorage() {
-	//        delete names;
-	delete graph;
-	delete nodeHelpDesk;
-}
diff --git a/Server/DataStructures/QueryObjectsStorage.h b/Server/DataStructures/QueryObjectsStorage.h
deleted file mode 100644
index be8bba0..0000000
--- a/Server/DataStructures/QueryObjectsStorage.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-
-#ifndef QUERYOBJECTSSTORAGE_H_
-#define QUERYOBJECTSSTORAGE_H_
-
-#include<vector>
-#include<string>
-
-#include "../../DataStructures/NodeInformationHelpDesk.h"
-#include "../../DataStructures/QueryEdge.h"
-#include "../../DataStructures/StaticGraph.h"
-
-struct QueryObjectsStorage {
-    typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
-    typedef QueryGraph::InputEdge InputEdge;
-
-    NodeInformationHelpDesk * nodeHelpDesk;
-    std::vector<std::string> names;
-    QueryGraph * graph;
-    std::string timestamp;
-    unsigned checkSum;
-
-    QueryObjectsStorage(std::string hsgrPath, std::string ramIndexPath, std::string fileIndexPath, std::string nodesPath, std::string edgesPath, std::string namesPath, std::string timestampPath);
-
-    ~QueryObjectsStorage();
-};
-
-#endif /* QUERYOBJECTSSTORAGE_H_ */
diff --git a/Server/DataStructures/SharedBarriers.h b/Server/DataStructures/SharedBarriers.h
new file mode 100644
index 0000000..36ba08b
--- /dev/null
+++ b/Server/DataStructures/SharedBarriers.h
@@ -0,0 +1,60 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef SHARED_BARRIER_H
+#define SHARED_BARRIER_H
+
+#include <boost/interprocess/sync/named_mutex.hpp>
+#include <boost/interprocess/sync/named_condition.hpp>
+
+struct SharedBarriers
+{
+
+    SharedBarriers()
+        : pending_update_mutex(boost::interprocess::open_or_create, "pending_update"),
+          update_mutex(boost::interprocess::open_or_create, "update"),
+          query_mutex(boost::interprocess::open_or_create, "query"),
+          no_running_queries_condition(boost::interprocess::open_or_create, "no_running_queries"),
+          update_ongoing(false), number_of_queries(0)
+    {
+    }
+
+    // Mutex to protect access to the boolean variable
+    boost::interprocess::named_mutex pending_update_mutex;
+    boost::interprocess::named_mutex update_mutex;
+    boost::interprocess::named_mutex query_mutex;
+
+    // Condition that no update is running
+    boost::interprocess::named_condition no_running_queries_condition;
+
+    // Is there an ongoing update?
+    bool update_ongoing;
+    // Is there any query?
+    int number_of_queries;
+};
+
+#endif // SHARED_BARRIER_H
diff --git a/Server/DataStructures/SharedDataFacade.h b/Server/DataStructures/SharedDataFacade.h
new file mode 100644
index 0000000..a2cb990
--- /dev/null
+++ b/Server/DataStructures/SharedDataFacade.h
@@ -0,0 +1,398 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef SHARED_DATA_FACADE_H
+#define SHARED_DATA_FACADE_H
+
+// implements all data storage when shared memory _IS_ used
+
+#include "BaseDataFacade.h"
+#include "SharedDataType.h"
+
+#include "../../DataStructures/RangeTable.h"
+#include "../../DataStructures/StaticGraph.h"
+#include "../../DataStructures/StaticRTree.h"
+#include "../../Util/BoostFileSystemFix.h"
+#include "../../Util/ProgramOptions.h"
+#include "../../Util/SimpleLogger.h"
+
+#include <algorithm>
+#include <memory>
+
+template <class EdgeDataT> class SharedDataFacade : public BaseDataFacade<EdgeDataT>
+{
+
+  private:
+    typedef EdgeDataT EdgeData;
+    typedef BaseDataFacade<EdgeData> super;
+    typedef StaticGraph<EdgeData, true> QueryGraph;
+    typedef typename StaticGraph<EdgeData, true>::NodeArrayEntry GraphNode;
+    typedef typename StaticGraph<EdgeData, true>::EdgeArrayEntry GraphEdge;
+    typedef typename RangeTable<16, true>::BlockT NameIndexBlock;
+    typedef typename QueryGraph::InputEdge InputEdge;
+    typedef typename super::RTreeLeaf RTreeLeaf;
+    typedef typename StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>::TreeNode
+    RTreeNode;
+
+    SharedDataLayout *data_layout;
+    char *shared_memory;
+    SharedDataTimestamp *data_timestamp_ptr;
+
+    SharedDataType CURRENT_LAYOUT;
+    SharedDataType CURRENT_DATA;
+    unsigned CURRENT_TIMESTAMP;
+
+    unsigned m_check_sum;
+    unsigned m_number_of_nodes;
+    std::shared_ptr<QueryGraph> m_query_graph;
+    std::shared_ptr<SharedMemory> m_layout_memory;
+    std::shared_ptr<SharedMemory> m_large_memory;
+    std::string m_timestamp;
+
+    std::shared_ptr<ShM<FixedPointCoordinate, true>::vector> m_coordinate_list;
+    ShM<NodeID, true>::vector m_via_node_list;
+    ShM<unsigned, true>::vector m_name_ID_list;
+    ShM<TurnInstruction, true>::vector m_turn_instruction_list;
+    ShM<char, true>::vector m_names_char_list;
+    ShM<unsigned, true>::vector m_name_begin_indices;
+    ShM<bool, true>::vector m_egde_is_compressed;
+    ShM<unsigned, true>::vector m_geometry_indices;
+    ShM<unsigned, true>::vector m_geometry_list;
+
+    std::shared_ptr<StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>>
+    m_static_rtree;
+
+    std::shared_ptr<RangeTable<16, true>> m_name_table;
+
+    void LoadChecksum()
+    {
+        m_check_sum =
+            *data_layout->GetBlockPtr<unsigned>(shared_memory, SharedDataLayout::HSGR_CHECKSUM);
+        SimpleLogger().Write() << "set checksum: " << m_check_sum;
+    }
+
+    void LoadTimestamp()
+    {
+        char *timestamp_ptr =
+            data_layout->GetBlockPtr<char>(shared_memory, SharedDataLayout::TIMESTAMP);
+        m_timestamp.resize(data_layout->GetBlockSize(SharedDataLayout::TIMESTAMP));
+        std::copy(timestamp_ptr,
+                  timestamp_ptr + data_layout->GetBlockSize(SharedDataLayout::TIMESTAMP),
+                  m_timestamp.begin());
+    }
+
+    void LoadRTree(const boost::filesystem::path &file_index_path)
+    {
+        BOOST_ASSERT_MSG(!m_coordinate_list->empty(), "coordinates must be loaded before r-tree");
+
+        RTreeNode *tree_ptr =
+            data_layout->GetBlockPtr<RTreeNode>(shared_memory, SharedDataLayout::R_SEARCH_TREE);
+        m_static_rtree =
+            std::make_shared<StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>>(
+                tree_ptr,
+                data_layout->num_entries[SharedDataLayout::R_SEARCH_TREE],
+                file_index_path,
+                m_coordinate_list);
+    }
+
+    void LoadGraph()
+    {
+        m_number_of_nodes = data_layout->num_entries[SharedDataLayout::GRAPH_NODE_LIST];
+        GraphNode *graph_nodes_ptr =
+            data_layout->GetBlockPtr<GraphNode>(shared_memory, SharedDataLayout::GRAPH_NODE_LIST);
+
+        GraphEdge *graph_edges_ptr =
+            data_layout->GetBlockPtr<GraphEdge>(shared_memory, SharedDataLayout::GRAPH_EDGE_LIST);
+
+        typename ShM<GraphNode, true>::vector node_list(
+            graph_nodes_ptr, data_layout->num_entries[SharedDataLayout::GRAPH_NODE_LIST]);
+        typename ShM<GraphEdge, true>::vector edge_list(
+            graph_edges_ptr, data_layout->num_entries[SharedDataLayout::GRAPH_EDGE_LIST]);
+        m_query_graph.reset(new QueryGraph(node_list, edge_list));
+    }
+
+    void LoadNodeAndEdgeInformation()
+    {
+
+        FixedPointCoordinate *coordinate_list_ptr = data_layout->GetBlockPtr<FixedPointCoordinate>(
+            shared_memory, SharedDataLayout::COORDINATE_LIST);
+        m_coordinate_list = std::make_shared<ShM<FixedPointCoordinate, true>::vector>(
+            coordinate_list_ptr, data_layout->num_entries[SharedDataLayout::COORDINATE_LIST]);
+
+        TurnInstruction *turn_instruction_list_ptr = data_layout->GetBlockPtr<TurnInstruction>(
+            shared_memory, SharedDataLayout::TURN_INSTRUCTION);
+        typename ShM<TurnInstruction, true>::vector turn_instruction_list(
+            turn_instruction_list_ptr,
+            data_layout->num_entries[SharedDataLayout::TURN_INSTRUCTION]);
+        m_turn_instruction_list.swap(turn_instruction_list);
+
+        unsigned *name_id_list_ptr =
+            data_layout->GetBlockPtr<unsigned>(shared_memory, SharedDataLayout::NAME_ID_LIST);
+        typename ShM<unsigned, true>::vector name_id_list(
+            name_id_list_ptr, data_layout->num_entries[SharedDataLayout::NAME_ID_LIST]);
+        m_name_ID_list.swap(name_id_list);
+    }
+
+    void LoadViaNodeList()
+    {
+        NodeID *via_node_list_ptr =
+            data_layout->GetBlockPtr<NodeID>(shared_memory, SharedDataLayout::VIA_NODE_LIST);
+        typename ShM<NodeID, true>::vector via_node_list(
+            via_node_list_ptr, data_layout->num_entries[SharedDataLayout::VIA_NODE_LIST]);
+        m_via_node_list.swap(via_node_list);
+    }
+
+    void LoadNames()
+    {
+        unsigned *offsets_ptr =
+            data_layout->GetBlockPtr<unsigned>(shared_memory, SharedDataLayout::NAME_OFFSETS);
+        NameIndexBlock *blocks_ptr =
+            data_layout->GetBlockPtr<NameIndexBlock>(shared_memory, SharedDataLayout::NAME_BLOCKS);
+        typename ShM<unsigned, true>::vector name_offsets(
+            offsets_ptr, data_layout->num_entries[SharedDataLayout::NAME_OFFSETS]);
+        typename ShM<NameIndexBlock, true>::vector name_blocks(
+            blocks_ptr, data_layout->num_entries[SharedDataLayout::NAME_BLOCKS]);
+
+        char *names_list_ptr =
+            data_layout->GetBlockPtr<char>(shared_memory, SharedDataLayout::NAME_CHAR_LIST);
+        typename ShM<char, true>::vector names_char_list(
+            names_list_ptr, data_layout->num_entries[SharedDataLayout::NAME_CHAR_LIST]);
+        m_name_table = std::make_shared<RangeTable<16, true>>(
+            name_offsets, name_blocks, names_char_list.size());
+
+        m_names_char_list.swap(names_char_list);
+    }
+
+    void LoadGeometries()
+    {
+        unsigned *geometries_compressed_ptr = data_layout->GetBlockPtr<unsigned>(
+            shared_memory, SharedDataLayout::GEOMETRIES_INDICATORS);
+        typename ShM<bool, true>::vector egde_is_compressed(
+            geometries_compressed_ptr,
+            data_layout->num_entries[SharedDataLayout::GEOMETRIES_INDICATORS]);
+        m_egde_is_compressed.swap(egde_is_compressed);
+
+        unsigned *geometries_index_ptr =
+            data_layout->GetBlockPtr<unsigned>(shared_memory, SharedDataLayout::GEOMETRIES_INDEX);
+        typename ShM<unsigned, true>::vector geometry_begin_indices(
+            geometries_index_ptr, data_layout->num_entries[SharedDataLayout::GEOMETRIES_INDEX]);
+        m_geometry_indices.swap(geometry_begin_indices);
+
+        unsigned *geometries_list_ptr =
+            data_layout->GetBlockPtr<unsigned>(shared_memory, SharedDataLayout::GEOMETRIES_LIST);
+        typename ShM<unsigned, true>::vector geometry_list(
+            geometries_list_ptr, data_layout->num_entries[SharedDataLayout::GEOMETRIES_LIST]);
+        m_geometry_list.swap(geometry_list);
+    }
+
+  public:
+    SharedDataFacade()
+    {
+        data_timestamp_ptr = (SharedDataTimestamp *)SharedMemoryFactory::Get(
+                                 CURRENT_REGIONS, sizeof(SharedDataTimestamp), false, false)->Ptr();
+
+        CURRENT_LAYOUT = LAYOUT_NONE;
+        CURRENT_DATA = DATA_NONE;
+        CURRENT_TIMESTAMP = 0;
+
+        // load data
+        CheckAndReloadFacade();
+    }
+
+    void CheckAndReloadFacade()
+    {
+        if (CURRENT_LAYOUT != data_timestamp_ptr->layout ||
+            CURRENT_DATA != data_timestamp_ptr->data ||
+            CURRENT_TIMESTAMP != data_timestamp_ptr->timestamp)
+        {
+            // release the previous shared memory segments
+            SharedMemory::Remove(CURRENT_LAYOUT);
+            SharedMemory::Remove(CURRENT_DATA);
+
+            CURRENT_LAYOUT = data_timestamp_ptr->layout;
+            CURRENT_DATA = data_timestamp_ptr->data;
+            CURRENT_TIMESTAMP = data_timestamp_ptr->timestamp;
+
+            m_layout_memory.reset(SharedMemoryFactory::Get(CURRENT_LAYOUT));
+
+            data_layout = (SharedDataLayout *)(m_layout_memory->Ptr());
+
+            m_large_memory.reset(SharedMemoryFactory::Get(CURRENT_DATA));
+            shared_memory = (char *)(m_large_memory->Ptr());
+
+            std::ofstream out("debug.bin");
+            out.write(shared_memory, data_layout->GetSizeOfLayout());
+            out.close();
+
+            const char *file_index_ptr =
+                data_layout->GetBlockPtr<char>(shared_memory, SharedDataLayout::FILE_INDEX_PATH);
+            boost::filesystem::path file_index_path(file_index_ptr);
+            if (!boost::filesystem::exists(file_index_path))
+            {
+                SimpleLogger().Write(logDEBUG) << "Leaf file name " << file_index_path.string();
+                throw OSRMException("Could not load leaf index file."
+                                    "Is any data loaded into shared memory?");
+            }
+
+            LoadGraph();
+            LoadChecksum();
+            LoadNodeAndEdgeInformation();
+            LoadGeometries();
+            LoadRTree(file_index_path);
+            LoadTimestamp();
+            LoadViaNodeList();
+            LoadNames();
+
+            data_layout->PrintInformation();
+        }
+    }
+
+    // search graph access
+    unsigned GetNumberOfNodes() const { return m_query_graph->GetNumberOfNodes(); }
+
+    unsigned GetNumberOfEdges() const { return m_query_graph->GetNumberOfEdges(); }
+
+    unsigned GetOutDegree(const NodeID n) const { return m_query_graph->GetOutDegree(n); }
+
+    NodeID GetTarget(const EdgeID e) const { return m_query_graph->GetTarget(e); }
+
+    EdgeDataT &GetEdgeData(const EdgeID e) { return m_query_graph->GetEdgeData(e); }
+
+    // const EdgeDataT &GetEdgeData( const EdgeID e ) const {
+    //     return m_query_graph->GetEdgeData(e);
+    // }
+
+    EdgeID BeginEdges(const NodeID n) const { return m_query_graph->BeginEdges(n); }
+
+    EdgeID EndEdges(const NodeID n) const { return m_query_graph->EndEdges(n); }
+
+    EdgeRange GetAdjacentEdgeRange(const NodeID node) const
+    {
+        return m_query_graph->GetAdjacentEdgeRange(node);
+    };
+
+    // searches for a specific edge
+    EdgeID FindEdge(const NodeID from, const NodeID to) const
+    {
+        return m_query_graph->FindEdge(from, to);
+    }
+
+    EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const
+    {
+        return m_query_graph->FindEdgeInEitherDirection(from, to);
+    }
+
+    EdgeID FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const
+    {
+        return m_query_graph->FindEdgeIndicateIfReverse(from, to, result);
+    }
+
+    // node and edge information access
+    FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const
+    {
+        return m_coordinate_list->at(id);
+    };
+
+    virtual bool EdgeIsCompressed(const unsigned id) const { return m_egde_is_compressed.at(id); }
+
+    virtual void GetUncompressedGeometry(const unsigned id, std::vector<unsigned> &result_nodes)
+        const
+    {
+        const unsigned begin = m_geometry_indices.at(id);
+        const unsigned end = m_geometry_indices.at(id + 1);
+
+        result_nodes.clear();
+        result_nodes.insert(
+            result_nodes.begin(), m_geometry_list.begin() + begin, m_geometry_list.begin() + end);
+    }
+
+    virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const
+    {
+        return m_via_node_list.at(id);
+    }
+
+    TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const
+    {
+        return m_turn_instruction_list.at(id);
+    }
+
+    bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
+                                            FixedPointCoordinate &result,
+                                            const unsigned zoom_level = 18) const
+    {
+        return m_static_rtree->LocateClosestEndPointForCoordinate(
+            input_coordinate, result, zoom_level);
+    }
+
+    bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
+                                      PhantomNode &resulting_phantom_node,
+                                      const unsigned zoom_level) const
+    {
+        return m_static_rtree->FindPhantomNodeForCoordinate(
+            input_coordinate, resulting_phantom_node, zoom_level);
+    }
+
+    bool
+    IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
+                                            std::vector<PhantomNode> &resulting_phantom_node_vector,
+                                            const unsigned zoom_level,
+                                            const unsigned number_of_results) const
+    {
+        return m_static_rtree->IncrementalFindPhantomNodeForCoordinate(
+            input_coordinate, resulting_phantom_node_vector, zoom_level, number_of_results);
+    }
+
+    unsigned GetCheckSum() const { return m_check_sum; }
+
+    unsigned GetNameIndexFromEdgeID(const unsigned id) const
+    {
+        return m_name_ID_list.at(id);
+    };
+
+    void GetName(const unsigned name_id, std::string &result) const
+    {
+        if (UINT_MAX == name_id)
+        {
+            result = "";
+            return;
+        }
+        auto range = m_name_table->GetRange(name_id);
+
+        result.clear();
+        if (range.begin() != range.end())
+        {
+            result.resize(range.back() - range.front() + 1);
+            std::copy(m_names_char_list.begin() + range.front(),
+                      m_names_char_list.begin() + range.back() + 1,
+                      result.begin());
+        }
+    }
+
+    std::string GetTimestamp() const { return m_timestamp; }
+};
+
+#endif // SHARED_DATA_FACADE_H
diff --git a/Server/DataStructures/SharedDataType.h b/Server/DataStructures/SharedDataType.h
new file mode 100644
index 0000000..98bdfd5
--- /dev/null
+++ b/Server/DataStructures/SharedDataType.h
@@ -0,0 +1,190 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef SHARED_DATA_TYPE_H_
+#define SHARED_DATA_TYPE_H_
+
+#include "../../Util/OSRMException.h"
+#include "../../Util/SimpleLogger.h"
+
+#include <cstdint>
+
+#include <array>
+
+// Added at the start and end of each block as sanity check
+constexpr char CANARY[] = "OSRM";
+
+struct SharedDataLayout
+{
+    enum BlockID {
+        NAME_OFFSETS = 0,
+        NAME_BLOCKS,
+        NAME_CHAR_LIST,
+        NAME_ID_LIST,
+        VIA_NODE_LIST,
+        GRAPH_NODE_LIST,
+        GRAPH_EDGE_LIST,
+        COORDINATE_LIST,
+        TURN_INSTRUCTION,
+        R_SEARCH_TREE,
+        GEOMETRIES_INDEX,
+        GEOMETRIES_LIST,
+        GEOMETRIES_INDICATORS,
+        HSGR_CHECKSUM,
+        TIMESTAMP,
+        FILE_INDEX_PATH,
+        NUM_BLOCKS
+    };
+
+    std::array<uint64_t, NUM_BLOCKS> num_entries;
+    std::array<uint64_t, NUM_BLOCKS> entry_size;
+
+    SharedDataLayout()
+    : num_entries()
+    , entry_size()
+    {
+    }
+
+    void PrintInformation() const
+    {
+        SimpleLogger().Write(logDEBUG) << "-";
+        SimpleLogger().Write(logDEBUG) << "name_offsets_size:          " << num_entries[NAME_OFFSETS];
+        SimpleLogger().Write(logDEBUG) << "name_blocks_size:           " << num_entries[NAME_BLOCKS];
+        SimpleLogger().Write(logDEBUG) << "name_char_list_size:        " << num_entries[NAME_CHAR_LIST];
+        SimpleLogger().Write(logDEBUG) << "name_id_list_size:          " << num_entries[NAME_ID_LIST];
+        SimpleLogger().Write(logDEBUG) << "via_node_list_size:         " << num_entries[VIA_NODE_LIST];
+        SimpleLogger().Write(logDEBUG) << "graph_node_list_size:       " << num_entries[GRAPH_NODE_LIST];
+        SimpleLogger().Write(logDEBUG) << "graph_edge_list_size:       " << num_entries[GRAPH_EDGE_LIST];
+        SimpleLogger().Write(logDEBUG) << "timestamp_length:           " << num_entries[TIMESTAMP];
+        SimpleLogger().Write(logDEBUG) << "coordinate_list_size:       " << num_entries[COORDINATE_LIST];
+        SimpleLogger().Write(logDEBUG) << "turn_instruction_list_size: " << num_entries[TURN_INSTRUCTION];
+        SimpleLogger().Write(logDEBUG) << "r_search_tree_size:         " << num_entries[R_SEARCH_TREE];
+        SimpleLogger().Write(logDEBUG) << "geometries_indicators:      " << num_entries[GEOMETRIES_INDICATORS]
+                                       << "/" << ((num_entries[GEOMETRIES_INDICATORS] / 8) + 1);
+        SimpleLogger().Write(logDEBUG) << "geometries_index_list_size: " << num_entries[GEOMETRIES_INDEX];
+        SimpleLogger().Write(logDEBUG) << "geometries_list_size:       " << num_entries[GEOMETRIES_LIST];
+        SimpleLogger().Write(logDEBUG) << "sizeof(checksum):           " << entry_size[HSGR_CHECKSUM];
+
+        SimpleLogger().Write(logDEBUG) << "NAME_OFFSETS         " << ": " << GetBlockSize(NAME_OFFSETS         );
+        SimpleLogger().Write(logDEBUG) << "NAME_BLOCKS          " << ": " << GetBlockSize(NAME_BLOCKS          );
+        SimpleLogger().Write(logDEBUG) << "NAME_CHAR_LIST       " << ": " << GetBlockSize(NAME_CHAR_LIST       );
+        SimpleLogger().Write(logDEBUG) << "NAME_ID_LIST         " << ": " << GetBlockSize(NAME_ID_LIST         );
+        SimpleLogger().Write(logDEBUG) << "VIA_NODE_LIST        " << ": " << GetBlockSize(VIA_NODE_LIST        );
+        SimpleLogger().Write(logDEBUG) << "GRAPH_NODE_LIST      " << ": " << GetBlockSize(GRAPH_NODE_LIST      );
+        SimpleLogger().Write(logDEBUG) << "GRAPH_EDGE_LIST      " << ": " << GetBlockSize(GRAPH_EDGE_LIST      );
+        SimpleLogger().Write(logDEBUG) << "COORDINATE_LIST      " << ": " << GetBlockSize(COORDINATE_LIST      );
+        SimpleLogger().Write(logDEBUG) << "TURN_INSTRUCTION     " << ": " << GetBlockSize(TURN_INSTRUCTION     );
+        SimpleLogger().Write(logDEBUG) << "R_SEARCH_TREE        " << ": " << GetBlockSize(R_SEARCH_TREE        );
+        SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDEX     " << ": " << GetBlockSize(GEOMETRIES_INDEX     );
+        SimpleLogger().Write(logDEBUG) << "GEOMETRIES_LIST      " << ": " << GetBlockSize(GEOMETRIES_LIST      );
+        SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDICATORS" << ": " << GetBlockSize(GEOMETRIES_INDICATORS);
+        SimpleLogger().Write(logDEBUG) << "HSGR_CHECKSUM        " << ": " << GetBlockSize(HSGR_CHECKSUM        );
+        SimpleLogger().Write(logDEBUG) << "TIMESTAMP            " << ": " << GetBlockSize(TIMESTAMP            );
+        SimpleLogger().Write(logDEBUG) << "FILE_INDEX_PATH      " << ": " << GetBlockSize(FILE_INDEX_PATH      );
+    }
+
+    template<typename T>
+    inline void SetBlockSize(BlockID bid, uint64_t entries)
+    {
+        num_entries[bid] = entries;
+        entry_size[bid] = sizeof(T);
+    }
+
+    inline uint64_t GetBlockSize(BlockID bid) const
+    {
+        // special encoding
+        if (bid == GEOMETRIES_INDICATORS)
+        {
+            return (num_entries[GEOMETRIES_INDICATORS]/32 + 1) * entry_size[GEOMETRIES_INDICATORS];
+        }
+
+        return num_entries[bid] * entry_size[bid];
+    }
+
+    inline uint64_t GetSizeOfLayout() const
+    {
+        return GetBlockOffset(NUM_BLOCKS) + NUM_BLOCKS*2*sizeof(CANARY);
+    }
+
+    inline uint64_t GetBlockOffset(BlockID bid) const
+    {
+        uint64_t result = sizeof(CANARY);
+        for (auto i = 0; i < bid; i++)
+        {
+            result += GetBlockSize((BlockID) i) + 2*sizeof(CANARY);
+        }
+        return result;
+    }
+
+    template<typename T, bool WRITE_CANARY=false>
+    inline T* GetBlockPtr(char* shared_memory, BlockID bid)
+    {
+        T* ptr = (T*)(shared_memory + GetBlockOffset(bid));
+        if (WRITE_CANARY)
+        {
+            char* start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY);
+            char* end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid);
+            std::copy(CANARY, CANARY + sizeof(CANARY), start_canary_ptr);
+            std::copy(CANARY, CANARY + sizeof(CANARY), end_canary_ptr);
+        }
+        else
+        {
+            char* start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY);
+            char* end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid);
+            bool start_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), start_canary_ptr);
+            bool end_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), end_canary_ptr);
+            if (!start_canary_alive)
+            {
+                throw OSRMException("Start canary of block corrupted.");
+            }
+            if (!end_canary_alive)
+            {
+                throw OSRMException("End canary of block corrupted.");
+            }
+        }
+
+        return ptr;
+    }
+};
+
+enum SharedDataType
+{ CURRENT_REGIONS,
+  LAYOUT_1,
+  DATA_1,
+  LAYOUT_2,
+  DATA_2,
+  LAYOUT_NONE,
+  DATA_NONE };
+
+struct SharedDataTimestamp
+{
+    SharedDataType layout;
+    SharedDataType data;
+    unsigned timestamp;
+};
+
+#endif /* SHARED_DATA_TYPE_H_ */
diff --git a/Server/Http/CompressionType.h b/Server/Http/CompressionType.h
new file mode 100644
index 0000000..74d0b62
--- /dev/null
+++ b/Server/Http/CompressionType.h
@@ -0,0 +1,41 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef COMPRESSION_TYPE_H
+#define COMPRESSION_TYPE_H
+
+namespace http
+{
+
+enum CompressionType
+{ noCompression,
+  gzipRFC1952,
+  deflateRFC1951 };
+
+} // namespace http
+
+#endif // COMPRESSION_TYPE_H
diff --git a/Server/Http/Reply.cpp b/Server/Http/Reply.cpp
new file mode 100644
index 0000000..b3247ec
--- /dev/null
+++ b/Server/Http/Reply.cpp
@@ -0,0 +1,123 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <osrm/Reply.h>
+
+#include "../../Util/StringUtil.h"
+
+namespace http
+{
+
+void Reply::SetSize(const unsigned size)
+{
+    for (Header &h : headers)
+    {
+        if ("Content-Length" == h.name)
+        {
+            h.value = UintToString(size);
+        }
+    }
+}
+
+// Sets the size of the uncompressed output.
+void Reply::SetUncompressedSize() { SetSize(static_cast<unsigned>(content.size())); }
+
+std::vector<boost::asio::const_buffer> Reply::ToBuffers()
+{
+    std::vector<boost::asio::const_buffer> buffers;
+    buffers.push_back(ToBuffer(status));
+    for (const Header &h : headers)
+    {
+        buffers.push_back(boost::asio::buffer(h.name));
+        buffers.push_back(boost::asio::buffer(seperators));
+        buffers.push_back(boost::asio::buffer(h.value));
+        buffers.push_back(boost::asio::buffer(crlf));
+    }
+    buffers.push_back(boost::asio::buffer(crlf));
+    buffers.push_back(boost::asio::buffer(content));
+    return buffers;
+}
+
+std::vector<boost::asio::const_buffer> Reply::HeaderstoBuffers()
+{
+    std::vector<boost::asio::const_buffer> buffers;
+    buffers.push_back(ToBuffer(status));
+    for (std::size_t i = 0; i < headers.size(); ++i)
+    {
+        Header &current_header = headers[i];
+        buffers.push_back(boost::asio::buffer(current_header.name));
+        buffers.push_back(boost::asio::buffer(seperators));
+        buffers.push_back(boost::asio::buffer(current_header.value));
+        buffers.push_back(boost::asio::buffer(crlf));
+    }
+    buffers.push_back(boost::asio::buffer(crlf));
+    return buffers;
+}
+
+Reply Reply::StockReply(Reply::status_type status)
+{
+    Reply reply;
+    reply.status = status;
+    reply.content.clear();
+
+    const std::string status_string = reply.ToString(status);
+    reply.content.insert(reply.content.end(), status_string.begin(), status_string.end());
+    reply.headers.emplace_back("Access-Control-Allow-Origin", "*");
+    reply.headers.emplace_back("Content-Length",
+                               UintToString(static_cast<unsigned>(reply.content.size())));
+    reply.headers.emplace_back("Content-Type", "text/html");
+    return reply;
+}
+
+std::string Reply::ToString(Reply::status_type status)
+{
+    if (Reply::ok == status)
+    {
+        return okHTML;
+    }
+    if (Reply::badRequest == status)
+    {
+        return badRequestHTML;
+    }
+    return internalServerErrorHTML;
+}
+
+boost::asio::const_buffer Reply::ToBuffer(Reply::status_type status)
+{
+    if (Reply::ok == status)
+    {
+        return boost::asio::buffer(okString);
+    }
+    if (Reply::internalServerError == status)
+    {
+        return boost::asio::buffer(internalServerErrorString);
+    }
+    return boost::asio::buffer(badRequestString);
+}
+
+Reply::Reply() : status(ok) {}
+}
diff --git a/Server/Http/Request.h b/Server/Http/Request.h
new file mode 100644
index 0000000..4746a5e
--- /dev/null
+++ b/Server/Http/Request.h
@@ -0,0 +1,48 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef REQUEST_H
+#define REQUEST_H
+
+#include <boost/asio.hpp>
+
+#include <string>
+
+namespace http
+{
+
+struct Request
+{
+    std::string uri;
+    std::string referrer;
+    std::string agent;
+    boost::asio::ip::address endpoint;
+};
+
+} // namespace http
+
+#endif // REQUEST_H
diff --git a/Server/RequestHandler.cpp b/Server/RequestHandler.cpp
new file mode 100644
index 0000000..36a2808
--- /dev/null
+++ b/Server/RequestHandler.cpp
@@ -0,0 +1,142 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "APIGrammar.h"
+#include "RequestHandler.h"
+#include "Http/Request.h"
+
+#include "../DataStructures/JSONContainer.h"
+#include "../Library/OSRM.h"
+#include "../Util/SimpleLogger.h"
+#include "../Util/StringUtil.h"
+#include "../typedefs.h"
+
+#include <osrm/Reply.h>
+#include <osrm/RouteParameters.h>
+
+#include <ctime>
+
+#include <algorithm>
+#include <iostream>
+
+RequestHandler::RequestHandler() : routing_machine(nullptr) {}
+
+void RequestHandler::handle_request(const http::Request &req, http::Reply &reply)
+{
+    // parse command
+    try
+    {
+        std::string request;
+        URIDecode(req.uri, request);
+
+        // deactivated as GCC apparently does not implement that, not even in 4.9
+        // std::time_t t = std::time(nullptr);
+        // SimpleLogger().Write() << std::put_time(std::localtime(&t), "%m-%d-%Y %H:%M:%S") <<
+        //     " " << req.endpoint.to_string() << " " <<
+        //     req.referrer << ( 0 == req.referrer.length() ? "- " :" ") <<
+        //     req.agent << ( 0 == req.agent.length() ? "- " :" ") << request;
+
+        time_t ltime;
+        struct tm *Tm;
+
+        ltime = time(nullptr);
+        Tm = localtime(&ltime);
+
+        // log timestamp
+        SimpleLogger().Write() << (Tm->tm_mday < 10 ? "0" : "") << Tm->tm_mday << "-"
+                               << (Tm->tm_mon + 1 < 10 ? "0" : "") << (Tm->tm_mon + 1) << "-"
+                               << 1900 + Tm->tm_year << " " << (Tm->tm_hour < 10 ? "0" : "")
+                               << Tm->tm_hour << ":" << (Tm->tm_min < 10 ? "0" : "") << Tm->tm_min
+                               << ":" << (Tm->tm_sec < 10 ? "0" : "") << Tm->tm_sec << " "
+                               << req.endpoint.to_string() << " " << req.referrer
+                               << (0 == req.referrer.length() ? "- " : " ") << req.agent
+                               << (0 == req.agent.length() ? "- " : " ") << request;
+
+        RouteParameters route_parameters;
+        APIGrammarParser api_parser(&route_parameters);
+
+        auto iter = request.begin();
+        const bool result = boost::spirit::qi::parse(iter, request.end(), api_parser);
+
+        // check if the was an error with the request
+        if (!result || (iter != request.end()))
+        {
+            reply = http::Reply::StockReply(http::Reply::badRequest);
+            reply.content.clear();
+            const unsigned position = static_cast<unsigned>(std::distance(request.begin(), iter));
+            JSON::Object json_result;
+            json_result.values["status"] = 400;
+            std::string message = "Query string malformed close to position ";
+            message += UintToString(position);
+            json_result.values["status_message"] = message;
+            JSON::render(reply.content, json_result);
+            return;
+        }
+
+        // parsing done, lets call the right plugin to handle the request
+        BOOST_ASSERT_MSG(routing_machine != nullptr, "pointer not init'ed");
+
+        if (!route_parameters.jsonp_parameter.empty())
+        { // prepend response with jsonp parameter
+            const std::string json_p = (route_parameters.jsonp_parameter + "(");
+            reply.content.insert(reply.content.end(), json_p.begin(), json_p.end());
+        }
+        routing_machine->RunQuery(route_parameters, reply);
+        if (!route_parameters.jsonp_parameter.empty())
+        { // append brace to jsonp response
+            reply.content.push_back(')');
+        }
+
+        // set headers
+        reply.headers.emplace_back("Content-Length",
+                                   UintToString(static_cast<unsigned>(reply.content.size())));
+        if ("gpx" == route_parameters.output_format)
+        { // gpx file
+            reply.headers.emplace_back("Content-Type", "application/gpx+xml; charset=UTF-8");
+            reply.headers.emplace_back("Content-Disposition", "attachment; filename=\"route.gpx\"");
+        }
+        else if (route_parameters.jsonp_parameter.empty())
+        { // json file
+            reply.headers.emplace_back("Content-Type", "application/json; charset=UTF-8");
+            reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.json\"");
+        }
+        else
+        { // jsonp
+            reply.headers.emplace_back("Content-Type", "text/javascript; charset=UTF-8");
+            reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.js\"");
+        }
+    }
+    catch (const std::exception &e)
+    {
+        reply = http::Reply::StockReply(http::Reply::internalServerError);
+        SimpleLogger().Write(logWARNING) << "[server error] code: " << e.what()
+                                         << ", uri: " << req.uri;
+        return;
+    }
+}
+
+void RequestHandler::RegisterRoutingMachine(OSRM *osrm) { routing_machine = osrm; }
diff --git a/Server/RequestHandler.h b/Server/RequestHandler.h
index 9dd0e28..462c34f 100644
--- a/Server/RequestHandler.h
+++ b/Server/RequestHandler.h
@@ -1,117 +1,59 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef REQUEST_HANDLER_H
 #define REQUEST_HANDLER_H
 
-#include <algorithm>
-#include <cctype> // std::tolower
 #include <string>
-#include <iostream>
-#include <boost/noncopyable.hpp>
-
-#include "APIGrammar.h"
-#include "BasicDatastructures.h"
-#include "../DataStructures/HashTable.h"
-#include "../Plugins/BasePlugin.h"
-#include "../Plugins/RouteParameters.h"
-#include "../Util/StringUtil.h"
-#include "../typedefs.h"
-
-namespace http {
-
-class RequestHandler : private boost::noncopyable {
-public:
-    explicit RequestHandler() : _pluginCount(0) { }
-
-    ~RequestHandler() {
-
-        for(unsigned i = 0; i < _pluginVector.size(); i++) {
-            BasePlugin * tempPointer = _pluginVector[i];
-            delete tempPointer;
-        }
-    }
-
-    void handle_request(const Request& req, Reply& rep){
-        //parse command
-        try {
-            std::string request(req.uri);
 
-            { //This block logs the current request to std out. should be moved to a logging component
-                time_t ltime;
-                struct tm *Tm;
+template <typename Iterator, class HandlerT> struct APIGrammar;
+struct RouteParameters;
+class OSRM;
 
-                ltime=time(NULL);
-                Tm=localtime(&ltime);
+namespace http
+{
+class Reply;
+struct Request;
+}
 
-                INFO((Tm->tm_mday < 10 ? "0" : "" )  << Tm->tm_mday << "-" << (Tm->tm_mon+1 < 10 ? "0" : "" )  << (Tm->tm_mon+1) << "-" << 1900+Tm->tm_year << " " << (Tm->tm_hour < 10 ? "0" : "" ) << Tm->tm_hour << ":" << (Tm->tm_min < 10 ? "0" : "" ) << Tm->tm_min << ":" << (Tm->tm_sec < 10 ? "0" : "" ) << Tm->tm_sec << " " <<
-                        req.endpoint.to_string() << " " << req.referrer << ( 0 == req.referrer.length() ? "- " :" ") << req.agent << ( 0 == req.agent.length() ? "- " :" ") << req.uri );
-            }
+class RequestHandler
+{
 
-            RouteParameters routeParameters;
-            APIGrammar<std::string::iterator, RouteParameters> apiParser(&routeParameters);
+  public:
+    typedef APIGrammar<std::string::iterator, RouteParameters> APIGrammarParser;
 
-            std::string::iterator it = request.begin();
-            bool result = boost::spirit::qi::parse(it, request.end(), apiParser);    // returns true if successful
-            if (!result || (it != request.end()) ) {
-                rep = http::Reply::stockReply(http::Reply::badRequest);
-                int position = std::distance(request.begin(), it);
-                std::string tmp_position_string;
-                intToString(position, tmp_position_string);
-                rep.content += "Input seems to be malformed close to position ";
-                rep.content += "<br><pre>";
-                rep.content += request;
-                rep.content += tmp_position_string;
-                rep.content += "<br>";
-                for(unsigned i = 0, end = std::distance(request.begin(), it); i < end; ++i)
-                    rep.content += " ";
-                rep.content += "^<br></pre>";
-            } else {
-                //Finished parsing, lets call the right plugin to handle the request
-                if(pluginMap.Holds(routeParameters.service)) {
-                    rep.status = Reply::ok;
-                    _pluginVector[pluginMap.Find(routeParameters.service)]->HandleRequest(routeParameters, rep );
-                } else {
-                    rep = Reply::stockReply(Reply::badRequest);
-                }
-                return;
-            }
-        } catch(std::exception& e) {
-            rep = Reply::stockReply(Reply::internalServerError);
-            std::cerr << "[server error] code: " << e.what() << ", uri: " << req.uri << std::endl;
-            return;
-        }
-    };
+    RequestHandler();
+    RequestHandler(const RequestHandler &) = delete;
 
-    void RegisterPlugin(BasePlugin * plugin) {
-        std::cout << "[handler] registering plugin " << plugin->GetDescriptor() << std::endl;
-        pluginMap.Add(plugin->GetDescriptor(), _pluginCount);
-        _pluginVector.push_back(plugin);
-        ++_pluginCount;
-    }
+    void handle_request(const http::Request &req, http::Reply &rep);
+    void RegisterRoutingMachine(OSRM *osrm);
 
-private:
-    HashTable<std::string, unsigned> pluginMap;
-    std::vector<BasePlugin *> _pluginVector;
-    unsigned _pluginCount;
+  private:
+    OSRM *routing_machine;
 };
-} // namespace http
 
 #endif // REQUEST_HANDLER_H
diff --git a/Server/RequestParser.cpp b/Server/RequestParser.cpp
new file mode 100644
index 0000000..cad05b9
--- /dev/null
+++ b/Server/RequestParser.cpp
@@ -0,0 +1,306 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "Http/Request.h"
+#include "RequestParser.h"
+
+namespace http
+{
+
+RequestParser::RequestParser() : state_(method_start), header({"", ""}) {}
+
+void RequestParser::Reset() { state_ = method_start; }
+
+boost::tuple<boost::tribool, char *>
+RequestParser::Parse(Request &req, char *begin, char *end, http::CompressionType *compression_type)
+{
+    while (begin != end)
+    {
+        boost::tribool result = consume(req, *begin++, compression_type);
+        if (result || !result)
+        {
+            return boost::make_tuple(result, begin);
+        }
+    }
+    boost::tribool result = boost::indeterminate;
+    return boost::make_tuple(result, begin);
+}
+
+boost::tribool
+RequestParser::consume(Request &req, char input, http::CompressionType *compression_type)
+{
+    switch (state_)
+    {
+    case method_start:
+        if (!isChar(input) || isCTL(input) || isTSpecial(input))
+        {
+            return false;
+        }
+        state_ = method;
+        return boost::indeterminate;
+    case method:
+        if (input == ' ')
+        {
+            state_ = uri;
+            return boost::indeterminate;
+        }
+        if (!isChar(input) || isCTL(input) || isTSpecial(input))
+        {
+            return false;
+        }
+        return boost::indeterminate;
+    case uri_start:
+        if (isCTL(input))
+        {
+            return false;
+        }
+        state_ = uri;
+        req.uri.push_back(input);
+        return boost::indeterminate;
+    case uri:
+        if (input == ' ')
+        {
+            state_ = http_version_h;
+            return boost::indeterminate;
+        }
+        if (isCTL(input))
+        {
+            return false;
+        }
+        req.uri.push_back(input);
+        return boost::indeterminate;
+    case http_version_h:
+        if (input == 'H')
+        {
+            state_ = http_version_t_1;
+            return boost::indeterminate;
+        }
+        return false;
+    case http_version_t_1:
+        if (input == 'T')
+        {
+            state_ = http_version_t_2;
+            return boost::indeterminate;
+        }
+        return false;
+    case http_version_t_2:
+        if (input == 'T')
+        {
+            state_ = http_version_p;
+            return boost::indeterminate;
+        }
+        return false;
+    case http_version_p:
+        if (input == 'P')
+        {
+            state_ = http_version_slash;
+            return boost::indeterminate;
+        }
+        return false;
+    case http_version_slash:
+        if (input == '/')
+        {
+            state_ = http_version_major_start;
+            return boost::indeterminate;
+        }
+        return false;
+    case http_version_major_start:
+        if (isDigit(input))
+        {
+            state_ = http_version_major;
+            return boost::indeterminate;
+        }
+        return false;
+    case http_version_major:
+        if (input == '.')
+        {
+            state_ = http_version_minor_start;
+            return boost::indeterminate;
+        }
+        if (isDigit(input))
+        {
+            return boost::indeterminate;
+        }
+        return false;
+    case http_version_minor_start:
+        if (isDigit(input))
+        {
+            state_ = http_version_minor;
+            return boost::indeterminate;
+        }
+        return false;
+    case http_version_minor:
+        if (input == '\r')
+        {
+            state_ = expecting_newline_1;
+            return boost::indeterminate;
+        }
+        if (isDigit(input))
+        {
+            return boost::indeterminate;
+        }
+        return false;
+    case expecting_newline_1:
+        if (input == '\n')
+        {
+            state_ = header_line_start;
+            return boost::indeterminate;
+        }
+        return false;
+    case header_line_start:
+        if (header.name == "Accept-Encoding")
+        {
+            /* giving gzip precedence over deflate */
+            if (header.value.find("deflate") != std::string::npos)
+            {
+                *compression_type = deflateRFC1951;
+            }
+            if (header.value.find("gzip") != std::string::npos)
+            {
+                *compression_type = gzipRFC1952;
+            }
+        }
+
+        if ("Referer" == header.name)
+        {
+            req.referrer = header.value;
+        }
+
+        if ("User-Agent" == header.name)
+        {
+            req.agent = header.value;
+        }
+
+        if (input == '\r')
+        {
+            state_ = expecting_newline_3;
+            return boost::indeterminate;
+        }
+        if (!isChar(input) || isCTL(input) || isTSpecial(input))
+        {
+            return false;
+        }
+        state_ = header_name;
+        header.Clear();
+        header.name.push_back(input);
+        return boost::indeterminate;
+    case header_lws:
+        if (input == '\r')
+        {
+            state_ = expecting_newline_2;
+            return boost::indeterminate;
+        }
+        if (input == ' ' || input == '\t')
+        {
+            return boost::indeterminate;
+        }
+        if (isCTL(input))
+        {
+            return false;
+        }
+        state_ = header_value;
+        return boost::indeterminate;
+    case header_name:
+        if (input == ':')
+        {
+            state_ = space_before_header_value;
+            return boost::indeterminate;
+        }
+        if (!isChar(input) || isCTL(input) || isTSpecial(input))
+        {
+            return false;
+        }
+        header.name.push_back(input);
+        return boost::indeterminate;
+    case space_before_header_value:
+        if (input == ' ')
+        {
+            state_ = header_value;
+            return boost::indeterminate;
+        }
+        return false;
+    case header_value:
+        if (input == '\r')
+        {
+            state_ = expecting_newline_2;
+            return boost::indeterminate;
+        }
+        if (isCTL(input))
+        {
+            return false;
+        }
+        header.value.push_back(input);
+        return boost::indeterminate;
+    case expecting_newline_2:
+        if (input == '\n')
+        {
+            state_ = header_line_start;
+            return boost::indeterminate;
+        }
+        return false;
+    default: // expecting_newline_3:
+        return (input == '\n');
+    // default:
+    //     return false;
+    }
+}
+
+inline bool RequestParser::isChar(int c) { return c >= 0 && c <= 127; }
+
+inline bool RequestParser::isCTL(int c) { return (c >= 0 && c <= 31) || (c == 127); }
+
+inline bool RequestParser::isTSpecial(int c)
+{
+    switch (c)
+    {
+    case '(':
+    case ')':
+    case '<':
+    case '>':
+    case '@':
+    case ',':
+    case ';':
+    case ':':
+    case '\\':
+    case '"':
+    case '/':
+    case '[':
+    case ']':
+    case '?':
+    case '=':
+    case '{':
+    case '}':
+    case ' ':
+    case '\t':
+        return true;
+    default:
+        return false;
+    }
+}
+
+inline bool RequestParser::isDigit(int c) { return c >= '0' && c <= '9'; }
+}
diff --git a/Server/RequestParser.h b/Server/RequestParser.h
index 7e33f9e..4b74d83 100644
--- a/Server/RequestParser.h
+++ b/Server/RequestParser.h
@@ -1,287 +1,86 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef REQUEST_PARSER_H
 #define REQUEST_PARSER_H
 
+#include "Http/CompressionType.h"
+#include <osrm/Header.h>
+
 #include <boost/logic/tribool.hpp>
 #include <boost/tuple/tuple.hpp>
-#include "BasicDatastructures.h"
-
-namespace http {
-
-class RequestParser {
-public:
-    RequestParser() : state_(method_start) { }
-    void Reset() { state_ = method_start; }
-
-    boost::tuple<boost::tribool, char*> Parse(Request& req, char* begin, char* end, CompressionType * compressionType) {
-        while (begin != end) {
-            boost::tribool result = consume(req, *begin++, compressionType);
-            if (result || !result){
-                return boost::make_tuple(result, begin);
-            }
-        }
-        boost::tribool result = boost::indeterminate;
-        return boost::make_tuple(result, begin);
-    }
-
-private:
-    boost::tribool consume(Request& req, char input, CompressionType * compressionType) {
-        switch (state_) {
-        case method_start:
-            if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
-                return false;
-            } else {
-                state_ = method;
-                return boost::indeterminate;
-            }
-        case method:
-            if (input == ' ') {
-                state_ = uri;
-                return boost::indeterminate;
-            } else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
-                return false;
-            } else {
-                return boost::indeterminate;
-            }
-        case uri_start:
-            if (isCTL(input)) {
-                return false;
-            } else {
-                state_ = uri;
-                req.uri.push_back(input);
-                return boost::indeterminate;
-            }
-        case uri:
-            if (input == ' ') {
-                state_ = http_version_h;
-                return boost::indeterminate;
-            } else if (isCTL(input)) {
-                return false;
-            } else {
-                req.uri.push_back(input);
-                return boost::indeterminate;
-            }
-        case http_version_h:
-            if (input == 'H') {
-                state_ = http_version_t_1;
-                return boost::indeterminate;
-            } else {
-                return false;
-            }
-        case http_version_t_1:
-            if (input == 'T') {
-                state_ = http_version_t_2;
-                return boost::indeterminate;
-            } else {
-                return false;
-            }
-        case http_version_t_2:
-            if (input == 'T') {
-                state_ = http_version_p;
-                return boost::indeterminate;
-            } else {
-                return false;
-            }
-        case http_version_p:
-            if (input == 'P') {
-                state_ = http_version_slash;
-                return boost::indeterminate;
-            } else {
-                return false;
-            }
-        case http_version_slash:
-            if (input == '/') {
-                state_ = http_version_major_start;
-                return boost::indeterminate;
-            } else {
-                return false;
-            }
-        case http_version_major_start:
-            if (isDigit(input)) {
-                state_ = http_version_major;
-                return boost::indeterminate;
-            } else {
-                return false;
-            }
-        case http_version_major:
-            if (input == '.') {
-                state_ = http_version_minor_start;
-                return boost::indeterminate;
-            } else if (isDigit(input)) {
-                return boost::indeterminate;
-            } else {
-                return false;
-            }
-        case http_version_minor_start:
-            if (isDigit(input)) {
-                state_ = http_version_minor;
-                return boost::indeterminate;
-            } else {
-                return false;
-            }
-        case http_version_minor:
-            if (input == '\r') {
-                state_ = expecting_newline_1;
-                return boost::indeterminate;
-            } else if (isDigit(input)) {
-                return boost::indeterminate;
-            }
-            else {
-                return false;
-            }
-        case expecting_newline_1:
-            if (input == '\n') {
-                state_ = header_line_start;
-                return boost::indeterminate;
-            } else {
-                return false;
-            }
-        case header_line_start:
-            if(header.name == "Accept-Encoding") {
-                /* giving gzip precedence over deflate */
-                if(header.value.find("deflate") != std::string::npos)
-                    *compressionType = deflateRFC1951;
-                if(header.value.find("gzip") != std::string::npos)
-                    *compressionType = gzipRFC1952;
-            }
-
-            if("Referer" == header.name)
-                req.referrer = header.value;
-
-            if("User-Agent" == header.name)
-                req.agent = header.value;
-
-            if (input == '\r') {
-                state_ = expecting_newline_3;
-                return boost::indeterminate;
-            } else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
-                return false;
-            } else {
-                state_ = header_name;
-                header.Clear();
-                header.name.push_back(input);
-                return boost::indeterminate;
-            }
-        case header_lws:
-            if (input == '\r') {
-                state_ = expecting_newline_2;
-                return boost::indeterminate;
-            } else if (input == ' ' || input == '\t') {
-                return boost::indeterminate;
-            }
-            else if (isCTL(input)) {
-                return false;
-            } else {
-                state_ = header_value;
-                return boost::indeterminate;
-            }
-        case header_name:
-            if (input == ':') {
-                state_ = space_before_header_value;
-                return boost::indeterminate;
-            } else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
-                return false;
-            } else {
-                header.name.push_back(input);
-                return boost::indeterminate;
-            }
-        case space_before_header_value:
-            if (input == ' ') {
-                state_ = header_value;
-                return boost::indeterminate;
-            } else {
-                return false;
-            }
-        case header_value:
-            if (input == '\r') {
-                state_ = expecting_newline_2;
-                return boost::indeterminate;
-            } else if (isCTL(input)) {
-                return false;
-            } else {
-                header.value.push_back(input);
-                return boost::indeterminate;
-            }
-        case expecting_newline_2:
-            if (input == '\n') {
-                state_ = header_line_start;
-                return boost::indeterminate;
-            } else {
-                return false;
-            }
-        case expecting_newline_3:
-            return (input == '\n');
-        default:
-            return false;
-        }
-    }
-
-    inline bool isChar(int c) {
-        return c >= 0 && c <= 127;
-    }
-
-    inline bool isCTL(int c) {
-        return (c >= 0 && c <= 31) || (c == 127);
-    }
-
-    inline bool isTSpecial(int c) {
-        switch (c) {
-        case '(': case ')': case '<': case '>': case '@':
-        case ',': case ';': case ':': case '\\': case '"':
-        case '/': case '[': case ']': case '?': case '=':
-        case '{': case '}': case ' ': case '\t':
-            return true;
-        default:
-            return false;
-        }
-    }
-
-    inline bool isDigit(int c) {
-        return c >= '0' && c <= '9';
-    }
 
-    enum state {
-        method_start,
-        method,
-        uri_start,
-        uri,
-        http_version_h,
-        http_version_t_1,
-        http_version_t_2,
-        http_version_p,
-        http_version_slash,
-        http_version_major_start,
-        http_version_major,
-        http_version_minor_start,
-        http_version_minor,
-        expecting_newline_1,
-        header_line_start,
-        header_lws,
-        header_name,
-        space_before_header_value,
-        header_value,
-        expecting_newline_2,
-        expecting_newline_3
-    } state_;
+namespace http
+{
+
+struct Request;
+
+class RequestParser
+{
+  public:
+    RequestParser();
+    void Reset();
+
+    boost::tuple<boost::tribool, char *>
+    Parse(Request &req, char *begin, char *end, CompressionType *compressionType);
+
+  private:
+    boost::tribool consume(Request &req, char input, CompressionType *compressionType);
+
+    inline bool isChar(int c);
+
+    inline bool isCTL(int c);
+
+    inline bool isTSpecial(int c);
+
+    inline bool isDigit(int c);
+
+    enum state
+    { method_start,
+      method,
+      uri_start,
+      uri,
+      http_version_h,
+      http_version_t_1,
+      http_version_t_2,
+      http_version_p,
+      http_version_slash,
+      http_version_major_start,
+      http_version_major,
+      http_version_minor_start,
+      http_version_minor,
+      expecting_newline_1,
+      header_line_start,
+      header_lws,
+      header_name,
+      space_before_header_value,
+      header_value,
+      expecting_newline_2,
+      expecting_newline_3 } state_;
 
     Header header;
 };
diff --git a/Server/Server.h b/Server/Server.h
index db525f5..be18c3b 100644
--- a/Server/Server.h
+++ b/Server/Server.h
@@ -1,88 +1,108 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef SERVER_H
 #define SERVER_H
 
-#include <vector>
-#include <boost/asio.hpp>
-#include <boost/bind.hpp>
-#include <boost/noncopyable.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/thread.hpp>
+#include "../Util/StringUtil.h"
 
 #include "Connection.h"
 #include "RequestHandler.h"
 
-namespace http {
-
-class Server: private boost::noncopyable {
-public:
-	explicit Server(const std::string& address, const std::string& port, unsigned thread_pool_size) : threadPoolSize(thread_pool_size), acceptor(ioService), newConnection(new Connection(ioService, requestHandler)), requestHandler(){
-		boost::asio::ip::tcp::resolver resolver(ioService);
-		boost::asio::ip::tcp::resolver::query query(address, port);
-		boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
-
-		acceptor.open(endpoint.protocol());
-		acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
-		acceptor.bind(endpoint);
-		acceptor.listen();
-		acceptor.async_accept(newConnection->socket(), boost::bind(&Server::handleAccept, this, boost::asio::placeholders::error));
-	}
-
-	void Run() {
-		std::vector<boost::shared_ptr<boost::thread> > threads;
-		for (unsigned i = 0; i < threadPoolSize; ++i) {
-			boost::shared_ptr<boost::thread> thread(new boost::thread(boost::bind(&boost::asio::io_service::run, &ioService)));
-			threads.push_back(thread);
-		}
-		for (unsigned i = 0; i < threads.size(); ++i)
-			threads[i]->join();
-	}
-
-	void Stop() {
-		ioService.stop();
-	}
-
-	RequestHandler & GetRequestHandlerPtr() {
-		return requestHandler;
-	}
-
-private:
-	typedef boost::shared_ptr<Connection > ConnectionPtr;
-
-	void handleAccept(const boost::system::error_code& e) {
-		if (!e) {
-			newConnection->start();
-			newConnection.reset(new Connection(ioService, requestHandler));
-			acceptor.async_accept(newConnection->socket(), boost::bind(&Server::handleAccept, this, boost::asio::placeholders::error));
-		}
-	}
-
-	unsigned threadPoolSize;
-	boost::asio::io_service ioService;
-	boost::asio::ip::tcp::acceptor acceptor;
-	ConnectionPtr newConnection;
-	RequestHandler requestHandler;
-};
+#include <boost/asio.hpp>
+#include <boost/bind.hpp>
 
-}   // namespace http
+#include <functional>
+#include <memory>
+#include <thread>
+#include <vector>
+
+class Server
+{
+  public:
+    explicit Server(const std::string &address, const int port, const unsigned thread_pool_size)
+        : thread_pool_size(thread_pool_size), acceptor(io_service),
+          new_connection(new http::Connection(io_service, request_handler)), request_handler()
+    {
+        const std::string port_string = IntToString(port);
+
+        boost::asio::ip::tcp::resolver resolver(io_service);
+        boost::asio::ip::tcp::resolver::query query(address, port_string);
+        boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
+
+        acceptor.open(endpoint.protocol());
+        acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+        acceptor.bind(endpoint);
+        acceptor.listen();
+        acceptor.async_accept(
+            new_connection->socket(),
+            boost::bind(&Server::HandleAccept, this, boost::asio::placeholders::error));
+    }
+
+    Server() = delete;
+    Server(const Server &) = delete;
+
+    void Run()
+    {
+        std::vector<std::shared_ptr<std::thread>> threads;
+        for (unsigned i = 0; i < thread_pool_size; ++i)
+        {
+            std::shared_ptr<std::thread> thread = std::make_shared<std::thread>(
+                boost::bind(&boost::asio::io_service::run, &io_service));
+            threads.push_back(thread);
+        }
+        for (unsigned i = 0; i < threads.size(); ++i)
+        {
+            threads[i]->join();
+        }
+    }
+
+    void Stop() { io_service.stop(); }
+
+    RequestHandler &GetRequestHandlerPtr() { return request_handler; }
+
+  private:
+    void HandleAccept(const boost::system::error_code &e)
+    {
+        if (!e)
+        {
+            new_connection->start();
+            new_connection.reset(new http::Connection(io_service, request_handler));
+            acceptor.async_accept(
+                new_connection->socket(),
+                boost::bind(&Server::HandleAccept, this, boost::asio::placeholders::error));
+        }
+    }
+
+    unsigned thread_pool_size;
+    boost::asio::io_service io_service;
+    boost::asio::ip::tcp::acceptor acceptor;
+    std::shared_ptr<http::Connection> new_connection;
+    RequestHandler request_handler;
+};
 
 #endif // SERVER_H
diff --git a/Server/ServerConfiguration.h b/Server/ServerConfiguration.h
deleted file mode 100644
index 0393a7f..0000000
--- a/Server/ServerConfiguration.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef SERVERCONFIGURATION_H_
-#define SERVERCONFIGURATION_H_
-
-#include "../Util/BaseConfiguration.h"
-
-typedef BaseConfiguration ServerConfiguration;
-
-#endif /* SERVERCONFIGURATION_H_ */
diff --git a/Server/ServerFactory.h b/Server/ServerFactory.h
index 966dc92..5e037cf 100644
--- a/Server/ServerFactory.h
+++ b/Server/ServerFactory.h
@@ -1,84 +1,49 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
- Created on: 26.11.2010
- Author: dennis
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
- */
+*/
 
-#ifndef SERVERFACTORY_H_
-#define SERVERFACTORY_H_
-
-#include <zlib.h>
+#ifndef SERVER_FACTORY_H
+#define SERVER_FACTORY_H
 
 #include "Server.h"
-#include "ServerConfiguration.h"
-
-#include "../Util/InputFileUtil.h"
-#include "../Util/OpenMPWrapper.h"
-#include "../Util/StringUtil.h"
-
-#include "../typedefs.h"
-
-typedef http::Server Server;
-
-struct ServerFactory {
-	static Server * CreateServer(ServerConfiguration& serverConfig) {
-
-		if(!testDataFile(serverConfig.GetParameter("nodesData"))) {
-			ERR("nodes file not found");
-		}
+#include "../Util/SimpleLogger.h"
 
-		if(!testDataFile(serverConfig.GetParameter("hsgrData"))) {
-		    ERR("hsgr file not found");
-		}
-
-		if(!testDataFile(serverConfig.GetParameter("namesData"))) {
-		    ERR("names file not found");
-		}
-
-		if(!testDataFile(serverConfig.GetParameter("ramIndex"))) {
-		    ERR("ram index file not found");
-		}
-
-		if(!testDataFile(serverConfig.GetParameter("fileIndex"))) {
-		    ERR("file index file not found");
-		}
-
-		int threads = omp_get_num_procs();
-		if(serverConfig.GetParameter("IP") == "")
-			serverConfig.SetParameter("IP", "0.0.0.0");
-		if(serverConfig.GetParameter("Port") == "")
-			serverConfig.SetParameter("Port", "5000");
-
-		if(stringToInt(serverConfig.GetParameter("Threads")) != 0 && stringToInt(serverConfig.GetParameter("Threads")) <= threads)
-			threads = stringToInt( serverConfig.GetParameter("Threads") );
-
-		std::cout << "[server] http 1.1 compression handled by zlib version " << zlibVersion() << std::endl;
-		Server * server = new Server(serverConfig.GetParameter("IP"), serverConfig.GetParameter("Port"), threads);
-		return server;
-	}
+#include <zlib.h>
 
-	static Server * CreateServer(const char * iniFile) {
-		ServerConfiguration serverConfig(iniFile);
-		return CreateServer(serverConfig);
-	}
+struct ServerFactory
+{
+    ServerFactory() = delete;
+    ServerFactory(const ServerFactory &) = delete;
+    static Server *CreateServer(std::string &ip_address, int ip_port, unsigned requested_num_threads)
+    {
+        SimpleLogger().Write() << "http 1.1 compression handled by zlib version " << zlibVersion();
+        const unsigned hardware_threads = std::max(1u, std::thread::hardware_concurrency());
+        const unsigned real_num_threads = std::min(hardware_threads, requested_num_threads);
+        return new Server(ip_address, ip_port, real_num_threads);
+    }
 };
 
-#endif /* SERVERFACTORY_H_ */
+#endif // SERVER_FACTORY_H
diff --git a/Tools/componentAnalysis.cpp b/Tools/componentAnalysis.cpp
deleted file mode 100644
index 64790aa..0000000
--- a/Tools/componentAnalysis.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#define VERBOSE(x) x
-#define VERBOSE2(x)
-
-#ifdef NDEBUG
-#undef VERBOSE
-#undef VERBOSE2
-#endif
-
-#include <boost/foreach.hpp>
-
-#include <fstream>
-#include <istream>
-#include <iostream>
-#include <cstring>
-#include <string>
-#include <vector>
-
-#include "../typedefs.h"
-#include "../Algorithms/StronglyConnectedComponents.h"
-#include "../DataStructures/BinaryHeap.h"
-#include "../DataStructures/DeallocatingVector.h"
-#include "../DataStructures/DynamicGraph.h"
-#include "../DataStructures/QueryEdge.h"
-#include "../DataStructures/TurnInstructions.h"
-#include "../Util/BaseConfiguration.h"
-#include "../Util/InputFileUtil.h"
-#include "../Util/GraphLoader.h"
-
-using namespace std;
-
-typedef QueryEdge::EdgeData EdgeData;
-typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
-typedef BaseConfiguration ContractorConfiguration;
-
-std::vector<NodeInfo> internalToExternalNodeMapping;
-std::vector<_Restriction> inputRestrictions;
-std::vector<NodeID> bollardNodes;
-std::vector<NodeID> trafficLightNodes;
-
-int main (int argc, char *argv[]) {
-    if(argc < 3) {
-        ERR("usage: " << std::endl << argv[0] << " <osrm-data> <osrm-restrictions>");
-    }
-    std::string SRTM_ROOT;
-
-    INFO("Using restrictions from file: " << argv[2]);
-    std::ifstream restrictionsInstream(argv[2], ios::binary);
-    if(!restrictionsInstream.good()) {
-        ERR("Could not access <osrm-restrictions> files");
-    }
-    _Restriction restriction;
-    unsigned usableRestrictionsCounter(0);
-    restrictionsInstream.read((char*)&usableRestrictionsCounter, sizeof(unsigned));
-    inputRestrictions.resize(usableRestrictionsCounter);
-    restrictionsInstream.read((char *)&(inputRestrictions[0]), usableRestrictionsCounter*sizeof(_Restriction));
-    restrictionsInstream.close();
-
-    std::ifstream in;
-    in.open (argv[1], std::ifstream::in | std::ifstream::binary);
-    if (!in.is_open()) {
-        ERR("Cannot open " << argv[1]);
-    }
-
-    std::vector<ImportEdge> edgeList;
-    NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions);
-    in.close();
-    INFO(inputRestrictions.size() << " restrictions, " << bollardNodes.size() << " bollard nodes, " << trafficLightNodes.size() << " traffic lights");
-
-    /***
-     * Building an edge-expanded graph from node-based input an turn restrictions
-     */
-
-    INFO("Starting SCC graph traversal");
-    TarjanSCC * tarjan = new TarjanSCC (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping);
-    std::vector<ImportEdge>().swap(edgeList);
-    tarjan->Run();
-    std::vector<_Restriction>().swap(inputRestrictions);
-    std::vector<NodeID>().swap(bollardNodes);
-    std::vector<NodeID>().swap(trafficLightNodes);
-    INFO("finished component analysis");
-    return 0;
-}
diff --git a/Tools/components.cpp b/Tools/components.cpp
new file mode 100644
index 0000000..945d94f
--- /dev/null
+++ b/Tools/components.cpp
@@ -0,0 +1,136 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "../typedefs.h"
+#include "../Algorithms/StronglyConnectedComponents.h"
+#include "../DataStructures/DynamicGraph.h"
+#include "../DataStructures/QueryEdge.h"
+#include "../DataStructures/TurnInstructions.h"
+#include "../Util/GraphLoader.h"
+#include "../Util/OSRMException.h"
+#include "../Util/SimpleLogger.h"
+#include "../Util/FingerPrint.h"
+
+#include <fstream>
+#include <memory>
+#include <string>
+#include <vector>
+
+typedef QueryEdge::EdgeData EdgeData;
+typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
+
+std::vector<NodeInfo> internal_to_external_node_map;
+std::vector<TurnRestriction> restrictions_vector;
+std::vector<NodeID> bollard_node_IDs_vector;
+std::vector<NodeID> traffic_light_node_IDs_vector;
+
+int main(int argc, char *argv[])
+{
+    LogPolicy::GetInstance().Unmute();
+    if (argc < 3)
+    {
+        SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0] << " <osrm> <osrm.restrictions>";
+        return -1;
+    }
+
+    try
+    {
+        SimpleLogger().Write() << "Using restrictions from file: " << argv[2];
+        std::ifstream restriction_ifstream(argv[2], std::ios::binary);
+        const FingerPrint fingerprint_orig;
+        FingerPrint fingerprint_loaded;
+        restriction_ifstream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
+
+        if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig))
+        {
+            SimpleLogger().Write(logWARNING) << argv[2] << " was prepared with a different build. "
+                                                           "Reprocess to get rid of this warning.";
+        }
+
+        if (!restriction_ifstream.good())
+        {
+            throw OSRMException("Could not access <osrm-restrictions> files");
+        }
+        uint32_t usable_restriction_count = 0;
+        restriction_ifstream.read((char *)&usable_restriction_count, sizeof(uint32_t));
+        restrictions_vector.resize(usable_restriction_count);
+
+        if (usable_restriction_count>0)
+        {
+            restriction_ifstream.read((char *)&(restrictions_vector[0]),
+                                 usable_restriction_count * sizeof(TurnRestriction));
+        }
+        restriction_ifstream.close();
+
+        std::ifstream input_stream;
+        input_stream.open(argv[1], std::ifstream::in | std::ifstream::binary);
+
+        if (!input_stream.is_open())
+        {
+            throw OSRMException("Cannot open osrm file");
+        }
+
+        std::vector<ImportEdge> edge_list;
+        const NodeID number_of_nodes = readBinaryOSRMGraphFromStream(input_stream,
+                                                                     edge_list,
+                                                                     bollard_node_IDs_vector,
+                                                                     traffic_light_node_IDs_vector,
+                                                                     &internal_to_external_node_map,
+                                                                     restrictions_vector);
+        input_stream.close();
+
+        BOOST_ASSERT_MSG(restrictions_vector.size() == usable_restriction_count,
+                         "size of restrictions_vector changed");
+
+        SimpleLogger().Write() << restrictions_vector.size() << " restrictions, "
+                               << bollard_node_IDs_vector.size() << " bollard nodes, "
+                               << traffic_light_node_IDs_vector.size() << " traffic lights";
+
+        /***
+         * Building an edge-expanded graph from node-based input an turn
+         * restrictions
+         */
+
+        SimpleLogger().Write() << "Starting SCC graph traversal";
+        std::shared_ptr<TarjanSCC> tarjan =
+            std::make_shared<TarjanSCC>(number_of_nodes,
+                                        edge_list,
+                                        bollard_node_IDs_vector,
+                                        traffic_light_node_IDs_vector,
+                                        restrictions_vector,
+                                        internal_to_external_node_map);
+        std::vector<ImportEdge>().swap(edge_list);
+
+        tarjan->Run();
+        SimpleLogger().Write() << "finished component analysis";
+    }
+    catch (const std::exception &e)
+    {
+        SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
+    }
+    return 0;
+}
diff --git a/Tools/io-benchmark.cpp b/Tools/io-benchmark.cpp
new file mode 100644
index 0000000..6304aae
--- /dev/null
+++ b/Tools/io-benchmark.cpp
@@ -0,0 +1,348 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "../Util/GitDescription.h"
+#include "../Util/OSRMException.h"
+#include "../Util/SimpleLogger.h"
+#include "../Util/TimingUtil.h"
+
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <fcntl.h>
+#ifdef __linux__
+#include <malloc.h>
+#endif
+
+#include <algorithm>
+#include <chrono>
+#include <iomanip>
+#include <numeric>
+#include <vector>
+
+const unsigned number_of_elements = 268435456;
+
+struct Statistics
+{
+    double min, max, med, mean, dev;
+};
+
+void RunStatistics(std::vector<double> &timings_vector, Statistics &stats)
+{
+    std::sort(timings_vector.begin(), timings_vector.end());
+    stats.min = timings_vector.front();
+    stats.max = timings_vector.back();
+    stats.med = timings_vector[timings_vector.size() / 2];
+    double primary_sum = std::accumulate(timings_vector.begin(), timings_vector.end(), 0.0);
+    stats.mean = primary_sum / timings_vector.size();
+
+    double primary_sq_sum = std::inner_product(
+        timings_vector.begin(), timings_vector.end(), timings_vector.begin(), 0.0);
+    stats.dev = std::sqrt(primary_sq_sum / timings_vector.size() - (stats.mean * stats.mean));
+}
+
+int main(int argc, char *argv[])
+{
+    LogPolicy::GetInstance().Unmute();
+
+    SimpleLogger().Write() << "starting up engines, " << g_GIT_DESCRIPTION << ", "
+                           << "compiled at " << __DATE__ << ", " __TIME__;
+
+#ifdef __FreeBSD__
+    SimpleLogger().Write() << "Not supported on FreeBSD";
+    return 0;
+#endif
+#ifdef WIN32
+    SimpleLogger().Write() << "Not supported on Windows";
+    return 0;
+#else
+
+
+    if (1 == argc)
+    {
+        SimpleLogger().Write(logWARNING) << "usage: " << argv[0] << " /path/on/device";
+        return -1;
+    }
+
+    boost::filesystem::path test_path = boost::filesystem::path(argv[1]);
+    test_path /= "osrm.tst";
+    SimpleLogger().Write(logDEBUG) << "temporary file: " << test_path.string();
+
+    try
+    {
+        // create files for testing
+        if (2 == argc)
+        {
+            // create file to test
+            if (boost::filesystem::exists(test_path))
+            {
+                throw OSRMException("Data file already exists");
+            }
+
+            int *random_array = new int[number_of_elements];
+            std::generate(random_array, random_array + number_of_elements, std::rand);
+#ifdef __APPLE__
+            FILE *fd = fopen(test_path.string().c_str(), "w");
+            fcntl(fileno(fd), F_NOCACHE, 1);
+            fcntl(fileno(fd), F_RDAHEAD, 0);
+            TIMER_START(write_1gb);
+            write(fileno(fd), (char *)random_array, number_of_elements * sizeof(unsigned));
+            TIMER_STOP(write_1gb);
+            fclose(fd);
+#endif
+#ifdef __linux__
+            int f =
+                open(test_path.string().c_str(), O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, S_IRWXU);
+            if (-1 == f)
+            {
+                throw OSRMException("Could not open random data file");
+            }
+            TIMER_START(write_1gb);
+            int ret = write(f, random_array, number_of_elements * sizeof(unsigned));
+            if (0 > ret)
+            {
+                throw OSRMException("could not write random data file");
+            }
+            TIMER_STOP(write_1gb);
+            close(f);
+#endif
+            delete[] random_array;
+            SimpleLogger().Write(logDEBUG) << "writing raw 1GB took " << TIMER_SEC(write_1gb)
+                                           << "s";
+            SimpleLogger().Write() << "raw write performance: " << std::setprecision(5)
+                                   << std::fixed << 1024 * 1024 / TIMER_SEC(write_1gb)
+                                   << "MB/sec";
+
+            SimpleLogger().Write(logDEBUG)
+                << "finished creation of random data. Flush disk cache now!";
+        }
+        else
+        {
+            // Run Non-Cached I/O benchmarks
+            if (!boost::filesystem::exists(test_path))
+            {
+                throw OSRMException("data file does not exist");
+            }
+
+            // volatiles do not get optimized
+            Statistics stats;
+
+#ifdef __APPLE__
+            volatile unsigned single_block[1024];
+            char *raw_array = new char[number_of_elements * sizeof(unsigned)];
+            FILE *fd = fopen(test_path.string().c_str(), "r");
+            fcntl(fileno(fd), F_NOCACHE, 1);
+            fcntl(fileno(fd), F_RDAHEAD, 0);
+#endif
+#ifdef __linux__
+            char *single_block = (char *)memalign(512, 1024 * sizeof(unsigned));
+
+            int f = open(test_path.string().c_str(), O_RDONLY | O_DIRECT | O_SYNC);
+            if (-1 == f)
+            {
+                SimpleLogger().Write(logDEBUG) << "opened, error: " << strerror(errno);
+                return -1;
+            }
+            char *raw_array = (char *)memalign(512, number_of_elements * sizeof(unsigned));
+#endif
+            TIMER_START(read_1gb);
+#ifdef __APPLE__
+            read(fileno(fd), raw_array, number_of_elements * sizeof(unsigned));
+            close(fileno(fd));
+            fd = fopen(test_path.string().c_str(), "r");
+#endif
+#ifdef __linux__
+            int ret = read(f, raw_array, number_of_elements * sizeof(unsigned));
+            SimpleLogger().Write(logDEBUG) << "read " << ret
+                                           << " bytes, error: " << strerror(errno);
+            close(f);
+            f = open(test_path.string().c_str(), O_RDONLY | O_DIRECT | O_SYNC);
+            SimpleLogger().Write(logDEBUG) << "opened, error: " << strerror(errno);
+#endif
+            TIMER_STOP(read_1gb);
+
+            SimpleLogger().Write(logDEBUG) << "reading raw 1GB took " << TIMER_SEC(read_1gb)
+                                           << "s";
+            SimpleLogger().Write() << "raw read performance: " << std::setprecision(5) << std::fixed
+                                   << 1024 * 1024 / TIMER_SEC(read_1gb) << "MB/sec";
+
+            std::vector<double> timing_results_raw_random;
+            SimpleLogger().Write(logDEBUG) << "running 1000 random I/Os of 4KB";
+
+#ifdef __APPLE__
+            fseek(fd, 0, SEEK_SET);
+#endif
+#ifdef __linux__
+            lseek(f, 0, SEEK_SET);
+#endif
+            // make 1000 random access, time each I/O seperately
+            unsigned number_of_blocks = (number_of_elements * sizeof(unsigned) - 1) / 4096;
+            for (unsigned i = 0; i < 1000; ++i)
+            {
+                unsigned block_to_read = std::rand() % number_of_blocks;
+                off_t current_offset = block_to_read * 4096;
+                TIMER_START(random_access);
+#ifdef __APPLE__
+                int ret1 = fseek(fd, current_offset, SEEK_SET);
+                int ret2 = read(fileno(fd), (char *)&single_block[0], 4096);
+#endif
+
+#ifdef __FreeBSD__
+                int ret1 = 0;
+                int ret2 = 0;
+#endif
+
+#ifdef __linux__
+                int ret1 = lseek(f, current_offset, SEEK_SET);
+                int ret2 = read(f, (char *)single_block, 4096);
+#endif
+                TIMER_STOP(random_access);
+                if (((off_t) - 1) == ret1)
+                {
+                    SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
+                    SimpleLogger().Write(logWARNING) << "seek error " << strerror(errno);
+                    throw OSRMException("seek error");
+                }
+                if (-1 == ret2)
+                {
+                    SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
+                    SimpleLogger().Write(logWARNING) << "read error " << strerror(errno);
+                    throw OSRMException("read error");
+                }
+                timing_results_raw_random.push_back(TIMER_SEC(random_access));
+            }
+
+            // Do statistics
+            SimpleLogger().Write(logDEBUG) << "running raw random I/O statistics";
+            std::ofstream random_csv("random.csv", std::ios::trunc);
+            for (unsigned i = 0; i < timing_results_raw_random.size(); ++i)
+            {
+                random_csv << i << ", " << timing_results_raw_random[i] << std::endl;
+            }
+            random_csv.close();
+            RunStatistics(timing_results_raw_random, stats);
+
+            SimpleLogger().Write() << "raw random I/O: " << std::setprecision(5) << std::fixed
+                                   << "min: " << stats.min << "ms, "
+                                   << "mean: " << stats.mean << "ms, "
+                                   << "med: " << stats.med << "ms, "
+                                   << "max: " << stats.max << "ms, "
+                                   << "dev: " << stats.dev << "ms";
+
+            std::vector<double> timing_results_raw_seq;
+#ifdef __APPLE__
+            fseek(fd, 0, SEEK_SET);
+#endif
+#ifdef __linux__
+            lseek(f, 0, SEEK_SET);
+#endif
+
+            // read every 100th block
+            for (unsigned i = 0; i < 1000; ++i)
+            {
+                off_t current_offset = i * 4096;
+                TIMER_START(read_every_100);
+#ifdef __APPLE__
+                int ret1 = fseek(fd, current_offset, SEEK_SET);
+                int ret2 = read(fileno(fd), (char *)&single_block, 4096);
+#endif
+
+#ifdef __FreeBSD__
+                int ret1 = 0;
+                int ret2 = 0;
+#endif
+
+#ifdef __linux__
+                int ret1 = lseek(f, current_offset, SEEK_SET);
+
+                int ret2 = read(f, (char *)single_block, 4096);
+#endif
+                TIMER_STOP(read_every_100);
+                if (((off_t) - 1) == ret1)
+                {
+                    SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
+                    SimpleLogger().Write(logWARNING) << "seek error " << strerror(errno);
+                    throw OSRMException("seek error");
+                }
+                if (-1 == ret2)
+                {
+                    SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
+                    SimpleLogger().Write(logWARNING) << "read error " << strerror(errno);
+                    throw OSRMException("read error");
+                }
+                timing_results_raw_seq.push_back(TIMER_SEC(read_every_100));
+            }
+#ifdef __APPLE__
+            fclose(fd);
+            // free(single_element);
+            free(raw_array);
+// free(single_block);
+#endif
+#ifdef __linux__
+            close(f);
+#endif
+            // Do statistics
+            SimpleLogger().Write(logDEBUG) << "running sequential I/O statistics";
+            // print simple statistics: min, max, median, variance
+            std::ofstream seq_csv("sequential.csv", std::ios::trunc);
+            for (unsigned i = 0; i < timing_results_raw_seq.size(); ++i)
+            {
+                seq_csv << i << ", " << timing_results_raw_seq[i] << std::endl;
+            }
+            seq_csv.close();
+            RunStatistics(timing_results_raw_seq, stats);
+            SimpleLogger().Write() << "raw sequential I/O: " << std::setprecision(5) << std::fixed
+                                   << "min: " << stats.min << "ms, "
+                                   << "mean: " << stats.mean << "ms, "
+                                   << "med: " << stats.med << "ms, "
+                                   << "max: " << stats.max << "ms, "
+                                   << "dev: " << stats.dev << "ms";
+
+            if (boost::filesystem::exists(test_path))
+            {
+                boost::filesystem::remove(test_path);
+                SimpleLogger().Write(logDEBUG) << "removing temporary files";
+            }
+        }
+    }
+    catch (const std::exception &e)
+    {
+        SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
+        SimpleLogger().Write(logWARNING) << "cleaning up, and exiting";
+        if (boost::filesystem::exists(test_path))
+        {
+            boost::filesystem::remove(test_path);
+            SimpleLogger().Write(logWARNING) << "removing temporary files";
+        }
+        return -1;
+    }
+    return 0;
+#endif
+}
diff --git a/Tools/simpleclient.cpp b/Tools/simpleclient.cpp
new file mode 100644
index 0000000..68d4b1d
--- /dev/null
+++ b/Tools/simpleclient.cpp
@@ -0,0 +1,131 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "../Library/OSRM.h"
+#include "../Util/GitDescription.h"
+#include "../Util/ProgramOptions.h"
+#include "../Util/SimpleLogger.h"
+
+#include <osrm/Reply.h>
+#include <osrm/RouteParameters.h>
+#include <osrm/ServerPaths.h>
+
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/json_parser.hpp>
+
+#include <iostream>
+#include <stack>
+#include <string>
+#include <sstream>
+
+// Dude, real recursions on the OS stack? You must be brave...
+void print_tree(boost::property_tree::ptree const &property_tree, const unsigned recursion_depth)
+{
+    auto end = property_tree.end();
+    for (auto tree_iterator = property_tree.begin(); tree_iterator != end; ++tree_iterator)
+    {
+        for (unsigned current_recursion = 0; current_recursion < recursion_depth;
+             ++current_recursion)
+        {
+            std::cout << " " << std::flush;
+        }
+        std::cout << tree_iterator->first << ": " << tree_iterator->second.get_value<std::string>()
+                  << std::endl;
+        print_tree(tree_iterator->second, recursion_depth + 1);
+    }
+}
+
+int main(int argc, const char *argv[])
+{
+    LogPolicy::GetInstance().Unmute();
+    try
+    {
+        std::string ip_address;
+        int ip_port, requested_thread_num;
+        bool use_shared_memory = false, trial = false;
+        ServerPaths server_paths;
+        if (!GenerateServerProgramOptions(argc,
+                                          argv,
+                                          server_paths,
+                                          ip_address,
+                                          ip_port,
+                                          requested_thread_num,
+                                          use_shared_memory,
+                                          trial))
+        {
+            return 0;
+        }
+
+        SimpleLogger().Write() << "starting up engines, " << g_GIT_DESCRIPTION << ", "
+                               << "compiled at " << __DATE__ << ", " __TIME__;
+
+        OSRM routing_machine(server_paths, use_shared_memory);
+
+        RouteParameters route_parameters;
+        route_parameters.zoom_level = 18;           // no generalization
+        route_parameters.print_instructions = true; // turn by turn instructions
+        route_parameters.alternate_route = true;    // get an alternate route, too
+        route_parameters.geometry = true;           // retrieve geometry of route
+        route_parameters.compression = true;        // polyline encoding
+        route_parameters.check_sum = UINT_MAX;      // see wiki
+        route_parameters.service = "viaroute";      // that's routing
+        route_parameters.output_format = "json";
+        route_parameters.jsonp_parameter = ""; // set for jsonp wrapping
+        route_parameters.language = "";        // unused atm
+        // route_parameters.hints.push_back(); // see wiki, saves I/O if done properly
+
+        // start_coordinate
+        route_parameters.coordinates.emplace_back(52.519930 * COORDINATE_PRECISION,
+                                                  13.438640 * COORDINATE_PRECISION);
+        // target_coordinate
+        route_parameters.coordinates.emplace_back(52.513191 * COORDINATE_PRECISION,
+                                                  13.415852 * COORDINATE_PRECISION);
+        http::Reply osrm_reply;
+        routing_machine.RunQuery(route_parameters, osrm_reply);
+
+        // attention: super-inefficient hack below:
+
+        std::stringstream my_stream;
+        for (const auto &element : osrm_reply.content)
+        {
+            std::cout << element;
+            my_stream << element;
+        }
+        std::cout << std::endl;
+
+        boost::property_tree::ptree property_tree;
+        boost::property_tree::read_json(my_stream, property_tree);
+
+        print_tree(property_tree, 0);
+    }
+    catch (std::exception &current_exception)
+    {
+        SimpleLogger().Write(logWARNING) << "caught exception: " << current_exception.what();
+        return -1;
+    }
+    return 0;
+}
diff --git a/Tools/unlock_all_mutexes.cpp b/Tools/unlock_all_mutexes.cpp
new file mode 100644
index 0000000..4d4156f
--- /dev/null
+++ b/Tools/unlock_all_mutexes.cpp
@@ -0,0 +1,52 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "../Util/GitDescription.h"
+#include "../Util/SimpleLogger.h"
+#include "../Server/DataStructures/SharedBarriers.h"
+
+#include <iostream>
+
+int main()
+{
+    LogPolicy::GetInstance().Unmute();
+    try
+    {
+        SimpleLogger().Write() << "starting up engines, " << g_GIT_DESCRIPTION << ", "
+                               << "compiled at " << __DATE__ << ", " __TIME__;
+        SimpleLogger().Write() << "Releasing all locks";
+        SharedBarriers barrier;
+        barrier.pending_update_mutex.unlock();
+        barrier.query_mutex.unlock();
+        barrier.update_mutex.unlock();
+    }
+    catch (const std::exception &e)
+    {
+        SimpleLogger().Write(logWARNING) << "[excpetion] " << e.what();
+    }
+    return 0;
+}
diff --git a/Util/Azimuth.h b/Util/Azimuth.h
index 166f55f..c4bf815 100644
--- a/Util/Azimuth.h
+++ b/Util/Azimuth.h
@@ -1,52 +1,73 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+*/
 
-#ifndef AZIMUTH_H_
-#define AZIMUTH_H_
+#ifndef AZIMUTH_H
+#define AZIMUTH_H
 
 #include <string>
 
-struct Azimuth {
-    static std::string Get(const double heading) {
-        if(heading <= 202.5) {
-            if(heading >= 0 && heading <= 22.5)
+struct Azimuth
+{
+    static std::string Get(const double heading)
+    {
+        if (heading <= 202.5)
+        {
+            if (heading >= 0 && heading <= 22.5)
+            {
                 return "N";
-            if(heading > 22.5 && heading <= 67.5)
+            }
+            if (heading > 22.5 && heading <= 67.5)
+            {
                 return "NE";
-            if(heading > 67.5 && heading <= 112.5)
+            }
+            if (heading > 67.5 && heading <= 112.5)
+            {
                 return "E";
-            if(heading > 112.5 && heading <= 157.5)
+            }
+            if (heading > 112.5 && heading <= 157.5)
+            {
                 return "SE";
+            }
             return "S";
         }
-        if(heading > 202.5 && heading <= 247.5)
+        if (heading > 202.5 && heading <= 247.5)
+        {
             return "SW";
-        if(heading > 247.5 && heading <= 292.5)
+        }
+        if (heading > 247.5 && heading <= 292.5)
+        {
             return "W";
-        if(heading > 292.5 && heading <= 337.5)
+        }
+        if (heading > 292.5 && heading <= 337.5)
+        {
             return "NW";
+        }
         return "N";
     }
 };
 
-
-#endif /* AZIMUTH_H_ */
+#endif // AZIMUTH_H
diff --git a/Util/BaseConfiguration.h b/Util/BaseConfiguration.h
deleted file mode 100644
index 69bc61f..0000000
--- a/Util/BaseConfiguration.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef BASECONFIGURATION_H_
-#define BASECONFIGURATION_H_
-
-#include <iostream>
-#include <string>
-#include <exception>
-#include <fstream>
-
-#include "../DataStructures/HashTable.h"
-
-class BaseConfiguration {
-public:
-    BaseConfiguration(const char * configFile) {
-        std::ifstream config( configFile );
-        if(!config) {
-            std::cerr << "[config] .ini not found" << std::endl;
-            return;
-        }
-
-        std::string line;
-        try {
-            if (config.is_open()) {
-                while ( config.good() )  {
-                    getline (config,line);
-                    std::vector<std::string> tokens;
-                    Tokenize(line, tokens);
-                    if(2 == tokens.size() )
-                        parameters.Add(tokens[0], tokens[1]);
-                }
-                config.close();
-            }
-        } catch(std::exception& e) {
-            ERR("[config] " << configFile << " not found -> Exception: " <<e.what());
-            if(config.is_open())
-                config.close();
-        }
-    }
-
-    std::string GetParameter(const char * key){
-        return GetParameter(std::string(key));
-    }
-
-    std::string GetParameter(std::string key) {
-        return parameters.Find(key);
-    }
-
-    void SetParameter(const char* key, const char* value) {
-        SetParameter(std::string(key), std::string(value));
-    }
-
-    void SetParameter(std::string key, std::string value) {
-        parameters.Set(key, value);
-    }
-
-private:
-    void Tokenize(const std::string& str, std::vector<std::string>& tokens,  const std::string& delimiters = "=") {
-        std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
-        std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
-
-        while (std::string::npos != pos || std::string::npos != lastPos) {
-            std::string temp = str.substr(lastPos, pos - lastPos);
-            TrimStringRight(temp);
-            TrimStringLeft(temp);
-            tokens.push_back( temp );
-            lastPos = str.find_first_not_of(delimiters, pos);
-            pos = str.find_first_of(delimiters, lastPos);
-        }
-    }
-    void TrimStringRight(std::string& str) {
-        std::string::size_type pos = str.find_last_not_of(" ");
-        if (pos != std::string::npos)
-            str.erase(pos+1);
-        else
-            str.erase( str.begin() , str.end() );
-    }
-    void TrimStringLeft(std::string& str) {
-        std::string::size_type pos = str.find_first_not_of(" ");
-        if (pos != std::string::npos)
-            str.erase(0, pos);
-        else
-            str.erase( str.begin() , str.end() );
-    }
-
-    HashTable<std::string, std::string> parameters;
-};
-
-#endif /* BASECONFIGURATION_H_ */
diff --git a/Util/BoostFileSystemFix.h b/Util/BoostFileSystemFix.h
new file mode 100644
index 0000000..1e1e98e
--- /dev/null
+++ b/Util/BoostFileSystemFix.h
@@ -0,0 +1,147 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef BOOST_FILE_SYSTEM_FIX_H
+#define BOOST_FILE_SYSTEM_FIX_H
+
+#include "OSRMException.h"
+#include "SimpleLogger.h"
+
+#include <boost/any.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/program_options.hpp>
+
+// This is one big workaround for latest boost renaming woes.
+
+#if BOOST_FILESYSTEM_VERSION < 3
+#warning Boost Installation with Filesystem3 missing, activating workaround
+#include <cstdio>
+#endif
+
+namespace boost
+{
+namespace filesystem
+{
+
+// Validator for boost::filesystem::path, that verifies that the file
+// exists. The validate() function must be defined in the same namespace
+// as the target type, (boost::filesystem::path in this case), otherwise
+// it is not called
+// inline void validate(
+//     boost::any & v,
+//     const std::vector<std::string> & values,
+//     boost::filesystem::path *,
+//     int
+// ) {
+//     boost::program_options::validators::check_first_occurrence(v);
+//     const std::string & input_string =
+//         boost::program_options::validators::get_single_string(values);
+//     // SimpleLogger().Write() << "validator called for " << input_string;
+//     // SimpleLogger().Write() << "validator called for " << input_string;
+//     if(boost::filesystem::is_regular_file(input_string)) {
+//         v = boost::any(boost::filesystem::path(input_string));
+//     } else {
+//         throw OSRMException(input_string + " not found");
+//     }
+// }
+
+// adapted from:
+// http://stackoverflow.com/questions/1746136/how-do-i-normalize-a-pathname-using-boostfilesystem
+inline boost::filesystem::path
+portable_canonical(const boost::filesystem::path &relative_path,
+                   const boost::filesystem::path &current_path = boost::filesystem::current_path())
+{
+    const boost::filesystem::path absolute_path =
+        boost::filesystem::absolute(relative_path, current_path);
+
+    boost::filesystem::path canonical_path;
+    for (auto path_iterator = absolute_path.begin(); path_iterator != absolute_path.end();
+         ++path_iterator)
+    {
+        if (".." == path_iterator->string())
+        {
+            // /a/b/.. is not necessarily /a if b is a symbolic link
+            if (boost::filesystem::is_symlink(canonical_path))
+            {
+                canonical_path /= *path_iterator;
+            }
+            else if (".." == canonical_path.filename())
+            {
+                // /a/b/../.. is not /a/b/.. under most circumstances
+                // We can end up with ..s in our result because of symbolic links
+                canonical_path /= *path_iterator;
+            }
+            else
+            {
+                // Otherwise it should be safe to resolve the parent
+                canonical_path = canonical_path.parent_path();
+            }
+        }
+        else if ("." == path_iterator->string())
+        {
+            // Ignore
+        }
+        else
+        {
+            // Just cat other path entries
+            canonical_path /= *path_iterator;
+        }
+    }
+    BOOST_ASSERT(canonical_path.is_absolute());
+    BOOST_ASSERT(boost::filesystem::exists(canonical_path));
+    return canonical_path;
+}
+
+#if BOOST_FILESYSTEM_VERSION < 3
+
+inline path temp_directory_path()
+{
+    char *buffer;
+    buffer = tmpnam(NULL);
+
+    return path(buffer);
+}
+
+inline path unique_path(const path &) { return temp_directory_path(); }
+
+#endif
+}
+}
+
+#ifndef BOOST_FILESYSTEM_VERSION
+#define BOOST_FILESYSTEM_VERSION 3
+#endif
+
+inline void AssertPathExists(const boost::filesystem::path &path)
+{
+    if (!boost::filesystem::is_regular_file(path))
+    {
+        throw OSRMException(path.string() + " not found.");
+    }
+}
+
+#endif /* BOOST_FILE_SYSTEM_FIX_H */
diff --git a/Util/ComputeAngle.h b/Util/ComputeAngle.h
new file mode 100644
index 0000000..02f678a
--- /dev/null
+++ b/Util/ComputeAngle.h
@@ -0,0 +1,57 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef COMPUTE_ANGLE_H
+#define COMPUTE_ANGLE_H
+
+#include "TrigonometryTables.h"
+#include "../Util/MercatorUtil.h"
+#include <osrm/Coordinate.h>
+
+#include <boost/assert.hpp>
+#include <cmath>
+
+/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
+template <class CoordinateT>
+inline static double GetAngleBetweenThreeFixedPointCoordinates(const CoordinateT &A,
+                                                               const CoordinateT &C,
+                                                               const CoordinateT &B)
+{
+    const double v1x = (A.lon - C.lon) / COORDINATE_PRECISION;
+    const double v1y = lat2y(A.lat / COORDINATE_PRECISION) - lat2y(C.lat / COORDINATE_PRECISION);
+    const double v2x = (B.lon - C.lon) / COORDINATE_PRECISION;
+    const double v2y = lat2y(B.lat / COORDINATE_PRECISION) - lat2y(C.lat / COORDINATE_PRECISION);
+
+    double angle = (atan2_lookup(v2y, v2x) - atan2_lookup(v1y, v1x)) * 180 / M_PI;
+    while (angle < 0)
+    {
+        angle += 360;
+    }
+    return angle;
+}
+
+#endif // COMPUTE_ANGLE_H
diff --git a/Util/ContainerUtils.h b/Util/ContainerUtils.h
index 215e988..2517545 100644
--- a/Util/ContainerUtils.h
+++ b/Util/ContainerUtils.h
@@ -1,9 +1,29 @@
 /*
- * ContainerUtils.h
- *
- *  Created on: 02.02.2013
- *      Author: dennis
- */
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef CONTAINERUTILS_H_
 #define CONTAINERUTILS_H_
@@ -11,24 +31,41 @@
 #include <algorithm>
 #include <vector>
 
-template<typename T>
-inline void sort_unique_resize(std::vector<T> & vector) {
-	std::sort(vector.begin(), vector.end());
-	unsigned number_of_unique_elements = std::unique(vector.begin(), vector.end()) - vector.begin();
-	vector.resize(number_of_unique_elements);
+template <typename T> inline void sort_unique_resize(std::vector<T> &vector)
+{
+    std::sort(vector.begin(), vector.end());
+    const auto number_of_unique_elements = std::unique(vector.begin(), vector.end()) - vector.begin();
+    vector.resize(number_of_unique_elements);
 }
 
-template<typename T>
-inline void sort_unique_resize_shrink_vector(std::vector<T> & vector) {
-	sort_unique_resize(vector);
-	std::vector<T>().swap(vector);
+template <typename T> inline void sort_unique_resize_shrink_vector(std::vector<T> &vector)
+{
+    sort_unique_resize(vector);
+    std::vector<T>().swap(vector);
 }
 
-template<typename T>
-inline void remove_consecutive_duplicates_from_vector(std::vector<T> & vector) {
-    unsigned number_of_unique_elements = std::unique(vector.begin(), vector.end()) - vector.begin();
+template <typename T> inline void remove_consecutive_duplicates_from_vector(std::vector<T> &vector)
+{
+    const auto number_of_unique_elements = std::unique(vector.begin(), vector.end()) - vector.begin();
     vector.resize(number_of_unique_elements);
 }
 
+template <typename FwdIter, typename Func>
+Func for_each_pair(FwdIter iter_begin, FwdIter iter_end, Func func)
+{
+    if (iter_begin == iter_end)
+    {
+        return func;
+    }
+
+    FwdIter iter_next = iter_begin;
+    ++iter_next;
+
+    for (; iter_next != iter_end; ++iter_begin, ++iter_next)
+    {
+        func(*iter_begin, *iter_next);
+    }
+    return func;
+}
 
 #endif /* CONTAINERUTILS_H_ */
diff --git a/Util/DataStoreOptions.h b/Util/DataStoreOptions.h
new file mode 100644
index 0000000..7a76bfb
--- /dev/null
+++ b/Util/DataStoreOptions.h
@@ -0,0 +1,284 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef DATA_STORE_OPTIONS_H
+#define DATA_STORE_OPTIONS_H
+
+#include "BoostFileSystemFix.h"
+#include "GitDescription.h"
+#include "IniFileUtil.h"
+#include "OSRMException.h"
+#include "SimpleLogger.h"
+
+#include <osrm/ServerPaths.h>
+
+#include <boost/any.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/program_options.hpp>
+
+#include <string>
+
+// generate boost::program_options object for the routing part
+inline bool GenerateDataStoreOptions(const int argc, const char *argv[], ServerPaths &paths, bool & springclean)
+{
+    // declare a group of options that will be allowed only on command line
+    boost::program_options::options_description generic_options("Options");
+    generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")
+        ("springclean,s", "Remove all regions in shared memory")("config,c",
+        boost::program_options::value<boost::filesystem::path>(&paths["config"])
+            ->default_value("server.ini"),
+        "Path to a configuration file");
+
+    // declare a group of options that will be allowed both on command line
+    // as well as in a config file
+    boost::program_options::options_description config_options("Configuration");
+    config_options.add_options()(
+        "hsgrdata",
+        boost::program_options::value<boost::filesystem::path>(&paths["hsgrdata"]),
+        ".hsgr file")("nodesdata",
+                      boost::program_options::value<boost::filesystem::path>(&paths["nodesdata"]),
+                      ".nodes file")(
+        "edgesdata",
+        boost::program_options::value<boost::filesystem::path>(&paths["edgesdata"]),
+        ".edges file")("geometry",
+                       boost::program_options::value<boost::filesystem::path>(&paths["geometry"]),
+                       ".geometry file")(
+        "ramindex",
+        boost::program_options::value<boost::filesystem::path>(&paths["ramindex"]),
+        ".ramIndex file")(
+        "fileindex",
+        boost::program_options::value<boost::filesystem::path>(&paths["fileindex"]),
+        ".fileIndex file")(
+        "namesdata",
+        boost::program_options::value<boost::filesystem::path>(&paths["namesdata"]),
+        ".names file")("timestamp",
+                       boost::program_options::value<boost::filesystem::path>(&paths["timestamp"]),
+                       ".timestamp file");
+
+    // hidden options, will be allowed both on command line and in config
+    // file, but will not be shown to the user
+    boost::program_options::options_description hidden_options("Hidden options");
+    hidden_options.add_options()(
+        "base,b",
+        boost::program_options::value<boost::filesystem::path>(&paths["base"]),
+        "base path to .osrm file");
+
+    // positional option
+    boost::program_options::positional_options_description positional_options;
+    positional_options.add("base", 1);
+
+    // combine above options for parsing
+    boost::program_options::options_description cmdline_options;
+    cmdline_options.add(generic_options).add(config_options).add(hidden_options);
+
+    boost::program_options::options_description config_file_options;
+    config_file_options.add(config_options).add(hidden_options);
+
+    boost::program_options::options_description visible_options(
+        boost::filesystem::basename(argv[0]) + " [<options>] <configuration>");
+    visible_options.add(generic_options).add(config_options);
+
+    // parse command line options
+    boost::program_options::variables_map option_variables;
+    boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
+                                      .options(cmdline_options)
+                                      .positional(positional_options)
+                                      .run(),
+                                  option_variables);
+
+    if (option_variables.count("version"))
+    {
+        SimpleLogger().Write() << g_GIT_DESCRIPTION;
+        return false;
+    }
+
+    if (option_variables.count("help"))
+    {
+        SimpleLogger().Write() << visible_options;
+        return false;
+    }
+
+    if (option_variables.count("springclean"))
+    {
+        springclean = true;
+        return true;
+    }
+    boost::program_options::notify(option_variables);
+
+    const bool parameter_present = (paths.find("hsgrdata") != paths.end() &&
+                                    !paths.find("hsgrdata")->second.string().empty()) ||
+                                   (paths.find("nodesdata") != paths.end() &&
+                                    !paths.find("nodesdata")->second.string().empty()) ||
+                                   (paths.find("edgesdata") != paths.end() &&
+                                    !paths.find("edgesdata")->second.string().empty()) ||
+                                   (paths.find("geometry") != paths.end() &&
+                                    !paths.find("geometry")->second.string().empty()) ||
+                                   (paths.find("ramindex") != paths.end() &&
+                                    !paths.find("ramindex")->second.string().empty()) ||
+                                   (paths.find("fileindex") != paths.end() &&
+                                    !paths.find("fileindex")->second.string().empty()) ||
+                                   (paths.find("timestamp") != paths.end() &&
+                                    !paths.find("timestamp")->second.string().empty());
+
+    if (parameter_present)
+    {
+        if ((paths.find("config") != paths.end() &&
+             boost::filesystem::is_regular_file(paths.find("config")->second)) ||
+            option_variables.count("base"))
+        {
+            SimpleLogger().Write(logWARNING) << "conflicting parameters";
+            SimpleLogger().Write() << visible_options;
+            return false;
+        }
+    }
+
+    // parse config file
+    ServerPaths::iterator path_iterator = paths.find("config");
+    if (path_iterator != paths.end() && boost::filesystem::is_regular_file(path_iterator->second) &&
+        !option_variables.count("base"))
+    {
+        SimpleLogger().Write() << "Reading options from: " << path_iterator->second.string();
+        std::string ini_file_contents = ReadIniFileAndLowerContents(path_iterator->second);
+        std::stringstream config_stream(ini_file_contents);
+        boost::program_options::store(parse_config_file(config_stream, config_file_options),
+                                      option_variables);
+        boost::program_options::notify(option_variables);
+    }
+    else if (option_variables.count("base"))
+    {
+        path_iterator = paths.find("base");
+        BOOST_ASSERT(paths.end() != path_iterator);
+        std::string base_string = path_iterator->second.string();
+
+        path_iterator = paths.find("hsgrdata");
+        if (path_iterator != paths.end())
+        {
+            path_iterator->second = base_string + ".hsgr";
+        }
+
+        path_iterator = paths.find("nodesdata");
+        if (path_iterator != paths.end())
+        {
+            path_iterator->second = base_string + ".nodes";
+        }
+
+        path_iterator = paths.find("edgesdata");
+        if (path_iterator != paths.end())
+        {
+            path_iterator->second = base_string + ".edges";
+        }
+
+        path_iterator = paths.find("geometry");
+        if (path_iterator != paths.end())
+        {
+            path_iterator->second = base_string + ".geometry";
+        }
+
+        path_iterator = paths.find("ramindex");
+        if (path_iterator != paths.end())
+        {
+            path_iterator->second = base_string + ".ramIndex";
+        }
+
+        path_iterator = paths.find("fileindex");
+        if (path_iterator != paths.end())
+        {
+            path_iterator->second = base_string + ".fileIndex";
+        }
+
+        path_iterator = paths.find("namesdata");
+        if (path_iterator != paths.end())
+        {
+            path_iterator->second = base_string + ".names";
+        }
+
+        path_iterator = paths.find("timestamp");
+        if (path_iterator != paths.end())
+        {
+            path_iterator->second = base_string + ".timestamp";
+        }
+    }
+
+    path_iterator = paths.find("hsgrdata");
+    if (path_iterator == paths.end() || path_iterator->second.string().empty())
+    {
+        throw OSRMException(".hsgr file must be specified");
+    }
+    AssertPathExists(path_iterator->second);
+
+    path_iterator = paths.find("nodesdata");
+    if (path_iterator == paths.end() || path_iterator->second.string().empty())
+    {
+        throw OSRMException(".nodes file must be specified");
+    }
+    AssertPathExists(path_iterator->second);
+
+    path_iterator = paths.find("edgesdata");
+    if (path_iterator == paths.end() || path_iterator->second.string().empty())
+    {
+        throw OSRMException(".edges file must be specified");
+    }
+    AssertPathExists(path_iterator->second);
+
+    path_iterator = paths.find("geometry");
+    if (path_iterator == paths.end() || path_iterator->second.string().empty())
+    {
+        throw OSRMException(".geometry file must be specified");
+    }
+    AssertPathExists(path_iterator->second);
+
+    path_iterator = paths.find("ramindex");
+    if (path_iterator == paths.end() || path_iterator->second.string().empty())
+    {
+        throw OSRMException(".ramindex file must be specified");
+    }
+    AssertPathExists(path_iterator->second);
+
+    path_iterator = paths.find("fileindex");
+    if (path_iterator == paths.end() || path_iterator->second.string().empty())
+    {
+        throw OSRMException(".fileindex file must be specified");
+    }
+    AssertPathExists(path_iterator->second);
+
+    path_iterator = paths.find("namesdata");
+    if (path_iterator == paths.end() || path_iterator->second.string().empty())
+    {
+        throw OSRMException(".names file must be specified");
+    }
+    AssertPathExists(path_iterator->second);
+
+    path_iterator = paths.find("timestamp");
+    if (path_iterator == paths.end() || path_iterator->second.string().empty())
+    {
+        throw OSRMException(".timestamp file must be specified");
+    }
+
+    return true;
+}
+
+#endif /* DATA_STORE_OPTIONS_H */
diff --git a/Util/FingerPrint.cpp.in b/Util/FingerPrint.cpp.in
new file mode 100644
index 0000000..d1ce4f0
--- /dev/null
+++ b/Util/FingerPrint.cpp.in
@@ -0,0 +1,106 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "FingerPrint.h"
+
+#include "OSRMException.h"
+
+#include <boost/uuid/name_generator.hpp>
+
+#include <cstring>
+
+#include <algorithm>
+#include <string>
+
+#cmakedefine01 HAS64BITS
+#cmakedefine MD5PREPARE "${MD5PREPARE}"
+#cmakedefine MD5RTREE "${MD5RTREE}"
+#cmakedefine MD5GRAPH "${MD5GRAPH}"
+#cmakedefine MD5OBJECTS "${MD5OBJECTS}"
+
+FingerPrint::FingerPrint() : magic_number(1297240911)
+{
+    md5_prepare[32] = md5_tree[32] = md5_graph[32] = md5_objects[32] = '\0';
+
+    boost::uuids::name_generator gen(named_uuid);
+    std::string temp_string(__DATE__);
+    temp_string += __TIME__;
+
+    std::memcpy(md5_prepare, MD5PREPARE, strlen(MD5PREPARE));
+    temp_string += md5_prepare;
+    std::memcpy(md5_tree, MD5RTREE, 32);
+    temp_string += md5_tree;
+    std::memcpy(md5_graph, MD5GRAPH, 32);
+    temp_string += md5_graph;
+    std::memcpy(md5_objects, MD5OBJECTS, 32);
+    temp_string += md5_objects;
+
+    named_uuid = gen(temp_string);
+    has_64_bits = HAS64BITS;
+}
+
+FingerPrint::~FingerPrint() {}
+
+const boost::uuids::uuid &FingerPrint::GetFingerPrint() const { return named_uuid; }
+
+bool FingerPrint::IsMagicNumberOK() const { return 1297240911 == magic_number; }
+
+bool FingerPrint::TestGraphUtil(const FingerPrint &other) const
+{
+    if (!other.IsMagicNumberOK())
+    {
+        throw OSRMException("hsgr input file misses magic number. Check or reprocess the file");
+    }
+    return std::equal(md5_graph, md5_graph + 32, other.md5_graph);
+}
+
+bool FingerPrint::TestPrepare(const FingerPrint &other) const
+{
+    if (!other.IsMagicNumberOK())
+    {
+        throw OSRMException("osrm input file misses magic number. Check or reprocess the file");
+    }
+    return std::equal(md5_prepare, md5_prepare + 32, other.md5_prepare);
+}
+
+bool FingerPrint::TestRTree(const FingerPrint &other) const
+{
+    if (!other.IsMagicNumberOK())
+    {
+        throw OSRMException("r-tree input file misses magic number. Check or reprocess the file");
+    }
+    return std::equal(md5_tree, md5_tree + 32, other.md5_tree);
+}
+
+bool FingerPrint::TestQueryObjects(const FingerPrint &other) const
+{
+    if (!other.IsMagicNumberOK())
+    {
+        throw OSRMException("missing magic number. Check or reprocess the file");
+    }
+    return std::equal(md5_objects, md5_objects + 32, other.md5_objects);
+}
diff --git a/Util/FingerPrint.h b/Util/FingerPrint.h
new file mode 100644
index 0000000..c61fe36
--- /dev/null
+++ b/Util/FingerPrint.h
@@ -0,0 +1,60 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef FINGERPRINT_H
+#define FINGERPRINT_H
+
+#include <boost/uuid/uuid.hpp>
+
+// implements a singleton, i.e. there is one and only one conviguration object
+class FingerPrint
+{
+  public:
+    FingerPrint();
+    FingerPrint(const FingerPrint&) = delete;
+    ~FingerPrint();
+    const boost::uuids::uuid &GetFingerPrint() const;
+    bool IsMagicNumberOK() const;
+    bool TestGraphUtil(const FingerPrint &other) const;
+    bool TestPrepare(const FingerPrint &other) const;
+    bool TestRTree(const FingerPrint &other) const;
+    bool TestNodeInfo(const FingerPrint &other) const;
+    bool TestQueryObjects(const FingerPrint &other) const;
+
+  private:
+    const unsigned magic_number;
+    char md5_prepare[33];
+    char md5_tree[33];
+    char md5_graph[33];
+    char md5_objects[33];
+
+    // initialize to {6ba7b810-9dad-11d1-80b4-00c04fd430c8}
+    boost::uuids::uuid named_uuid;
+    bool has_64_bits;
+};
+
+#endif /* FingerPrint_H */
diff --git a/Util/GitDescription.cpp.in b/Util/GitDescription.cpp.in
new file mode 100644
index 0000000..6f4ba7e
--- /dev/null
+++ b/Util/GitDescription.cpp.in
@@ -0,0 +1,29 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#define GIT_DESCRIPTION "${GIT_DESCRIPTION}"
+char g_GIT_DESCRIPTION[] = GIT_DESCRIPTION;
diff --git a/Util/GitDescription.h b/Util/GitDescription.h
new file mode 100644
index 0000000..d3a00f4
--- /dev/null
+++ b/Util/GitDescription.h
@@ -0,0 +1,33 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef GIT_DESCRIPTION_H
+#define GIT_DESCRIPTION_H
+
+extern char g_GIT_DESCRIPTION[];
+
+#endif //GIT_DESCRIPTION_H
diff --git a/Util/GraphLoader.h b/Util/GraphLoader.h
index 5dc50f8..612332b 100644
--- a/Util/GraphLoader.h
+++ b/Util/GraphLoader.h
@@ -1,377 +1,320 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef GRAPHLOADER_H
 #define GRAPHLOADER_H
 
+#include "OSRMException.h"
 #include "../DataStructures/ImportNode.h"
 #include "../DataStructures/ImportEdge.h"
-#include "../DataStructures/NodeCoords.h"
+#include "../DataStructures/QueryNode.h"
 #include "../DataStructures/Restriction.h"
+#include "../Util/SimpleLogger.h"
+#include "../Util/FingerPrint.h"
 #include "../typedefs.h"
 
 #include <boost/assert.hpp>
-#include <boost/unordered_map.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+#include <tbb/parallel_sort.h>
 
-#include <cassert>
 #include <cmath>
 
 #include <algorithm>
 #include <fstream>
 #include <iostream>
 #include <iomanip>
+#include <unordered_map>
 #include <vector>
 
-typedef boost::unordered_map<NodeID, NodeID> ExternalNodeMap;
-
-template<class EdgeT>
-struct _ExcessRemover {
-    inline bool operator()( const EdgeT & edge ) const {
-        return edge.source() == UINT_MAX;
+template <typename EdgeT>
+NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream,
+                                     std::vector<EdgeT> &edge_list,
+                                     std::vector<NodeID> &barrier_node_list,
+                                     std::vector<NodeID> &traffic_light_node_list,
+                                     std::vector<NodeInfo> *int_to_ext_node_id_map,
+                                     std::vector<TurnRestriction> &restriction_list)
+{
+    const FingerPrint fingerprint_orig;
+    FingerPrint fingerprint_loaded;
+    input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
+
+    if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig))
+    {
+        SimpleLogger().Write(logWARNING) << ".osrm was prepared with different build.\n"
+                                            "Reprocess to get rid of this warning.";
     }
-};
 
-template<typename EdgeT>
-NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, std::vector<NodeID> &bollardNodes, std::vector<NodeID> &trafficLightNodes, std::vector<NodeInfo> * int2ExtNodeMap, std::vector<_Restriction> & inputRestrictions) {
     NodeID n, source, target;
     EdgeID m;
-    short dir;// direction (0 = open, 1 = forward, 2+ = open)
-    ExternalNodeMap ext2IntNodeMap;
-    in.read((char*)&n, sizeof(NodeID));
-    DEBUG("Importing n = " << n << " nodes ");
-    _Node node;
-    for (NodeID i=0; i<n; ++i) {
-        in.read((char*)&node, sizeof(_Node));
-        int2ExtNodeMap->push_back(NodeInfo(node.lat, node.lon, node.id));
-        ext2IntNodeMap.insert(std::make_pair(node.id, i));
-        if(node.bollard)
-        	bollardNodes.push_back(i);
-        if(node.trafficLight)
-        	trafficLightNodes.push_back(i);
+    short dir; // direction (0 = open, 1 = forward, 2+ = open)
+    std::unordered_map<NodeID, NodeID> ext_to_int_id_map;
+    input_stream.read((char *)&n, sizeof(NodeID));
+    SimpleLogger().Write() << "Importing n = " << n << " nodes ";
+    ExternalMemoryNode current_node;
+    for (NodeID i = 0; i < n; ++i)
+    {
+        input_stream.read((char *)&current_node, sizeof(ExternalMemoryNode));
+        int_to_ext_node_id_map->emplace_back(current_node.lat, current_node.lon, current_node.node_id);
+        ext_to_int_id_map.emplace(current_node.node_id, i);
+        if (current_node.bollard)
+        {
+            barrier_node_list.emplace_back(i);
+        }
+        if (current_node.trafficLight)
+        {
+            traffic_light_node_list.emplace_back(i);
+        }
     }
 
-    //tighten vector sizes
-    std::vector<NodeID>(bollardNodes).swap(bollardNodes);
-    std::vector<NodeID>(trafficLightNodes).swap(trafficLightNodes);
-
-    in.read((char*)&m, sizeof(unsigned));
-    DEBUG(" and " << m << " edges ");
-    for(unsigned i = 0; i < inputRestrictions.size(); ++i) {
-        ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(inputRestrictions[i].fromNode);
-        if( intNodeID == ext2IntNodeMap.end()) {
-            DEBUG("Unmapped from Node of restriction");
+    // tighten vector sizes
+    barrier_node_list.shrink_to_fit();
+    traffic_light_node_list.shrink_to_fit();
+    input_stream.read((char *)&m, sizeof(unsigned));
+    SimpleLogger().Write() << " and " << m << " edges ";
+    for (TurnRestriction &current_restriction : restriction_list)
+    {
+        auto internal_id_iter = ext_to_int_id_map.find(current_restriction.fromNode);
+        if (internal_id_iter == ext_to_int_id_map.end())
+        {
+            SimpleLogger().Write(logDEBUG) << "Unmapped from Node of restriction";
             continue;
-
         }
-        inputRestrictions[i].fromNode = intNodeID->second;
+        current_restriction.fromNode = internal_id_iter->second;
 
-        intNodeID = ext2IntNodeMap.find(inputRestrictions[i].viaNode);
-        if( intNodeID == ext2IntNodeMap.end()) {
-            DEBUG("Unmapped via node of restriction");
+        internal_id_iter = ext_to_int_id_map.find(current_restriction.viaNode);
+        if (internal_id_iter == ext_to_int_id_map.end())
+        {
+            SimpleLogger().Write(logDEBUG) << "Unmapped via node of restriction";
             continue;
         }
-        inputRestrictions[i].viaNode = intNodeID->second;
+        current_restriction.viaNode = internal_id_iter->second;
 
-        intNodeID = ext2IntNodeMap.find(inputRestrictions[i].toNode);
-        if( intNodeID == ext2IntNodeMap.end()) {
-            DEBUG("Unmapped to node of restriction");
+        internal_id_iter = ext_to_int_id_map.find(current_restriction.toNode);
+        if (internal_id_iter == ext_to_int_id_map.end())
+        {
+            SimpleLogger().Write(logDEBUG) << "Unmapped to node of restriction";
             continue;
         }
-        inputRestrictions[i].toNode = intNodeID->second;
+        current_restriction.toNode = internal_id_iter->second;
     }
 
-    edgeList.reserve(m);
+    edge_list.reserve(m);
     EdgeWeight weight;
     short type;
     NodeID nameID;
     int length;
-    bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow;
-
-    for (EdgeID i=0; i<m; ++i) {
-        in.read((char*)&source,             sizeof(unsigned));
-        in.read((char*)&target,             sizeof(unsigned));
-        in.read((char*)&length,             sizeof(int));
-        in.read((char*)&dir,                sizeof(short));
-        in.read((char*)&weight,             sizeof(int));
-        in.read((char*)&type,               sizeof(short));
-        in.read((char*)&nameID,             sizeof(unsigned));
-        in.read((char*)&isRoundabout,       sizeof(bool));
-        in.read((char*)&ignoreInGrid,       sizeof(bool));
-        in.read((char*)&isAccessRestricted, sizeof(bool));
-        in.read((char*)&isContraFlow,       sizeof(bool));
-
-        BOOST_ASSERT_MSG(length > 0, "loaded null length edge" );
+    bool is_roundabout, ignore_in_grid, is_access_restricted, is_contra_flow, is_split;
+
+    for (EdgeID i = 0; i < m; ++i)
+    {
+        input_stream.read((char *)&source, sizeof(unsigned));
+        input_stream.read((char *)&target, sizeof(unsigned));
+        input_stream.read((char *)&length, sizeof(int));
+        input_stream.read((char *)&dir, sizeof(short));
+        input_stream.read((char *)&weight, sizeof(int));
+        input_stream.read((char *)&type, sizeof(short));
+        input_stream.read((char *)&nameID, sizeof(unsigned));
+        input_stream.read((char *)&is_roundabout, sizeof(bool));
+        input_stream.read((char *)&ignore_in_grid, sizeof(bool));
+        input_stream.read((char *)&is_access_restricted, sizeof(bool));
+        input_stream.read((char *)&is_contra_flow, sizeof(bool));
+        input_stream.read((char *)&is_split, sizeof(bool));
+
+        BOOST_ASSERT_MSG(length > 0, "loaded null length edge");
         BOOST_ASSERT_MSG(weight > 0, "loaded null weight");
-        BOOST_ASSERT_MSG(0<=dir && dir<=2, "loaded bogus direction");
+        BOOST_ASSERT_MSG(0 <= dir && dir <= 2, "loaded bogus direction");
 
         bool forward = true;
         bool backward = true;
-        if (1 == dir) { backward = false; }
-        if (2 == dir) { forward = false; }
+        if (1 == dir)
+        {
+            backward = false;
+        }
+        if (2 == dir)
+        {
+            forward = false;
+        }
 
-        assert(type >= 0);
+        BOOST_ASSERT(type >= 0);
 
-        //         translate the external NodeIDs to internal IDs
-        ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(source);
-        if( ext2IntNodeMap.find(source) == ext2IntNodeMap.end()) {
+        // translate the external NodeIDs to internal IDs
+        auto internal_id_iter = ext_to_int_id_map.find(source);
+        if (ext_to_int_id_map.find(source) == ext_to_int_id_map.end())
+        {
 #ifndef NDEBUG
-            WARN(" unresolved source NodeID: " << source );
+            SimpleLogger().Write(logWARNING) << " unresolved source NodeID: " << source;
 #endif
             continue;
         }
-        source = intNodeID->second;
-        intNodeID = ext2IntNodeMap.find(target);
-        if(ext2IntNodeMap.find(target) == ext2IntNodeMap.end()) {
+        source = internal_id_iter->second;
+        internal_id_iter = ext_to_int_id_map.find(target);
+        if (ext_to_int_id_map.find(target) == ext_to_int_id_map.end())
+        {
 #ifndef NDEBUG
-            WARN("unresolved target NodeID : " << target );
+            SimpleLogger().Write(logWARNING) << "unresolved target NodeID : " << target;
 #endif
             continue;
         }
-        target = intNodeID->second;
-        BOOST_ASSERT_MSG(source != UINT_MAX && target != UINT_MAX,
-            "nonexisting source or target"
-        );
+        target = internal_id_iter->second;
+        BOOST_ASSERT_MSG(source != UINT_MAX && target != UINT_MAX, "nonexisting source or target");
 
-        if(source > target) {
+        if (source > target)
+        {
             std::swap(source, target);
             std::swap(forward, backward);
         }
 
-        EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow );
-        edgeList.push_back(inputEdge);
+        edge_list.emplace_back(source,
+                               target,
+                               nameID,
+                               weight,
+                               forward,
+                               backward,
+                               type,
+                               is_roundabout,
+                               ignore_in_grid,
+                               is_access_restricted,
+                               is_contra_flow,
+                               is_split);
     }
-    std::sort(edgeList.begin(), edgeList.end());
-    for(unsigned i = 1; i < edgeList.size(); ++i) {
-        if( (edgeList[i-1].target() == edgeList[i].target()) && (edgeList[i-1].source() == edgeList[i].source()) ) {
-            bool edgeFlagsAreEquivalent = (edgeList[i-1].isForward() == edgeList[i].isForward()) && (edgeList[i-1].isBackward() == edgeList[i].isBackward());
-            bool edgeFlagsAreSuperSet1 = (edgeList[i-1].isForward() && edgeList[i-1].isBackward()) && (edgeList[i].isBackward() != edgeList[i].isBackward() );
-            bool edgeFlagsAreSuperSet2 = (edgeList[i].isForward() && edgeList[i].isBackward()) && (edgeList[i-1].isBackward() != edgeList[i-1].isBackward() );
-
-            if( edgeFlagsAreEquivalent ) {
-                edgeList[i]._weight = std::min(edgeList[i-1].weight(), edgeList[i].weight());
-                edgeList[i-1]._source = UINT_MAX;
-            } else if (edgeFlagsAreSuperSet1) {
-                if(edgeList[i-1].weight() <= edgeList[i].weight()) {
-                    //edge i-1 is smaller and goes in both directions. Throw away the other edge
-                    edgeList[i]._source = UINT_MAX;
-                } else {
-                    //edge i-1 is open in both directions, but edge i is smaller in one direction. Close edge i-1 in this direction
-                    edgeList[i-1].forward = !edgeList[i].isForward();
-                    edgeList[i-1].backward = !edgeList[i].isBackward();
+
+    tbb::parallel_sort(edge_list.begin(), edge_list.end());
+    for (unsigned i = 1; i < edge_list.size(); ++i)
+    {
+        if ((edge_list[i - 1].target == edge_list[i].target) &&
+            (edge_list[i - 1].source == edge_list[i].source))
+        {
+            const bool edge_flags_equivalent =
+                (edge_list[i - 1].forward == edge_list[i].forward) &&
+                (edge_list[i - 1].backward == edge_list[i].backward);
+            const bool edge_flags_are_superset1 =
+                (edge_list[i - 1].forward && edge_list[i - 1].backward) &&
+                (edge_list[i].backward != edge_list[i].backward);
+            const bool edge_flags_are_superset_2 =
+                (edge_list[i].forward && edge_list[i].backward) &&
+                (edge_list[i - 1].backward != edge_list[i - 1].backward);
+
+            if (edge_flags_equivalent)
+            {
+                edge_list[i].weight = std::min(edge_list[i - 1].weight, edge_list[i].weight);
+                edge_list[i - 1].source = UINT_MAX;
+            }
+            else if (edge_flags_are_superset1)
+            {
+                if (edge_list[i - 1].weight <= edge_list[i].weight)
+                {
+                    // edge i-1 is smaller and goes in both directions. Throw away the other edge
+                    edge_list[i].source = UINT_MAX;
+                }
+                else
+                {
+                    // edge i-1 is open in both directions, but edge i is smaller in one direction.
+                    // Close edge i-1 in this direction
+                    edge_list[i - 1].forward = !edge_list[i].forward;
+                    edge_list[i - 1].backward = !edge_list[i].backward;
+                }
+            }
+            else if (edge_flags_are_superset_2)
+            {
+                if (edge_list[i - 1].weight <= edge_list[i].weight)
+                {
+                    // edge i-1 is smaller for one direction. edge i is open in both. close edge i
+                    // in the other direction
+                    edge_list[i].forward = !edge_list[i - 1].forward;
+                    edge_list[i].backward = !edge_list[i - 1].backward;
+                }
+                else
+                {
+                    // edge i is smaller and goes in both direction. Throw away edge i-1
+                    edge_list[i - 1].source = UINT_MAX;
                 }
-            } else if (edgeFlagsAreSuperSet2) {
-                if(edgeList[i-1].weight() <= edgeList[i].weight()) {
-                     //edge i-1 is smaller for one direction. edge i is open in both. close edge i in the other direction
-                     edgeList[i].forward = !edgeList[i-1].isForward();
-                     edgeList[i].backward = !edgeList[i-1].isBackward();
-                 } else {
-                     //edge i is smaller and goes in both direction. Throw away edge i-1
-                     edgeList[i-1]._source = UINT_MAX;
-                 }
             }
         }
     }
-    typename std::vector<EdgeT>::iterator newEnd = std::remove_if(edgeList.begin(), edgeList.end(), _ExcessRemover<EdgeT>());
-    ext2IntNodeMap.clear();
-    std::vector<EdgeT>(edgeList.begin(), newEnd).swap(edgeList); //remove excess candidates.
-    INFO("Graph loaded ok and has " << edgeList.size() << " edges");
+    const auto new_end_iter = std::remove_if(edge_list.begin(),
+                                       edge_list.end(),
+                                       [](const EdgeT &edge)
+                                       { return edge.source == SPECIAL_NODEID; });
+    ext_to_int_id_map.clear();
+    edge_list.erase(new_end_iter, edge_list.end()); // remove excess candidates.
+    edge_list.shrink_to_fit();
+    SimpleLogger().Write() << "Graph loaded ok and has " << edge_list.size() << " edges";
     return n;
 }
-template<typename EdgeT>
-NodeID readDTMPGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, std::vector<NodeInfo> * int2ExtNodeMap) {
-    NodeID n, source, target, id;
-    EdgeID m;
-    int dir, xcoord, ycoord;// direction (0 = open, 1 = forward, 2+ = open)
-    ExternalNodeMap ext2IntNodeMap;
-    in >> n;
-    DEBUG("Importing n = " << n << " nodes ");
-    for (NodeID i=0; i<n;++i) {
-        in >> id >> ycoord >> xcoord;
-        int2ExtNodeMap->push_back(NodeInfo(xcoord, ycoord, id));
-        ext2IntNodeMap.insert(std::make_pair(id, i));
-    }
-    in >> m;
-    DEBUG(" and " << m << " edges");
-
-    edgeList.reserve(m);
-    for (EdgeID i=0; i<m; ++i) {
-        EdgeWeight weight;
-        unsigned speedType(0);
-        short type(0);
-        // NodeID nameID;
-        int length;
-        in >> source >> target >> length >> dir >> speedType;
-
-        if(dir == 3)
-            dir = 0;
-
-        switch(speedType) {
-        case 1:
-            weight = 130;
-            break;
-        case 2:
-            weight = 120;
-            break;
-        case 3:
-            weight = 110;
-            break;
-        case 4:
-            weight = 100;
-            break;
-        case 5:
-            weight = 90;
-            break;
-        case 6:
-            weight = 80;
-            break;
-        case 7:
-            weight = 70;
-            break;
-        case 8:
-            weight = 60;
-            break;
-        case 9:
-            weight = 50;
-            break;
-        case 10:
-            weight = 40;
-            break;
-        case 11:
-            weight = 30;
-            break;
-        case 12:
-            weight = 20;
-            break;
-        case 13:
-            weight = length;
-            break;
-        case 15:
-            weight = 10;
-            break;
-        default:
-            weight = 0;
-            break;
-        }
 
-        weight = length*weight/3.6;
-        if(speedType == 13)
-            weight = length;
-        assert(length > 0);
-        assert(weight > 0);
-        if(dir <0 || dir > 2)
-            WARN("direction bogus: " << dir);
-        assert(0<=dir && dir<=2);
-
-        bool forward = true;
-        bool backward = true;
-        if (dir == 1) backward = false;
-        if (dir == 2) forward = false;
-
-        if(length == 0) { ERR("loaded null length edge"); }
-
-        //         translate the external NodeIDs to internal IDs
-        ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(source);
-        if( ext2IntNodeMap.find(source) == ext2IntNodeMap.end()) {
-            ERR("after " << edgeList.size() << " edges" << "\n->" << source << "," << target << "," << length << "," << dir << "," << weight << "\n->unresolved source NodeID: " << source);
-        }
-        source = intNodeID->second;
-        intNodeID = ext2IntNodeMap.find(target);
-        if(ext2IntNodeMap.find(target) == ext2IntNodeMap.end()) { ERR("unresolved target NodeID : " << target); }
-        target = intNodeID->second;
+template <typename NodeT, typename EdgeT>
+unsigned readHSGRFromStream(const boost::filesystem::path &hsgr_file,
+                            std::vector<NodeT> &node_list,
+                            std::vector<EdgeT> &edge_list,
+                            unsigned *check_sum)
+{
+    if (!boost::filesystem::exists(hsgr_file))
+    {
+        throw OSRMException("hsgr file does not exist");
+    }
+    if (0 == boost::filesystem::file_size(hsgr_file))
+    {
+        throw OSRMException("hsgr file is empty");
+    }
 
-        if(source == UINT_MAX || target == UINT_MAX) { ERR("nonexisting source or target" ); }
+    boost::filesystem::ifstream hsgr_input_stream(hsgr_file, std::ios::binary);
 
-        EdgeT inputEdge(source, target, 0, weight, forward, backward, type );
-        edgeList.push_back(inputEdge);
+    FingerPrint fingerprint_loaded, fingerprint_orig;
+    hsgr_input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
+    if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig))
+    {
+        SimpleLogger().Write(logWARNING) << ".hsgr was prepared with different build.\n"
+                                            "Reprocess to get rid of this warning.";
     }
-    ext2IntNodeMap.clear();
-    std::vector<EdgeT>(edgeList.begin(), edgeList.end()).swap(edgeList); //remove excess candidates.
-    std::cout << "ok" << std::endl;
-    return n;
-}
-
-template<typename EdgeT>
-NodeID readDDSGGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, std::vector<NodeID> & int2ExtNodeMap) {
-    ExternalNodeMap nodeMap;
-    NodeID n, source, target;
-    unsigned numberOfNodes = 0;
-    char d;
-    EdgeID m;
-    int dir;// direction (0 = open, 1 = forward, 2+ = open)
-    in >> d;
-    in >> n;
-    in >> m;
-#ifndef DEBUG
-    std::cout << "expecting " << n << " nodes and " << m << " edges ..." << flush;
-#endif
-    edgeList.reserve(m);
-    for (EdgeID i=0; i<m; i++) {
-        EdgeWeight weight;
-        in >> source >> target >> weight >> dir;
 
-        assert(weight > 0);
-        if(dir <0 || dir > 3)
-            ERR( "[error] direction bogus: " << dir );
-        assert(0<=dir && dir<=3);
+    unsigned number_of_nodes = 0;
+    unsigned number_of_edges = 0;
+    hsgr_input_stream.read((char *)check_sum, sizeof(unsigned));
+    hsgr_input_stream.read((char *)&number_of_nodes, sizeof(unsigned));
+    BOOST_ASSERT_MSG(0 != number_of_nodes, "number of nodes is zero");
+    hsgr_input_stream.read((char *)&number_of_edges, sizeof(unsigned));
 
-        bool forward = true;
-        bool backward = true;
-        if (dir == 1) backward = false;
-        if (dir == 2) forward = false;
-        if (dir == 3) {backward = true; forward = true;}
+    SimpleLogger().Write() << "number_of_nodes: " << number_of_nodes
+                           << ", number_of_edges: " << number_of_edges;
 
-        if(weight == 0) { ERR("loaded null length edge"); }
+    // BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero");
+    node_list.resize(number_of_nodes + 1);
+    hsgr_input_stream.read((char *)&(node_list[0]), number_of_nodes * sizeof(NodeT));
 
-        if( nodeMap.find(source) == nodeMap.end()) {
-            nodeMap.insert(std::make_pair(source, numberOfNodes ));
-            int2ExtNodeMap.push_back(source);
-            numberOfNodes++;
-        }
-        if( nodeMap.find(target) == nodeMap.end()) {
-            nodeMap.insert(std::make_pair(target, numberOfNodes));
-            int2ExtNodeMap.push_back(target);
-            numberOfNodes++;
-        }
-        EdgeT inputEdge(source, target, 0, weight, forward, backward, 1 );
-        edgeList.push_back(inputEdge);
+    edge_list.resize(number_of_edges);
+    if (number_of_edges > 0)
+    {
+        hsgr_input_stream.read((char *)&(edge_list[0]), number_of_edges * sizeof(EdgeT));
     }
-    std::vector<EdgeT>(edgeList.begin(), edgeList.end()).swap(edgeList); //remove excess candidates.
-
-    nodeMap.clear();
-    return numberOfNodes;
-}
-
-template<typename NodeT, typename EdgeT>
-unsigned readHSGRFromStream(std::istream &in, std::vector<NodeT>& nodeList, std::vector<EdgeT> & edgeList, unsigned * checkSum) {
-    unsigned numberOfNodes = 0;
-    in.read((char*) checkSum, sizeof(unsigned));
-    in.read((char*) & numberOfNodes, sizeof(unsigned));
-    nodeList.resize(numberOfNodes + 1);
-    in.read((char*) &(nodeList[0]), numberOfNodes*sizeof(NodeT));
-
-    unsigned numberOfEdges = 0;
-    in.read((char*) &numberOfEdges, sizeof(unsigned));
-    edgeList.resize(numberOfEdges);
-    in.read((char*) &(edgeList[0]), numberOfEdges*sizeof(EdgeT));
+    hsgr_input_stream.close();
 
-    return numberOfNodes;
+    return number_of_nodes;
 }
 
 #endif // GRAPHLOADER_H
diff --git a/Util/IniFileUtil.h b/Util/IniFileUtil.h
new file mode 100644
index 0000000..ea1d7a1
--- /dev/null
+++ b/Util/IniFileUtil.h
@@ -0,0 +1,49 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef INI_FILE_UTIL_H
+#define INI_FILE_UTIL_H
+
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <boost/regex.hpp>
+
+#include <regex>
+#include <string>
+
+// support old capitalized option names by down-casing them with a regex replace
+inline std::string ReadIniFileAndLowerContents(const boost::filesystem::path &path)
+{
+    boost::filesystem::fstream config_stream(path);
+    std::string ini_file_content((std::istreambuf_iterator<char>(config_stream)),
+                          std::istreambuf_iterator<char>());
+    boost::regex regex( "^([^=]*)" ); //match from start of line to '='
+    std::string format( "\\L$1\\E" ); //replace with downcased substring
+    return boost::regex_replace( ini_file_content, regex, format );
+}
+
+#endif // INI_FILE_UTIL_H
diff --git a/Util/InputFileUtil.h b/Util/InputFileUtil.h
deleted file mode 100644
index 685d92f..0000000
--- a/Util/InputFileUtil.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#ifndef INPUTFILEUTIL_H_
-#define INPUTFILEUTIL_H_
-
-#include <boost/filesystem.hpp>
-
-#include "../typedefs.h"
-
-// Check if file exists and if it can be opened for reading with ifstream an object
-inline bool testDataFile(const std::string & filename){
-    boost::filesystem::path fileToTest(filename);
-	if(!boost::filesystem::exists(fileToTest))       {
-		WARN("Failed to open file " << filename << " for reading.");
-		return false;
-	}
-	return true;
-}
-
-inline bool testDataFiles(int argc, char *argv[]){
-	for(int i = 0; i < argc; ++i) {
-		if(!testDataFile(argv[i]))
-			return false;
-	}
-	return true;
-}
-
-#endif /* INPUTFILEUTIL_H_ */
diff --git a/Util/LinuxStackTrace.h b/Util/LinuxStackTrace.h
deleted file mode 100644
index a3a23a7..0000000
--- a/Util/LinuxStackTrace.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-
-
-#ifndef LINUXSTACKTRACE_H_
-#define LINUXSTACKTRACE_H_
-
-#include <string>
-
-
-#ifdef __linux__
-#include <cxxabi.h>
-#include <execinfo.h>
-#include <csignal>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-
-#include <sstream>
-
-std::string binaryName;
-
-std::string getFileAndLine (char * offset_end) {
-    std::string a(offset_end);
-    std::string result;
-    a = a.substr(2,a.length()-3);
-    static char buf[256];
-    std::string command("/usr/bin/addr2line -C -e " + binaryName + " -f -i " + a);
-    // prepare command to be executed
-    // our program need to be passed after the -e parameter
-    FILE* f = popen (command.c_str(), "r");
-
-    if (f == NULL) {
-        perror (buf);
-        return "";
-    }
-    // get function name
-    if ( NULL != fgets (buf, 256, f) ) {
-
-        // get file and line
-        if ( NULL != fgets (buf, 256, f) ) {
-
-            if (buf[0] != '?') {
-                result = ( buf);
-            } else {
-                result = "unkown";
-            }
-        } else { result = ""; }
-    } else { result = ""; }
-    pclose(f);
-    return result;
-}
-
-
-void crashHandler(int sig_num, siginfo_t * info, void * ) {
-    const size_t maxDepth = 100;
-    //size_t stackDepth;
-
-    void *stackAddrs[maxDepth];
-    backtrace(stackAddrs, maxDepth);
-
-    std::cerr << "signal " << sig_num << " (" << strsignal(sig_num) << "), address is " << info->si_addr << " from " << stackAddrs[0] << std::endl;
-
-    void * array[50];
-    int size = backtrace(array, 50);
-
-    array[1] = stackAddrs[0];
-
-    char ** messages = backtrace_symbols(array, size);
-
-    // skip first stack frame (points here)
-    for (int i = 1; i < size-1 && messages != NULL; ++i) {
-        char *mangledname = 0, *offset_begin = 0, *offset_end = 0;
-
-        // find parantheses and +address offset surrounding mangled name
-        for (char *p = messages[i+1]; *p; ++p) {
-            if (*p == '(') {
-                mangledname = p;
-            } else if (*p == '+') {
-                offset_begin = p;
-            } else if (*p == ')') {
-                offset_end = p;
-                break;
-            }
-        }
-
-        // if the line could be processed, attempt to demangle the symbol
-        if (mangledname && offset_begin && offset_end && mangledname < offset_begin) {
-            *mangledname++ = '\0';
-            *offset_begin++ = '\0';
-            *offset_end++ = '\0';
-
-            int status;
-            char * real_name = abi::__cxa_demangle(mangledname, 0, 0, &status);
-
-            // if demangling is successful, output the demangled function name
-            if (status == 0) {
-                std::cerr << "[bt]: (" << i << ") " << messages[i+1] << " : " << real_name << " " << getFileAndLine(offset_end);
-            }
-            // otherwise, output the mangled function name
-            else {
-                std::cerr << "[bt]: (" << i << ") " << messages[i+1] << " : "
-                        << mangledname << "+" << offset_begin << offset_end
-                        << std::endl;
-            }
-            free(real_name);
-        }
-        // otherwise, print the whole line
-        else {
-            std::cerr << "[bt]: (" << i << ") " << messages[i+1] << std::endl;
-        }
-    }
-    std::cerr << std::endl;
-
-    free(messages);
-
-    exit(EXIT_FAILURE);
-}
-
-void installCrashHandler(std::string b) {
-    binaryName = b;
-#ifndef NDEBUG
-    struct sigaction sigact;
-    sigemptyset(&sigact.sa_mask);
-    sigact.sa_sigaction = crashHandler;
-    sigact.sa_flags = SA_RESTART | SA_SIGINFO;
-
-    if (sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL) != 0) {
-        std::cerr <<  "error setting signal handler for " << SIGSEGV << " " << strsignal(SIGSEGV) << std::endl;
-
-        exit(EXIT_FAILURE);
-    }
-#endif
-}
-#else
-inline void installCrashHandler(std::string ) {}
-#endif
-#endif /* LINUXSTACKTRACE_H_ */
diff --git a/Util/LuaUtil.h b/Util/LuaUtil.h
index 3793d8b..5c502c9 100644
--- a/Util/LuaUtil.h
+++ b/Util/LuaUtil.h
@@ -1,57 +1,66 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef LUAUTIL_H_
-#define LUAUTIL_H_
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef LUA_UTIL_H
+#define LUA_UTIL_H
 
 extern "C" {
-    #include <lua.h>
-    #include <lauxlib.h>
-    #include <lualib.h>
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
 }
 
 #include <boost/filesystem/convenience.hpp>
 #include <luabind/luabind.hpp>
+
 #include <iostream>
 #include <string>
 
-template<typename T>
-void LUA_print(T number) {
-  std::cout << "[LUA] " << number << std::endl;
-}
+template <typename T> void LUA_print(T output) { std::cout << "[LUA] " << output << std::endl; }
 
 // Check if the lua function <name> is defined
-inline bool lua_function_exists(lua_State* lua_state, const char* name) {
-    luabind::object g = luabind::globals(lua_state);
-    luabind::object func = g[name];
-    return func && (luabind::type(func) == LUA_TFUNCTION);
+inline bool lua_function_exists(lua_State *lua_state, const char *name)
+{
+    luabind::object globals_table = luabind::globals(lua_state);
+    luabind::object lua_function = globals_table[name];
+    return lua_function && (luabind::type(lua_function) == LUA_TFUNCTION);
 }
 
-// Add the folder contain the script to the lua load path, so script can easily require() other lua scripts inside that folder, or subfolders.
+// Add the folder contain the script to the lua load path, so script can easily require() other lua
+// scripts inside that folder, or subfolders.
 // See http://lua-users.org/wiki/PackagePath for details on the package.path syntax.
-inline void luaAddScriptFolderToLoadPath(lua_State* myLuaState, const char* fileName) {
-    const boost::filesystem::path profilePath( fileName );
-    std::string folder = profilePath.parent_path().string();
-    //TODO: This code is most probably not Windows safe since it uses UNIX'ish path delimiters
-    const std::string luaCode = "package.path = \"" + folder + "/?.lua;profiles/?.lua;\" .. package.path";
-    luaL_dostring( myLuaState, luaCode.c_str() );
+inline void luaAddScriptFolderToLoadPath(lua_State *lua_state, const char *file_name)
+{
+    const boost::filesystem::path profile_path(file_name);
+    std::string folder = profile_path.parent_path().string();
+    // TODO: This code is most probably not Windows safe since it uses UNIX'ish path delimiters
+    const std::string lua_code =
+        "package.path = \"" + folder + "/?.lua;profiles/?.lua;\" .. package.path";
+    luaL_dostring(lua_state, lua_code.c_str());
 }
 
-#endif /* LUAUTIL_H_ */
+#endif // LUA_UTIL_H
diff --git a/Util/MachineInfo.h b/Util/MachineInfo.h
index 7c0f31c..c5cb052 100644
--- a/Util/MachineInfo.h
+++ b/Util/MachineInfo.h
@@ -1,86 +1,57 @@
 /*
- open source routing machine
- Copyright (C) Dennis Luxen, others 2010
- 
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU AFFERO General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- any later version.
- 
- 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.
- 
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- or see http://www.gnu.org/licenses/agpl.txt.
- */
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #ifndef MACHINE_INFO_H
 #define MACHINE_INFO_H
 
-#if defined(__APPLE__) || defined(__FreeBSD__)
-extern "C" {
-#include <sys/types.h>
-#include <sys/sysctl.h>
-}	
-#elif defined _WIN32
-#include <windows.h>
-#endif
+enum Endianness
+{ LittleEndian = 1,
+  BigEndian = 2 };
 
-enum Endianness {
-    LittleEndian = 1,
-    BigEndian = 2
-};
-
-//Function is optimized to a single 'mov eax,1' on GCC, clang and icc using -O3
-inline Endianness getMachineEndianness() {
+// Function is optimized to a single 'mov eax,1' on GCC, clang and icc using -O3
+inline Endianness GetMachineEndianness()
+{
     int i(1);
-    char *p = (char *) &i;
+    char *p = (char *)&i;
     if (1 == p[0])
+    {
         return LittleEndian;
+    }
     return BigEndian;
 }
 
 // Reverses Network Byte Order into something usable, compiles down to a bswap-mov combination
-inline unsigned swapEndian(unsigned x) {
-    if(getMachineEndianness() == LittleEndian)
-        return ( (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24) );
+inline unsigned SwapEndian(unsigned x)
+{
+    if (GetMachineEndianness() == LittleEndian)
+    {
+        return ((x >> 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x << 24));
+    }
     return x;
 }
 
-// Returns the physical memory size in kilobytes
-inline unsigned GetPhysicalmemory(void){
-#if defined(SUN5) || defined(__linux__)
-	return (sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE));
-	
-#elif defined(__APPLE__)
-	int mib[2] = {CTL_HW, HW_MEMSIZE};
-	long long memsize;
-	size_t len = sizeof(memsize);
-	sysctl(mib, 2, &memsize, &len, NULL, 0);
-	return memsize/1024;
-	
-#elif defined(__FreeBSD__)
-	int mib[2] = {CTL_HW, HW_PHYSMEM};
-	long long memsize;
-	size_t len = sizeof(memsize);
-	sysctl(mib, 2, &memsize, &len, NULL, 0);
-	return memsize/1024;
-	
-#elif defined(_WIN32)
-	MEMORYSTATUSEX status;
-	status.dwLength = sizeof(status);
-	GlobalMemoryStatusEx(&status);
-	return status.ullTotalPhys/1024;
-#else
-	std::cout << "[Warning] Compiling on unknown architecture." << std::endl 
-		<< "Please file a ticket at http://project-osrm.org" << std::endl;
-	return 2048*1024; /* 128 Mb default memory */
-
-#endif
-}
 #endif // MACHINE_INFO_H
-
diff --git a/Util/MercatorUtil.h b/Util/MercatorUtil.h
new file mode 100644
index 0000000..31d1139
--- /dev/null
+++ b/Util/MercatorUtil.h
@@ -0,0 +1,43 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef MERCATOR_UTIL_H
+#define MERCATOR_UTIL_H
+
+#include <cmath>
+
+inline float y2lat(const float a)
+{
+    return 180.f * static_cast<float>(M_1_PI) * (2.f * std::atan(std::exp(a * static_cast<float>(M_PI) / 180.f)) - static_cast<float>(M_PI_2));
+}
+
+inline float lat2y(const float a)
+{
+    return 180.f * static_cast<float>(M_1_PI) * std::log(std::tan(static_cast<float>(M_PI_4) + a * (static_cast<float>(M_PI) / 180.f) / 2.f));
+}
+
+#endif // MERCATOR_UTIL_H
diff --git a/Util/OSRMException.h b/Util/OSRMException.h
new file mode 100644
index 0000000..f4f4290
--- /dev/null
+++ b/Util/OSRMException.h
@@ -0,0 +1,46 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef OSRM_EXCEPTION_H
+#define OSRM_EXCEPTION_H
+
+#include <exception>
+#include <string>
+
+class OSRMException : public std::exception
+{
+  public:
+    explicit OSRMException(const char *message) : message(message) {}
+    explicit OSRMException(const std::string &message) : message(message) {}
+    virtual ~OSRMException() throw() {}
+
+  private:
+    virtual const char *what() const throw() { return message.c_str(); }
+    const std::string message;
+};
+
+#endif /* OSRM_EXCEPTION_H */
diff --git a/Util/OpenMPWrapper.h b/Util/OpenMPWrapper.h
deleted file mode 100644
index 232dcbd..0000000
--- a/Util/OpenMPWrapper.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
-
-*/
-
-#ifndef _OPENMPREPLACEMENTY_H
-#define _OPENMPREPLACEMENTY_H
-
-#ifdef _OPENMP
-#include <omp.h>  	
-#else
-inline const int omp_get_num_procs() { return 1; }
-inline const int omp_get_max_threads() { return 1; }
-inline const int omp_get_thread_num() { return 0; }
-inline const void omp_set_num_threads(int i) {}
-#endif
-
-#endif
diff --git a/Util/ProgramOptions.h b/Util/ProgramOptions.h
new file mode 100644
index 0000000..c6e5448
--- /dev/null
+++ b/Util/ProgramOptions.h
@@ -0,0 +1,270 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef PROGAM_OPTIONS_H
+#define PROGAM_OPTIONS_H
+
+#include "GitDescription.h"
+#include "IniFileUtil.h"
+#include "OSRMException.h"
+#include "SimpleLogger.h"
+
+#include <osrm/ServerPaths.h>
+
+#include <boost/any.hpp>
+#include <boost/program_options.hpp>
+
+#include <fstream>
+#include <string>
+
+const static unsigned INIT_OK_START_ENGINE = 0;
+const static unsigned INIT_OK_DO_NOT_START_ENGINE = 1;
+const static unsigned INIT_FAILED = -1;
+
+// generate boost::program_options object for the routing part
+inline unsigned GenerateServerProgramOptions(const int argc,
+                                             const char *argv[],
+                                             ServerPaths &paths,
+                                             std::string &ip_address,
+                                             int &ip_port,
+                                             int &requested_num_threads,
+                                             bool &use_shared_memory,
+                                             bool &trial)
+{
+
+    // declare a group of options that will be allowed only on command line
+    boost::program_options::options_description generic_options("Options");
+    generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")(
+        "config,c",
+        boost::program_options::value<boost::filesystem::path>(&paths["config"])
+            ->default_value("server.ini"),
+        "Path to a configuration file")(
+        "trial",
+        boost::program_options::value<bool>(&trial)->implicit_value(true),
+        "Quit after initialization");
+
+    // declare a group of options that will be allowed both on command line
+    // as well as in a config file
+    boost::program_options::options_description config_options("Configuration");
+    config_options.add_options()(
+        "hsgrdata",
+        boost::program_options::value<boost::filesystem::path>(&paths["hsgrdata"]),
+        ".hsgr file")("nodesdata",
+                      boost::program_options::value<boost::filesystem::path>(&paths["nodesdata"]),
+                      ".nodes file")(
+        "edgesdata",
+        boost::program_options::value<boost::filesystem::path>(&paths["edgesdata"]),
+        ".edges file")("geometry",
+                       boost::program_options::value<boost::filesystem::path>(&paths["geometries"]),
+                       ".geometry file")(
+        "ramindex",
+        boost::program_options::value<boost::filesystem::path>(&paths["ramindex"]),
+        ".ramIndex file")(
+        "fileindex",
+        boost::program_options::value<boost::filesystem::path>(&paths["fileindex"]),
+        "File index file")(
+        "namesdata",
+        boost::program_options::value<boost::filesystem::path>(&paths["namesdata"]),
+        ".names file")("timestamp",
+                       boost::program_options::value<boost::filesystem::path>(&paths["timestamp"]),
+                       ".timestamp file")(
+        "ip,i",
+        boost::program_options::value<std::string>(&ip_address)->default_value("0.0.0.0"),
+        "IP address")(
+        "port,p", boost::program_options::value<int>(&ip_port)->default_value(5000), "TCP/IP port")(
+        "threads,t",
+        boost::program_options::value<int>(&requested_num_threads)->default_value(8),
+        "Number of threads to use")(
+        "sharedmemory,s",
+        boost::program_options::value<bool>(&use_shared_memory)->implicit_value(true),
+        "Load data from shared memory");
+
+    // hidden options, will be allowed both on command line and in config
+    // file, but will not be shown to the user
+    boost::program_options::options_description hidden_options("Hidden options");
+    hidden_options.add_options()(
+        "base,b",
+        boost::program_options::value<boost::filesystem::path>(&paths["base"]),
+        "base path to .osrm file");
+
+    // positional option
+    boost::program_options::positional_options_description positional_options;
+    positional_options.add("base", 1);
+
+    // combine above options for parsing
+    boost::program_options::options_description cmdline_options;
+    cmdline_options.add(generic_options).add(config_options).add(hidden_options);
+
+    boost::program_options::options_description config_file_options;
+    config_file_options.add(config_options).add(hidden_options);
+
+    boost::program_options::options_description visible_options(
+        boost::filesystem::basename(argv[0]) + " <base.osrm> [<options>]");
+    visible_options.add(generic_options).add(config_options);
+
+    // parse command line options
+    boost::program_options::variables_map option_variables;
+    boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
+                                      .options(cmdline_options)
+                                      .positional(positional_options)
+                                      .run(),
+                                  option_variables);
+
+    if (option_variables.count("version"))
+    {
+        SimpleLogger().Write() << g_GIT_DESCRIPTION;
+        return INIT_OK_DO_NOT_START_ENGINE;
+    }
+
+    if (option_variables.count("help"))
+    {
+        SimpleLogger().Write() << visible_options;
+        return INIT_OK_DO_NOT_START_ENGINE;
+    }
+
+    boost::program_options::notify(option_variables);
+
+    // parse config file
+    ServerPaths::iterator path_iterator = paths.find("config");
+    if (path_iterator != paths.end() && boost::filesystem::is_regular_file(path_iterator->second) &&
+        !option_variables.count("base"))
+    {
+        SimpleLogger().Write() << "Reading options from: " << path_iterator->second.string();
+        std::string ini_file_contents = ReadIniFileAndLowerContents(path_iterator->second);
+        std::stringstream config_stream(ini_file_contents);
+        boost::program_options::store(parse_config_file(config_stream, config_file_options),
+                                      option_variables);
+        boost::program_options::notify(option_variables);
+        return INIT_OK_START_ENGINE;
+    }
+
+    if (1 > requested_num_threads)
+    {
+        throw OSRMException("Number of threads must be a positive number");
+    }
+
+    if (!use_shared_memory && option_variables.count("base"))
+    {
+        path_iterator = paths.find("base");
+        BOOST_ASSERT(paths.end() != path_iterator);
+        std::string base_string = path_iterator->second.string();
+
+        path_iterator = paths.find("hsgrdata");
+        if (path_iterator != paths.end() &&
+            !boost::filesystem::is_regular_file(path_iterator->second))
+        {
+            path_iterator->second = base_string + ".hsgr";
+        }
+        else
+        {
+            throw OSRMException(base_string + ".hsgr not found");
+        }
+
+        path_iterator = paths.find("nodesdata");
+        if (path_iterator != paths.end() &&
+            !boost::filesystem::is_regular_file(path_iterator->second))
+        {
+            path_iterator->second = base_string + ".nodes";
+        }
+        else
+        {
+            throw OSRMException(base_string + ".nodes not found");
+        }
+
+        path_iterator = paths.find("edgesdata");
+        if (path_iterator != paths.end() &&
+            !boost::filesystem::is_regular_file(path_iterator->second))
+        {
+            path_iterator->second = base_string + ".edges";
+        }
+        else
+        {
+            throw OSRMException(base_string + ".edges not found");
+        }
+
+        path_iterator = paths.find("geometries");
+        if (path_iterator != paths.end() &&
+            !boost::filesystem::is_regular_file(path_iterator->second))
+        {
+            path_iterator->second = base_string + ".geometry";
+        }
+        else
+        {
+            throw OSRMException(base_string + ".geometry not found");
+        }
+
+        path_iterator = paths.find("ramindex");
+        if (path_iterator != paths.end() &&
+            !boost::filesystem::is_regular_file(path_iterator->second))
+        {
+            path_iterator->second = base_string + ".ramIndex";
+        }
+        else
+        {
+            throw OSRMException(base_string + ".ramIndex not found");
+        }
+
+        path_iterator = paths.find("fileindex");
+        if (path_iterator != paths.end() &&
+            !boost::filesystem::is_regular_file(path_iterator->second))
+        {
+            path_iterator->second = base_string + ".fileIndex";
+        }
+        else
+        {
+            throw OSRMException(base_string + ".fileIndex not found");
+        }
+
+        path_iterator = paths.find("namesdata");
+        if (path_iterator != paths.end() &&
+            !boost::filesystem::is_regular_file(path_iterator->second))
+        {
+            path_iterator->second = base_string + ".names";
+        }
+        else
+        {
+            throw OSRMException(base_string + ".namesIndex not found");
+        }
+
+        path_iterator = paths.find("timestamp");
+        if (path_iterator != paths.end() &&
+            !boost::filesystem::is_regular_file(path_iterator->second))
+        {
+            path_iterator->second = base_string + ".timestamp";
+        }
+
+        return INIT_OK_START_ENGINE;
+    }
+    if (use_shared_memory && !option_variables.count("base"))
+    {
+        return INIT_OK_START_ENGINE;
+    }
+    SimpleLogger().Write() << visible_options;
+    return INIT_OK_DO_NOT_START_ENGINE;
+}
+
+#endif /* PROGRAM_OPTIONS_H */
diff --git a/Util/SimpleLogger.h b/Util/SimpleLogger.h
new file mode 100644
index 0000000..a234c96
--- /dev/null
+++ b/Util/SimpleLogger.h
@@ -0,0 +1,158 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef SIMPLE_LOGGER_H
+#define SIMPLE_LOGGER_H
+
+#include <boost/assert.hpp>
+
+#include <cstdio>
+
+#ifdef _MSC_VER
+#include <io.h>
+#define isatty _isatty
+#define fileno _fileno
+#else
+#include <unistd.h>
+#endif
+
+#include <ostream>
+#include <iostream>
+#include <mutex>
+#include <sstream>
+
+enum LogLevel
+{ logINFO,
+  logWARNING,
+  logDEBUG };
+
+const char COL_RESET[] = "\x1b[0m";
+const char RED[] = "\x1b[31m";
+const char GREEN[] = "\x1b[32m";
+const char YELLOW[] = "\x1b[33m";
+const char BLUE[] = "\x1b[34m";
+const char MAGENTA[] = "\x1b[35m";
+const char CYAN[] = "\x1b[36m";
+
+class LogPolicy
+{
+  public:
+    void Unmute() { m_is_mute = false; }
+
+    void Mute() { m_is_mute = true; }
+
+    bool IsMute() const { return m_is_mute; }
+
+    static LogPolicy &GetInstance()
+    {
+        static LogPolicy runningInstance;
+        return runningInstance;
+    }
+
+    LogPolicy(const LogPolicy &) = delete;
+
+  private:
+    LogPolicy() : m_is_mute(true) {}
+    bool m_is_mute;
+};
+
+class SimpleLogger
+{
+  public:
+    SimpleLogger() : level(logINFO) {}
+
+    std::mutex& get_mutex()
+    {
+        static std::mutex m;
+        return m;
+    }
+
+
+    std::ostringstream &Write(LogLevel l = logINFO)
+    {
+        std::lock_guard<std::mutex> lock(get_mutex());
+        try
+        {
+            level = l;
+            os << "[";
+            switch (level)
+            {
+            case logINFO:
+                os << "info";
+                break;
+            case logWARNING:
+                os << "warn";
+                break;
+            case logDEBUG:
+#ifndef NDEBUG
+                os << "debug";
+#endif
+                break;
+            default:
+                BOOST_ASSERT_MSG(false, "should not happen");
+                break;
+            }
+            os << "] ";
+        }
+        catch (...) {}
+        return os;
+    }
+
+    virtual ~SimpleLogger()
+    {
+        std::lock_guard<std::mutex> lock(get_mutex());
+        if (!LogPolicy::GetInstance().IsMute())
+        {
+            const bool is_terminal = ( 0 != isatty(fileno(stdout)) ? true : false);
+            switch (level)
+            {
+            case logINFO:
+                std::cout << os.str() << (is_terminal ? COL_RESET : "") << std::endl;
+                break;
+            case logWARNING:
+                std::cerr << (is_terminal ? RED : "") << os.str() << (is_terminal ? COL_RESET : "")
+                          << std::endl;
+                break;
+            case logDEBUG:
+#ifndef NDEBUG
+                std::cout << (is_terminal ? YELLOW : "") << os.str()
+                          << (is_terminal ? COL_RESET : "") << std::endl;
+#endif
+                break;
+            default:
+                BOOST_ASSERT_MSG(false, "should not happen");
+                break;
+            }
+        }
+    }
+
+  private:
+    LogLevel level;
+    std::ostringstream os;
+};
+
+#endif /* SIMPLE_LOGGER_H */
diff --git a/Util/StdHashExtensions.h b/Util/StdHashExtensions.h
new file mode 100644
index 0000000..50cd337
--- /dev/null
+++ b/Util/StdHashExtensions.h
@@ -0,0 +1,73 @@
+/*
+
+Copyright (c) 2014, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef STD_HASH_EXTENSIONS_H
+#define STD_HASH_EXTENSIONS_H
+
+#include <functional>
+
+// this is largely inspired by boost's hash combine as can be found in
+// "The C++ Standard Library" 2nd Edition. Nicolai M. Josuttis. 2012.
+template<typename T>
+inline void hash_combine(std::size_t &seed, const T& val)
+{
+    seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+}
+
+template<typename T>
+inline void hash_val(std::size_t &seed, const T& val)
+{
+    hash_combine(seed, val);
+}
+
+template<typename T, typename ... Types>
+inline void hash_val(std::size_t &seed, const T& val, const Types& ... args)
+{
+    hash_combine(seed, val);
+    hash_val(seed, args ...);
+}
+
+template<typename ... Types>
+inline std::size_t hash_val( const Types&... args)
+{
+    std::size_t seed = 0;
+    hash_val(seed, args...);
+    return seed;
+}
+
+namespace std
+{
+template <typename T1, typename T2> struct hash<std::pair<T1, T2>>
+{
+    size_t operator()(const std::pair<T1, T2> &pair) const
+    {
+        return hash_val(pair.first, pair.second);
+    }
+};
+}
+
+#endif // STD_HASH_EXTENSIONS_H
diff --git a/Util/StringUtil.h b/Util/StringUtil.h
index b09ac16..68a9ac9 100644
--- a/Util/StringUtil.h
+++ b/Util/StringUtil.h
@@ -1,163 +1,318 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef STRINGUTIL_H_
-#define STRINGUTIL_H_
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <string>
-#include <boost/algorithm/string.hpp>
+*/
+
+#ifndef STRINGUTIL_H
+#define STRINGUTIL_H
 
+#include <boost/algorithm/string.hpp>
 #include <boost/spirit/include/karma.hpp>
 #include <boost/spirit/include/qi.hpp>
 
 #include <cstdio>
-
-#include "../DataStructures/Coordinate.h"
-#include "../typedefs.h"
+#include <cctype>
+#include <string>
+#include <type_traits>
+#include <vector>
 
 // precision:  position after decimal point
 // length: maximum number of digits including comma and decimals
-template< int length, int precision >
-static inline char* printInt( char* buffer, int value ) {
-    bool minus = false;
-    if ( value < 0 ) {
-        minus = true;
+// work with negative values to prevent overflowing when taking -value
+template <int length, int precision> static inline char *printInt(char *buffer, int value)
+{
+    bool minus = true;
+    if (value > 0)
+    {
+        minus = false;
         value = -value;
     }
     buffer += length - 1;
-    for ( int i = 0; i < precision; i++ ) {
-        *buffer = '0' + ( value % 10 );
+    for (int i = 0; i < precision; i++)
+    {
+        *buffer = '0' - (value % 10);
         value /= 10;
         buffer--;
     }
     *buffer = '.';
     buffer--;
-    for ( int i = precision + 1; i < length; i++ ) {
-        *buffer = '0' + ( value % 10 );
+    for (int i = precision + 1; i < length; i++)
+    {
+        *buffer = '0' - (value % 10);
         value /= 10;
-        if ( value == 0 ) break;
+        if (value == 0)
+            break;
         buffer--;
     }
-    if ( minus ) {
+    if (minus)
+    {
         buffer--;
         *buffer = '-';
     }
     return buffer;
 }
 
-static inline void intToString(const int value, std::string & output) {
-    // The largest 32-bit integer is 4294967295, that is 10 chars
-    // On the safe side, add 1 for sign, and 1 for trailing zero
-    output.clear();
+// convert scoped enums to integers
+template <typename Enumeration>
+auto as_integer(Enumeration const value)
+    -> typename std::underlying_type<Enumeration>::type
+{
+    return static_cast<typename std::underlying_type<Enumeration>::type>(value);
+}
+
+static inline std::string IntToString(const int value)
+{
+    std::string output;
     std::back_insert_iterator<std::string> sink(output);
     boost::spirit::karma::generate(sink, boost::spirit::karma::int_, value);
+    return output;
 }
 
-static inline int stringToInt(const std::string& input) {
-    std::string::const_iterator realBeginOfNumber = input.begin();
-    //Delete any trailing white-spaces
-    while(realBeginOfNumber != input.end() && std::isspace(*realBeginOfNumber))
-        ++realBeginOfNumber;
-    int value = 0; // 2
-    boost::spirit::qi::parse(realBeginOfNumber, input.end(), boost::spirit::int_, value); // 3
-    return value;
+static inline std::string UintToString(const unsigned value)
+{
+    std::string output;
+    std::back_insert_iterator<std::string> sink(output);
+    boost::spirit::karma::generate(sink, boost::spirit::karma::uint_, value);
+    return output;
 }
 
-static inline void doubleToString(const double value, std::string & output){
+static inline void int64ToString(const int64_t value, std::string &output)
+{
     output.clear();
     std::back_insert_iterator<std::string> sink(output);
-    boost::spirit::karma::generate(sink, boost::spirit::karma::double_, value);
+    boost::spirit::karma::generate(sink, boost::spirit::karma::long_long, value);
 }
 
-static inline void doubleToStringWithTwoDigitsBehindComma(const double value, std::string & output){
-    // The largest 32-bit integer is 4294967295, that is 10 chars
-    // On the safe side, add 1 for sign, and 1 for trailing zero
-    char buffer[12] ;
-    sprintf(buffer, "%g", value) ;
-    output = buffer ;
+static inline int StringToInt(const std::string &input)
+{
+    auto first_digit = input.begin();
+    // Delete any trailing white-spaces
+    while (first_digit != input.end() && std::isspace(*first_digit))
+    {
+        ++first_digit;
+    }
+    int value = 0;
+    boost::spirit::qi::parse(first_digit, input.end(), boost::spirit::int_, value);
+    return value;
 }
 
-static inline void convertInternalLatLonToString(const int value, std::string & output) {
-    char buffer[100];
-    buffer[10] = 0; // Nullterminierung
-    char* string = printInt< 10, 5 >( buffer, value );
-    output = string;
+static inline unsigned StringToUint(const std::string &input)
+{
+    auto first_digit = input.begin();
+    // Delete any trailing white-spaces
+    while (first_digit != input.end() && std::isspace(*first_digit))
+    {
+        ++first_digit;
+    }
+    unsigned value = 0;
+    boost::spirit::qi::parse(first_digit, input.end(), boost::spirit::uint_, value);
+    return value;
 }
 
-static inline void convertInternalCoordinateToString(const _Coordinate & coord, std::string & output) {
-    std::string tmp;
-    convertInternalLatLonToString(coord.lon, tmp);
-    output = tmp;
-    output += ",";
-    convertInternalLatLonToString(coord.lat, tmp);
-    output += tmp;
-    output += " ";
+static inline uint64_t StringToInt64(const std::string &input)
+{
+    auto first_digit = input.begin();
+    // Delete any trailing white-spaces
+    while (first_digit != input.end() && std::isspace(*first_digit))
+    {
+        ++first_digit;
+    }
+    uint64_t value = 0;
+    boost::spirit::qi::parse(first_digit, input.end(), boost::spirit::long_long, value);
+    return value;
 }
-static inline void convertInternalReversedCoordinateToString(const _Coordinate & coord, std::string & output) {
-    std::string tmp;
-    convertInternalLatLonToString(coord.lat, tmp);
-    output = tmp;
-    output += ",";
-    convertInternalLatLonToString(coord.lon, tmp);
-    output += tmp;
-    output += " ";
+
+// source: http://tinodidriksen.com/2011/05/28/cpp-convert-string-to-double-speed/
+static inline double StringToDouble(const char *p)
+{
+    double r = 0.0;
+    bool neg = false;
+    if (*p == '-')
+    {
+        neg = true;
+        ++p;
+    }
+    while (*p >= '0' && *p <= '9')
+    {
+        r = (r * 10.0) + (*p - '0');
+        ++p;
+    }
+    if (*p == '.')
+    {
+        double f = 0.0;
+        int n = 0;
+        ++p;
+        while (*p >= '0' && *p <= '9')
+        {
+            f = (f * 10.0) + (*p - '0');
+            ++p;
+            ++n;
+        }
+        r += f / std::pow(10.0, n);
+    }
+    if (neg)
+    {
+        r = -r;
+    }
+    return r;
 }
 
-inline void replaceAll(std::string &s, const std::string &sub, const std::string &other) {
-	boost::replace_all(s, sub, other);
+template <typename T>
+struct scientific_policy : boost::spirit::karma::real_policies<T>
+{
+    //  we want the numbers always to be in fixed format
+    static int floatfield(T n) { return boost::spirit::karma::real_policies<T>::fmtflags::fixed; }
+    static unsigned int precision(T) { return 6; }
+};
+typedef
+boost::spirit::karma::real_generator<double, scientific_policy<double> >
+science_type;
+
+static inline std::string FixedDoubleToString(const double value)
+{
+    std::string output;
+    std::back_insert_iterator<std::string> sink(output);
+    boost::spirit::karma::generate(sink, science_type(), value);
+    if (output.size() >= 2 && output[output.size()-2] == '.' && output[output.size()-1] == '0')
+    {
+        output.resize(output.size()-2);
+    }
+    return output;
 }
 
-inline void stringSplit(const std::string &s, const char delim, std::vector<std::string>& result) {
-	boost::split(result, s, boost::is_any_of(std::string(&delim)));
+static inline std::string DoubleToString(const double value)
+{
+    std::string output;
+    std::back_insert_iterator<std::string> sink(output);
+    boost::spirit::karma::generate(sink, value);
+    return output;
 }
 
-static std::string originals[] = {"&", "\"",  "<",  ">", "'", "[", "]", "\\"};
-static std::string entities[] = {"&", """, "<", ">", "'", "&91;", "&93;", " \" };
+static inline void doubleToStringWithTwoDigitsBehindComma(const double value, std::string &output)
+{
+    // The largest 32-bit integer is 4294967295, that is 10 chars
+    // On the safe side, add 1 for sign, and 1 for trailing zero
+    char buffer[12];
+    sprintf(buffer, "%g", value);
+    output = buffer;
+}
+
+inline void replaceAll(std::string &s, const std::string &sub, const std::string &other)
+{
+    boost::replace_all(s, sub, other);
+}
 
-inline std::string HTMLEntitize( const std::string & input) {
-    std::string result(input);
-    for(unsigned i = 0; i < sizeof(originals)/sizeof(std::string); ++i) {
-        replaceAll(result, originals[i], entities[i]);
+inline std::string EscapeJSONString(const std::string &input)
+{
+    std::string output;
+    output.reserve(input.size());
+    for (auto iter = input.begin(); iter != input.end(); ++iter)
+    {
+        switch (iter[0])
+        {
+        case '\\':
+            output += "\\\\";
+            break;
+        case '"':
+            output += "\\\"";
+            break;
+        case '/':
+            output += "\\/";
+            break;
+        case '\b':
+            output += "\\b";
+            break;
+        case '\f':
+            output += "\\f";
+            break;
+        case '\n':
+            output += "\\n";
+            break;
+        case '\r':
+            output += "\\r";
+            break;
+        case '\t':
+            output += "\\t";
+            break;
+        default:
+            output += *iter;
+            break;
+        }
     }
-    return result;
+    return output;
 }
 
-inline std::string HTMLDeEntitize( std::string & result) {
-    for(unsigned i = 0; i < sizeof(originals)/sizeof(std::string); ++i) {
-        replaceAll(result, entities[i], originals[i]);
+static std::string originals[] = {"&", "\"", "<", ">", "'", "[", "]", "\\"};
+static std::string entities[] = {"&", """, "<", ">",
+                                 "'", "&91;",   "&93;", " \"};
+
+inline std::size_t URIDecode(const std::string &input, std::string &output)
+{
+    auto src_iter = input.begin();
+    output.resize(input.size() + 1);
+    std::size_t decoded_length = 0;
+    for (decoded_length = 0; src_iter != input.end(); ++decoded_length)
+    {
+        if (src_iter[0] == '%' && src_iter[1] && src_iter[2] && isxdigit(src_iter[1]) &&
+            isxdigit(src_iter[2]))
+        {
+            std::string::value_type a = src_iter[1];
+            std::string::value_type b = src_iter[2];
+            a -= src_iter[1] < 58 ? 48 : src_iter[1] < 71 ? 55 : 87;
+            b -= src_iter[2] < 58 ? 48 : src_iter[2] < 71 ? 55 : 87;
+            output[decoded_length] = 16 * a + b;
+            src_iter += 3;
+            continue;
+        }
+        output[decoded_length] = *src_iter++;
     }
-    return result;
+    output.resize(decoded_length);
+    return decoded_length;
 }
 
-inline bool StringStartsWith(const std::string & input, const std::string & prefix) {
+inline std::size_t URIDecodeInPlace(std::string &URI) { return URIDecode(URI, URI); }
+
+inline bool StringStartsWith(const std::string &input, const std::string &prefix)
+{
     return boost::starts_with(input, prefix);
 }
 
-// Function returns a 'random' filename in temporary directors.
-// May not be platform independent.
-inline void GetTemporaryFileName(std::string & filename) {
-    char buffer[L_tmpnam];
-    char * retPointer = tmpnam (buffer);
-    if(0 == retPointer)
-        ERR("Could not create temporary file name");
-    filename = buffer;
+inline std::string GetRandomString()
+{
+    std::string s;
+    s.resize(128);
+    static const char alphanum[] = "0123456789"
+                                   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                                   "abcdefghijklmnopqrstuvwxyz";
+
+    for (int i = 0; i < 127; ++i)
+    {
+        s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
+    }
+    s[127] = 0;
+    return s;
 }
 
-#endif /* STRINGUTIL_H_ */
+#endif // STRINGUTIL_H
diff --git a/Util/TimingUtil.h b/Util/TimingUtil.h
new file mode 100644
index 0000000..c1505ce
--- /dev/null
+++ b/Util/TimingUtil.h
@@ -0,0 +1,39 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef TIMINGUTIL_H
+#define TIMINGUTIL_H
+
+#include <chrono>
+
+#define TIMER_START(_X) auto _X##_start = std::chrono::steady_clock::now(), _X##_stop = _X##_start
+#define TIMER_STOP(_X) _X##_stop = std::chrono::steady_clock::now()
+#define TIMER_MSEC(_X) std::chrono::duration_cast<std::chrono::milliseconds>(_X##_stop - _X##_start).count()
+#define TIMER_SEC(_X) (0.001*std::chrono::duration_cast<std::chrono::milliseconds>(_X##_stop - _X##_start).count())
+#define TIMER_MIN(_X) std::chrono::duration_cast<std::chrono::minutes>(_X##_stop - _X##_start).count()
+
+#endif // TIMINGUTIL_H
diff --git a/Util/TrigonometryTables.h b/Util/TrigonometryTables.h
new file mode 100644
index 0000000..d145404
--- /dev/null
+++ b/Util/TrigonometryTables.h
@@ -0,0 +1,790 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef TRIGONOMETRY_TABLES_H
+#define TRIGONOMETRY_TABLES_H
+
+#include "../typedefs.h"
+#include <cmath>
+
+#include <limits>
+
+constexpr unsigned short atan_table[4096] = {
+0x0000,  0x0014,  0x0028,  0x003d,  0x0051,  0x0065,
+0x007a,  0x008e,  0x00a3,  0x00b7,  0x00cb,  0x00e0,
+0x00f4,  0x0108,  0x011d,  0x0131,  0x0146,  0x015a,
+0x016e,  0x0183,  0x0197,  0x01ab,  0x01c0,  0x01d4,
+0x01e9,  0x01fd,  0x0211,  0x0226,  0x023a,  0x024e,
+0x0263,  0x0277,  0x028c,  0x02a0,  0x02b4,  0x02c9,
+0x02dd,  0x02f1,  0x0306,  0x031a,  0x032f,  0x0343,
+0x0357,  0x036c,  0x0380,  0x0394,  0x03a9,  0x03bd,
+0x03d2,  0x03e6,  0x03fa,  0x040f,  0x0423,  0x0437,
+0x044c,  0x0460,  0x0475,  0x0489,  0x049d,  0x04b2,
+0x04c6,  0x04da,  0x04ef,  0x0503,  0x0517,  0x052c,
+0x0540,  0x0555,  0x0569,  0x057d,  0x0592,  0x05a6,
+0x05ba,  0x05cf,  0x05e3,  0x05f8,  0x060c,  0x0620,
+0x0635,  0x0649,  0x065d,  0x0672,  0x0686,  0x069b,
+0x06af,  0x06c3,  0x06d8,  0x06ec,  0x0700,  0x0715,
+0x0729,  0x073d,  0x0752,  0x0766,  0x077b,  0x078f,
+0x07a3,  0x07b8,  0x07cc,  0x07e0,  0x07f5,  0x0809,
+0x081d,  0x0832,  0x0846,  0x085b,  0x086f,  0x0883,
+0x0898,  0x08ac,  0x08c0,  0x08d5,  0x08e9,  0x08fd,
+0x0912,  0x0926,  0x093b,  0x094f,  0x0963,  0x0978,
+0x098c,  0x09a0,  0x09b5,  0x09c9,  0x09dd,  0x09f2,
+0x0a06,  0x0a1a,  0x0a2f,  0x0a43,  0x0a58,  0x0a6c,
+0x0a80,  0x0a95,  0x0aa9,  0x0abd,  0x0ad2,  0x0ae6,
+0x0afa,  0x0b0f,  0x0b23,  0x0b37,  0x0b4c,  0x0b60,
+0x0b75,  0x0b89,  0x0b9d,  0x0bb2,  0x0bc6,  0x0bda,
+0x0bef,  0x0c03,  0x0c17,  0x0c2c,  0x0c40,  0x0c54,
+0x0c69,  0x0c7d,  0x0c91,  0x0ca6,  0x0cba,  0x0cce,
+0x0ce3,  0x0cf7,  0x0d0b,  0x0d20,  0x0d34,  0x0d48,
+0x0d5d,  0x0d71,  0x0d86,  0x0d9a,  0x0dae,  0x0dc3,
+0x0dd7,  0x0deb,  0x0e00,  0x0e14,  0x0e28,  0x0e3d,
+0x0e51,  0x0e65,  0x0e7a,  0x0e8e,  0x0ea2,  0x0eb7,
+0x0ecb,  0x0edf,  0x0ef4,  0x0f08,  0x0f1c,  0x0f31,
+0x0f45,  0x0f59,  0x0f6e,  0x0f82,  0x0f96,  0x0fab,
+0x0fbf,  0x0fd3,  0x0fe8,  0x0ffc,  0x1010,  0x1025,
+0x1039,  0x104d,  0x1062,  0x1076,  0x108a,  0x109e,
+0x10b3,  0x10c7,  0x10db,  0x10f0,  0x1104,  0x1118,
+0x112d,  0x1141,  0x1155,  0x116a,  0x117e,  0x1192,
+0x11a7,  0x11bb,  0x11cf,  0x11e4,  0x11f8,  0x120c,
+0x1221,  0x1235,  0x1249,  0x125d,  0x1272,  0x1286,
+0x129a,  0x12af,  0x12c3,  0x12d7,  0x12ec,  0x1300,
+0x1314,  0x1329,  0x133d,  0x1351,  0x1365,  0x137a,
+0x138e,  0x13a2,  0x13b7,  0x13cb,  0x13df,  0x13f4,
+0x1408,  0x141c,  0x1431,  0x1445,  0x1459,  0x146d,
+0x1482,  0x1496,  0x14aa,  0x14bf,  0x14d3,  0x14e7,
+0x14fb,  0x1510,  0x1524,  0x1538,  0x154d,  0x1561,
+0x1575,  0x1589,  0x159e,  0x15b2,  0x15c6,  0x15db,
+0x15ef,  0x1603,  0x1617,  0x162c,  0x1640,  0x1654,
+0x1669,  0x167d,  0x1691,  0x16a5,  0x16ba,  0x16ce,
+0x16e2,  0x16f7,  0x170b,  0x171f,  0x1733,  0x1748,
+0x175c,  0x1770,  0x1784,  0x1799,  0x17ad,  0x17c1,
+0x17d6,  0x17ea,  0x17fe,  0x1812,  0x1827,  0x183b,
+0x184f,  0x1863,  0x1878,  0x188c,  0x18a0,  0x18b4,
+0x18c9,  0x18dd,  0x18f1,  0x1905,  0x191a,  0x192e,
+0x1942,  0x1957,  0x196b,  0x197f,  0x1993,  0x19a8,
+0x19bc,  0x19d0,  0x19e4,  0x19f9,  0x1a0d,  0x1a21,
+0x1a35,  0x1a49,  0x1a5e,  0x1a72,  0x1a86,  0x1a9a,
+0x1aaf,  0x1ac3,  0x1ad7,  0x1aeb,  0x1b00,  0x1b14,
+0x1b28,  0x1b3c,  0x1b51,  0x1b65,  0x1b79,  0x1b8d,
+0x1ba2,  0x1bb6,  0x1bca,  0x1bde,  0x1bf2,  0x1c07,
+0x1c1b,  0x1c2f,  0x1c43,  0x1c58,  0x1c6c,  0x1c80,
+0x1c94,  0x1ca8,  0x1cbd,  0x1cd1,  0x1ce5,  0x1cf9,
+0x1d0e,  0x1d22,  0x1d36,  0x1d4a,  0x1d5e,  0x1d73,
+0x1d87,  0x1d9b,  0x1daf,  0x1dc3,  0x1dd8,  0x1dec,
+0x1e00,  0x1e14,  0x1e28,  0x1e3d,  0x1e51,  0x1e65,
+0x1e79,  0x1e8d,  0x1ea2,  0x1eb6,  0x1eca,  0x1ede,
+0x1ef2,  0x1f07,  0x1f1b,  0x1f2f,  0x1f43,  0x1f57,
+0x1f6c,  0x1f80,  0x1f94,  0x1fa8,  0x1fbc,  0x1fd1,
+0x1fe5,  0x1ff9,  0x200d,  0x2021,  0x2035,  0x204a,
+0x205e,  0x2072,  0x2086,  0x209a,  0x20ae,  0x20c3,
+0x20d7,  0x20eb,  0x20ff,  0x2113,  0x2127,  0x213c,
+0x2150,  0x2164,  0x2178,  0x218c,  0x21a0,  0x21b5,
+0x21c9,  0x21dd,  0x21f1,  0x2205,  0x2219,  0x222e,
+0x2242,  0x2256,  0x226a,  0x227e,  0x2292,  0x22a6,
+0x22bb,  0x22cf,  0x22e3,  0x22f7,  0x230b,  0x231f,
+0x2333,  0x2348,  0x235c,  0x2370,  0x2384,  0x2398,
+0x23ac,  0x23c0,  0x23d5,  0x23e9,  0x23fd,  0x2411,
+0x2425,  0x2439,  0x244d,  0x2461,  0x2476,  0x248a,
+0x249e,  0x24b2,  0x24c6,  0x24da,  0x24ee,  0x2502,
+0x2517,  0x252b,  0x253f,  0x2553,  0x2567,  0x257b,
+0x258f,  0x25a3,  0x25b7,  0x25cb,  0x25e0,  0x25f4,
+0x2608,  0x261c,  0x2630,  0x2644,  0x2658,  0x266c,
+0x2680,  0x2694,  0x26a9,  0x26bd,  0x26d1,  0x26e5,
+0x26f9,  0x270d,  0x2721,  0x2735,  0x2749,  0x275d,
+0x2771,  0x2785,  0x279a,  0x27ae,  0x27c2,  0x27d6,
+0x27ea,  0x27fe,  0x2812,  0x2826,  0x283a,  0x284e,
+0x2862,  0x2876,  0x288a,  0x289e,  0x28b3,  0x28c7,
+0x28db,  0x28ef,  0x2903,  0x2917,  0x292b,  0x293f,
+0x2953,  0x2967,  0x297b,  0x298f,  0x29a3,  0x29b7,
+0x29cb,  0x29df,  0x29f3,  0x2a07,  0x2a1b,  0x2a2f,
+0x2a43,  0x2a58,  0x2a6c,  0x2a80,  0x2a94,  0x2aa8,
+0x2abc,  0x2ad0,  0x2ae4,  0x2af8,  0x2b0c,  0x2b20,
+0x2b34,  0x2b48,  0x2b5c,  0x2b70,  0x2b84,  0x2b98,
+0x2bac,  0x2bc0,  0x2bd4,  0x2be8,  0x2bfc,  0x2c10,
+0x2c24,  0x2c38,  0x2c4c,  0x2c60,  0x2c74,  0x2c88,
+0x2c9c,  0x2cb0,  0x2cc4,  0x2cd8,  0x2cec,  0x2d00,
+0x2d14,  0x2d28,  0x2d3c,  0x2d50,  0x2d64,  0x2d78,
+0x2d8c,  0x2da0,  0x2db4,  0x2dc8,  0x2ddc,  0x2df0,
+0x2e04,  0x2e18,  0x2e2c,  0x2e40,  0x2e54,  0x2e68,
+0x2e7c,  0x2e90,  0x2ea3,  0x2eb7,  0x2ecb,  0x2edf,
+0x2ef3,  0x2f07,  0x2f1b,  0x2f2f,  0x2f43,  0x2f57,
+0x2f6b,  0x2f7f,  0x2f93,  0x2fa7,  0x2fbb,  0x2fcf,
+0x2fe3,  0x2ff7,  0x300b,  0x301e,  0x3032,  0x3046,
+0x305a,  0x306e,  0x3082,  0x3096,  0x30aa,  0x30be,
+0x30d2,  0x30e6,  0x30fa,  0x310e,  0x3122,  0x3135,
+0x3149,  0x315d,  0x3171,  0x3185,  0x3199,  0x31ad,
+0x31c1,  0x31d5,  0x31e9,  0x31fd,  0x3210,  0x3224,
+0x3238,  0x324c,  0x3260,  0x3274,  0x3288,  0x329c,
+0x32b0,  0x32c3,  0x32d7,  0x32eb,  0x32ff,  0x3313,
+0x3327,  0x333b,  0x334f,  0x3363,  0x3376,  0x338a,
+0x339e,  0x33b2,  0x33c6,  0x33da,  0x33ee,  0x3401,
+0x3415,  0x3429,  0x343d,  0x3451,  0x3465,  0x3479,
+0x348c,  0x34a0,  0x34b4,  0x34c8,  0x34dc,  0x34f0,
+0x3504,  0x3517,  0x352b,  0x353f,  0x3553,  0x3567,
+0x357b,  0x358e,  0x35a2,  0x35b6,  0x35ca,  0x35de,
+0x35f2,  0x3605,  0x3619,  0x362d,  0x3641,  0x3655,
+0x3668,  0x367c,  0x3690,  0x36a4,  0x36b8,  0x36cb,
+0x36df,  0x36f3,  0x3707,  0x371b,  0x372f,  0x3742,
+0x3756,  0x376a,  0x377e,  0x3791,  0x37a5,  0x37b9,
+0x37cd,  0x37e1,  0x37f4,  0x3808,  0x381c,  0x3830,
+0x3844,  0x3857,  0x386b,  0x387f,  0x3893,  0x38a6,
+0x38ba,  0x38ce,  0x38e2,  0x38f5,  0x3909,  0x391d,
+0x3931,  0x3944,  0x3958,  0x396c,  0x3980,  0x3993,
+0x39a7,  0x39bb,  0x39cf,  0x39e2,  0x39f6,  0x3a0a,
+0x3a1e,  0x3a31,  0x3a45,  0x3a59,  0x3a6d,  0x3a80,
+0x3a94,  0x3aa8,  0x3abb,  0x3acf,  0x3ae3,  0x3af7,
+0x3b0a,  0x3b1e,  0x3b32,  0x3b45,  0x3b59,  0x3b6d,
+0x3b81,  0x3b94,  0x3ba8,  0x3bbc,  0x3bcf,  0x3be3,
+0x3bf7,  0x3c0b,  0x3c1e,  0x3c32,  0x3c46,  0x3c59,
+0x3c6d,  0x3c81,  0x3c94,  0x3ca8,  0x3cbc,  0x3ccf,
+0x3ce3,  0x3cf7,  0x3d0a,  0x3d1e,  0x3d32,  0x3d45,
+0x3d59,  0x3d6d,  0x3d80,  0x3d94,  0x3da8,  0x3dbb,
+0x3dcf,  0x3de3,  0x3df6,  0x3e0a,  0x3e1e,  0x3e31,
+0x3e45,  0x3e59,  0x3e6c,  0x3e80,  0x3e93,  0x3ea7,
+0x3ebb,  0x3ece,  0x3ee2,  0x3ef6,  0x3f09,  0x3f1d,
+0x3f30,  0x3f44,  0x3f58,  0x3f6b,  0x3f7f,  0x3f93,
+0x3fa6,  0x3fba,  0x3fcd,  0x3fe1,  0x3ff5,  0x4008,
+0x401c,  0x402f,  0x4043,  0x4057,  0x406a,  0x407e,
+0x4091,  0x40a5,  0x40b8,  0x40cc,  0x40e0,  0x40f3,
+0x4107,  0x411a,  0x412e,  0x4142,  0x4155,  0x4169,
+0x417c,  0x4190,  0x41a3,  0x41b7,  0x41ca,  0x41de,
+0x41f2,  0x4205,  0x4219,  0x422c,  0x4240,  0x4253,
+0x4267,  0x427a,  0x428e,  0x42a1,  0x42b5,  0x42c9,
+0x42dc,  0x42f0,  0x4303,  0x4317,  0x432a,  0x433e,
+0x4351,  0x4365,  0x4378,  0x438c,  0x439f,  0x43b3,
+0x43c6,  0x43da,  0x43ed,  0x4401,  0x4414,  0x4428,
+0x443b,  0x444f,  0x4462,  0x4476,  0x4489,  0x449d,
+0x44b0,  0x44c4,  0x44d7,  0x44eb,  0x44fe,  0x4512,
+0x4525,  0x4539,  0x454c,  0x4560,  0x4573,  0x4586,
+0x459a,  0x45ad,  0x45c1,  0x45d4,  0x45e8,  0x45fb,
+0x460f,  0x4622,  0x4636,  0x4649,  0x465c,  0x4670,
+0x4683,  0x4697,  0x46aa,  0x46be,  0x46d1,  0x46e5,
+0x46f8,  0x470b,  0x471f,  0x4732,  0x4746,  0x4759,
+0x476c,  0x4780,  0x4793,  0x47a7,  0x47ba,  0x47cd,
+0x47e1,  0x47f4,  0x4808,  0x481b,  0x482e,  0x4842,
+0x4855,  0x4869,  0x487c,  0x488f,  0x48a3,  0x48b6,
+0x48ca,  0x48dd,  0x48f0,  0x4904,  0x4917,  0x492a,
+0x493e,  0x4951,  0x4965,  0x4978,  0x498b,  0x499f,
+0x49b2,  0x49c5,  0x49d9,  0x49ec,  0x49ff,  0x4a13,
+0x4a26,  0x4a39,  0x4a4d,  0x4a60,  0x4a73,  0x4a87,
+0x4a9a,  0x4aad,  0x4ac1,  0x4ad4,  0x4ae7,  0x4afb,
+0x4b0e,  0x4b21,  0x4b35,  0x4b48,  0x4b5b,  0x4b6f,
+0x4b82,  0x4b95,  0x4ba8,  0x4bbc,  0x4bcf,  0x4be2,
+0x4bf6,  0x4c09,  0x4c1c,  0x4c2f,  0x4c43,  0x4c56,
+0x4c69,  0x4c7d,  0x4c90,  0x4ca3,  0x4cb6,  0x4cca,
+0x4cdd,  0x4cf0,  0x4d03,  0x4d17,  0x4d2a,  0x4d3d,
+0x4d50,  0x4d64,  0x4d77,  0x4d8a,  0x4d9d,  0x4db1,
+0x4dc4,  0x4dd7,  0x4dea,  0x4dfe,  0x4e11,  0x4e24,
+0x4e37,  0x4e4b,  0x4e5e,  0x4e71,  0x4e84,  0x4e97,
+0x4eab,  0x4ebe,  0x4ed1,  0x4ee4,  0x4ef7,  0x4f0b,
+0x4f1e,  0x4f31,  0x4f44,  0x4f57,  0x4f6b,  0x4f7e,
+0x4f91,  0x4fa4,  0x4fb7,  0x4fcb,  0x4fde,  0x4ff1,
+0x5004,  0x5017,  0x502a,  0x503e,  0x5051,  0x5064,
+0x5077,  0x508a,  0x509d,  0x50b1,  0x50c4,  0x50d7,
+0x50ea,  0x50fd,  0x5110,  0x5123,  0x5137,  0x514a,
+0x515d,  0x5170,  0x5183,  0x5196,  0x51a9,  0x51bc,
+0x51d0,  0x51e3,  0x51f6,  0x5209,  0x521c,  0x522f,
+0x5242,  0x5255,  0x5268,  0x527c,  0x528f,  0x52a2,
+0x52b5,  0x52c8,  0x52db,  0x52ee,  0x5301,  0x5314,
+0x5327,  0x533a,  0x534e,  0x5361,  0x5374,  0x5387,
+0x539a,  0x53ad,  0x53c0,  0x53d3,  0x53e6,  0x53f9,
+0x540c,  0x541f,  0x5432,  0x5445,  0x5458,  0x546b,
+0x547e,  0x5491,  0x54a5,  0x54b8,  0x54cb,  0x54de,
+0x54f1,  0x5504,  0x5517,  0x552a,  0x553d,  0x5550,
+0x5563,  0x5576,  0x5589,  0x559c,  0x55af,  0x55c2,
+0x55d5,  0x55e8,  0x55fb,  0x560e,  0x5621,  0x5634,
+0x5647,  0x565a,  0x566d,  0x5680,  0x5693,  0x56a6,
+0x56b9,  0x56cb,  0x56de,  0x56f1,  0x5704,  0x5717,
+0x572a,  0x573d,  0x5750,  0x5763,  0x5776,  0x5789,
+0x579c,  0x57af,  0x57c2,  0x57d5,  0x57e8,  0x57fb,
+0x580e,  0x5820,  0x5833,  0x5846,  0x5859,  0x586c,
+0x587f,  0x5892,  0x58a5,  0x58b8,  0x58cb,  0x58de,
+0x58f0,  0x5903,  0x5916,  0x5929,  0x593c,  0x594f,
+0x5962,  0x5975,  0x5988,  0x599a,  0x59ad,  0x59c0,
+0x59d3,  0x59e6,  0x59f9,  0x5a0c,  0x5a1f,  0x5a31,
+0x5a44,  0x5a57,  0x5a6a,  0x5a7d,  0x5a90,  0x5aa2,
+0x5ab5,  0x5ac8,  0x5adb,  0x5aee,  0x5b01,  0x5b13,
+0x5b26,  0x5b39,  0x5b4c,  0x5b5f,  0x5b72,  0x5b84,
+0x5b97,  0x5baa,  0x5bbd,  0x5bd0,  0x5be2,  0x5bf5,
+0x5c08,  0x5c1b,  0x5c2e,  0x5c40,  0x5c53,  0x5c66,
+0x5c79,  0x5c8c,  0x5c9e,  0x5cb1,  0x5cc4,  0x5cd7,
+0x5ce9,  0x5cfc,  0x5d0f,  0x5d22,  0x5d34,  0x5d47,
+0x5d5a,  0x5d6d,  0x5d7f,  0x5d92,  0x5da5,  0x5db8,
+0x5dca,  0x5ddd,  0x5df0,  0x5e03,  0x5e15,  0x5e28,
+0x5e3b,  0x5e4d,  0x5e60,  0x5e73,  0x5e86,  0x5e98,
+0x5eab,  0x5ebe,  0x5ed0,  0x5ee3,  0x5ef6,  0x5f09,
+0x5f1b,  0x5f2e,  0x5f41,  0x5f53,  0x5f66,  0x5f79,
+0x5f8b,  0x5f9e,  0x5fb1,  0x5fc3,  0x5fd6,  0x5fe9,
+0x5ffb,  0x600e,  0x6021,  0x6033,  0x6046,  0x6059,
+0x606b,  0x607e,  0x6091,  0x60a3,  0x60b6,  0x60c8,
+0x60db,  0x60ee,  0x6100,  0x6113,  0x6126,  0x6138,
+0x614b,  0x615d,  0x6170,  0x6183,  0x6195,  0x61a8,
+0x61ba,  0x61cd,  0x61e0,  0x61f2,  0x6205,  0x6217,
+0x622a,  0x623d,  0x624f,  0x6262,  0x6274,  0x6287,
+0x6299,  0x62ac,  0x62bf,  0x62d1,  0x62e4,  0x62f6,
+0x6309,  0x631b,  0x632e,  0x6340,  0x6353,  0x6366,
+0x6378,  0x638b,  0x639d,  0x63b0,  0x63c2,  0x63d5,
+0x63e7,  0x63fa,  0x640c,  0x641f,  0x6431,  0x6444,
+0x6456,  0x6469,  0x647b,  0x648e,  0x64a0,  0x64b3,
+0x64c5,  0x64d8,  0x64ea,  0x64fd,  0x650f,  0x6522,
+0x6534,  0x6547,  0x6559,  0x656c,  0x657e,  0x6591,
+0x65a3,  0x65b5,  0x65c8,  0x65da,  0x65ed,  0x65ff,
+0x6612,  0x6624,  0x6637,  0x6649,  0x665b,  0x666e,
+0x6680,  0x6693,  0x66a5,  0x66b8,  0x66ca,  0x66dc,
+0x66ef,  0x6701,  0x6714,  0x6726,  0x6738,  0x674b,
+0x675d,  0x6770,  0x6782,  0x6794,  0x67a7,  0x67b9,
+0x67cc,  0x67de,  0x67f0,  0x6803,  0x6815,  0x6827,
+0x683a,  0x684c,  0x685e,  0x6871,  0x6883,  0x6896,
+0x68a8,  0x68ba,  0x68cd,  0x68df,  0x68f1,  0x6904,
+0x6916,  0x6928,  0x693b,  0x694d,  0x695f,  0x6972,
+0x6984,  0x6996,  0x69a8,  0x69bb,  0x69cd,  0x69df,
+0x69f2,  0x6a04,  0x6a16,  0x6a29,  0x6a3b,  0x6a4d,
+0x6a5f,  0x6a72,  0x6a84,  0x6a96,  0x6aa9,  0x6abb,
+0x6acd,  0x6adf,  0x6af2,  0x6b04,  0x6b16,  0x6b28,
+0x6b3b,  0x6b4d,  0x6b5f,  0x6b71,  0x6b84,  0x6b96,
+0x6ba8,  0x6bba,  0x6bcd,  0x6bdf,  0x6bf1,  0x6c03,
+0x6c15,  0x6c28,  0x6c3a,  0x6c4c,  0x6c5e,  0x6c70,
+0x6c83,  0x6c95,  0x6ca7,  0x6cb9,  0x6ccb,  0x6cde,
+0x6cf0,  0x6d02,  0x6d14,  0x6d26,  0x6d39,  0x6d4b,
+0x6d5d,  0x6d6f,  0x6d81,  0x6d93,  0x6da6,  0x6db8,
+0x6dca,  0x6ddc,  0x6dee,  0x6e00,  0x6e12,  0x6e25,
+0x6e37,  0x6e49,  0x6e5b,  0x6e6d,  0x6e7f,  0x6e91,
+0x6ea3,  0x6eb6,  0x6ec8,  0x6eda,  0x6eec,  0x6efe,
+0x6f10,  0x6f22,  0x6f34,  0x6f46,  0x6f58,  0x6f6b,
+0x6f7d,  0x6f8f,  0x6fa1,  0x6fb3,  0x6fc5,  0x6fd7,
+0x6fe9,  0x6ffb,  0x700d,  0x701f,  0x7031,  0x7043,
+0x7055,  0x7068,  0x707a,  0x708c,  0x709e,  0x70b0,
+0x70c2,  0x70d4,  0x70e6,  0x70f8,  0x710a,  0x711c,
+0x712e,  0x7140,  0x7152,  0x7164,  0x7176,  0x7188,
+0x719a,  0x71ac,  0x71be,  0x71d0,  0x71e2,  0x71f4,
+0x7206,  0x7218,  0x722a,  0x723c,  0x724e,  0x7260,
+0x7272,  0x7284,  0x7296,  0x72a8,  0x72ba,  0x72cc,
+0x72dd,  0x72ef,  0x7301,  0x7313,  0x7325,  0x7337,
+0x7349,  0x735b,  0x736d,  0x737f,  0x7391,  0x73a3,
+0x73b5,  0x73c7,  0x73d8,  0x73ea,  0x73fc,  0x740e,
+0x7420,  0x7432,  0x7444,  0x7456,  0x7468,  0x747a,
+0x748b,  0x749d,  0x74af,  0x74c1,  0x74d3,  0x74e5,
+0x74f7,  0x7509,  0x751a,  0x752c,  0x753e,  0x7550,
+0x7562,  0x7574,  0x7585,  0x7597,  0x75a9,  0x75bb,
+0x75cd,  0x75df,  0x75f0,  0x7602,  0x7614,  0x7626,
+0x7638,  0x764a,  0x765b,  0x766d,  0x767f,  0x7691,
+0x76a3,  0x76b4,  0x76c6,  0x76d8,  0x76ea,  0x76fb,
+0x770d,  0x771f,  0x7731,  0x7743,  0x7754,  0x7766,
+0x7778,  0x778a,  0x779b,  0x77ad,  0x77bf,  0x77d1,
+0x77e2,  0x77f4,  0x7806,  0x7818,  0x7829,  0x783b,
+0x784d,  0x785e,  0x7870,  0x7882,  0x7894,  0x78a5,
+0x78b7,  0x78c9,  0x78da,  0x78ec,  0x78fe,  0x7910,
+0x7921,  0x7933,  0x7945,  0x7956,  0x7968,  0x797a,
+0x798b,  0x799d,  0x79af,  0x79c0,  0x79d2,  0x79e4,
+0x79f5,  0x7a07,  0x7a19,  0x7a2a,  0x7a3c,  0x7a4e,
+0x7a5f,  0x7a71,  0x7a82,  0x7a94,  0x7aa6,  0x7ab7,
+0x7ac9,  0x7adb,  0x7aec,  0x7afe,  0x7b0f,  0x7b21,
+0x7b33,  0x7b44,  0x7b56,  0x7b67,  0x7b79,  0x7b8b,
+0x7b9c,  0x7bae,  0x7bbf,  0x7bd1,  0x7be2,  0x7bf4,
+0x7c06,  0x7c17,  0x7c29,  0x7c3a,  0x7c4c,  0x7c5d,
+0x7c6f,  0x7c81,  0x7c92,  0x7ca4,  0x7cb5,  0x7cc7,
+0x7cd8,  0x7cea,  0x7cfb,  0x7d0d,  0x7d1e,  0x7d30,
+0x7d41,  0x7d53,  0x7d64,  0x7d76,  0x7d87,  0x7d99,
+0x7daa,  0x7dbc,  0x7dcd,  0x7ddf,  0x7df0,  0x7e02,
+0x7e13,  0x7e25,  0x7e36,  0x7e48,  0x7e59,  0x7e6b,
+0x7e7c,  0x7e8e,  0x7e9f,  0x7eb0,  0x7ec2,  0x7ed3,
+0x7ee5,  0x7ef6,  0x7f08,  0x7f19,  0x7f2b,  0x7f3c,
+0x7f4d,  0x7f5f,  0x7f70,  0x7f82,  0x7f93,  0x7fa4,
+0x7fb6,  0x7fc7,  0x7fd9,  0x7fea,  0x7ffb,  0x800d,
+0x801e,  0x8030,  0x8041,  0x8052,  0x8064,  0x8075,
+0x8086,  0x8098,  0x80a9,  0x80bb,  0x80cc,  0x80dd,
+0x80ef,  0x8100,  0x8111,  0x8123,  0x8134,  0x8145,
+0x8157,  0x8168,  0x8179,  0x818b,  0x819c,  0x81ad,
+0x81bf,  0x81d0,  0x81e1,  0x81f3,  0x8204,  0x8215,
+0x8226,  0x8238,  0x8249,  0x825a,  0x826c,  0x827d,
+0x828e,  0x829f,  0x82b1,  0x82c2,  0x82d3,  0x82e5,
+0x82f6,  0x8307,  0x8318,  0x832a,  0x833b,  0x834c,
+0x835d,  0x836f,  0x8380,  0x8391,  0x83a2,  0x83b3,
+0x83c5,  0x83d6,  0x83e7,  0x83f8,  0x840a,  0x841b,
+0x842c,  0x843d,  0x844e,  0x8460,  0x8471,  0x8482,
+0x8493,  0x84a4,  0x84b6,  0x84c7,  0x84d8,  0x84e9,
+0x84fa,  0x850b,  0x851d,  0x852e,  0x853f,  0x8550,
+0x8561,  0x8572,  0x8584,  0x8595,  0x85a6,  0x85b7,
+0x85c8,  0x85d9,  0x85ea,  0x85fb,  0x860d,  0x861e,
+0x862f,  0x8640,  0x8651,  0x8662,  0x8673,  0x8684,
+0x8695,  0x86a7,  0x86b8,  0x86c9,  0x86da,  0x86eb,
+0x86fc,  0x870d,  0x871e,  0x872f,  0x8740,  0x8751,
+0x8762,  0x8773,  0x8784,  0x8796,  0x87a7,  0x87b8,
+0x87c9,  0x87da,  0x87eb,  0x87fc,  0x880d,  0x881e,
+0x882f,  0x8840,  0x8851,  0x8862,  0x8873,  0x8884,
+0x8895,  0x88a6,  0x88b7,  0x88c8,  0x88d9,  0x88ea,
+0x88fb,  0x890c,  0x891d,  0x892e,  0x893f,  0x8950,
+0x8961,  0x8972,  0x8983,  0x8994,  0x89a5,  0x89b6,
+0x89c6,  0x89d7,  0x89e8,  0x89f9,  0x8a0a,  0x8a1b,
+0x8a2c,  0x8a3d,  0x8a4e,  0x8a5f,  0x8a70,  0x8a81,
+0x8a92,  0x8aa3,  0x8ab3,  0x8ac4,  0x8ad5,  0x8ae6,
+0x8af7,  0x8b08,  0x8b19,  0x8b2a,  0x8b3b,  0x8b4b,
+0x8b5c,  0x8b6d,  0x8b7e,  0x8b8f,  0x8ba0,  0x8bb1,
+0x8bc1,  0x8bd2,  0x8be3,  0x8bf4,  0x8c05,  0x8c16,
+0x8c27,  0x8c37,  0x8c48,  0x8c59,  0x8c6a,  0x8c7b,
+0x8c8c,  0x8c9c,  0x8cad,  0x8cbe,  0x8ccf,  0x8ce0,
+0x8cf0,  0x8d01,  0x8d12,  0x8d23,  0x8d34,  0x8d44,
+0x8d55,  0x8d66,  0x8d77,  0x8d87,  0x8d98,  0x8da9,
+0x8dba,  0x8dca,  0x8ddb,  0x8dec,  0x8dfd,  0x8e0d,
+0x8e1e,  0x8e2f,  0x8e40,  0x8e50,  0x8e61,  0x8e72,
+0x8e83,  0x8e93,  0x8ea4,  0x8eb5,  0x8ec5,  0x8ed6,
+0x8ee7,  0x8ef8,  0x8f08,  0x8f19,  0x8f2a,  0x8f3a,
+0x8f4b,  0x8f5c,  0x8f6c,  0x8f7d,  0x8f8e,  0x8f9e,
+0x8faf,  0x8fc0,  0x8fd0,  0x8fe1,  0x8ff2,  0x9002,
+0x9013,  0x9024,  0x9034,  0x9045,  0x9056,  0x9066,
+0x9077,  0x9088,  0x9098,  0x90a9,  0x90b9,  0x90ca,
+0x90db,  0x90eb,  0x90fc,  0x910c,  0x911d,  0x912e,
+0x913e,  0x914f,  0x915f,  0x9170,  0x9181,  0x9191,
+0x91a2,  0x91b2,  0x91c3,  0x91d3,  0x91e4,  0x91f5,
+0x9205,  0x9216,  0x9226,  0x9237,  0x9247,  0x9258,
+0x9268,  0x9279,  0x9289,  0x929a,  0x92aa,  0x92bb,
+0x92cc,  0x92dc,  0x92ed,  0x92fd,  0x930e,  0x931e,
+0x932f,  0x933f,  0x9350,  0x9360,  0x9370,  0x9381,
+0x9391,  0x93a2,  0x93b2,  0x93c3,  0x93d3,  0x93e4,
+0x93f4,  0x9405,  0x9415,  0x9426,  0x9436,  0x9447,
+0x9457,  0x9467,  0x9478,  0x9488,  0x9499,  0x94a9,
+0x94ba,  0x94ca,  0x94da,  0x94eb,  0x94fb,  0x950c,
+0x951c,  0x952c,  0x953d,  0x954d,  0x955e,  0x956e,
+0x957e,  0x958f,  0x959f,  0x95af,  0x95c0,  0x95d0,
+0x95e1,  0x95f1,  0x9601,  0x9612,  0x9622,  0x9632,
+0x9643,  0x9653,  0x9663,  0x9674,  0x9684,  0x9694,
+0x96a5,  0x96b5,  0x96c5,  0x96d6,  0x96e6,  0x96f6,
+0x9707,  0x9717,  0x9727,  0x9738,  0x9748,  0x9758,
+0x9768,  0x9779,  0x9789,  0x9799,  0x97aa,  0x97ba,
+0x97ca,  0x97da,  0x97eb,  0x97fb,  0x980b,  0x981b,
+0x982c,  0x983c,  0x984c,  0x985c,  0x986d,  0x987d,
+0x988d,  0x989d,  0x98ad,  0x98be,  0x98ce,  0x98de,
+0x98ee,  0x98ff,  0x990f,  0x991f,  0x992f,  0x993f,
+0x9950,  0x9960,  0x9970,  0x9980,  0x9990,  0x99a0,
+0x99b1,  0x99c1,  0x99d1,  0x99e1,  0x99f1,  0x9a01,
+0x9a12,  0x9a22,  0x9a32,  0x9a42,  0x9a52,  0x9a62,
+0x9a72,  0x9a83,  0x9a93,  0x9aa3,  0x9ab3,  0x9ac3,
+0x9ad3,  0x9ae3,  0x9af3,  0x9b04,  0x9b14,  0x9b24,
+0x9b34,  0x9b44,  0x9b54,  0x9b64,  0x9b74,  0x9b84,
+0x9b94,  0x9ba4,  0x9bb5,  0x9bc5,  0x9bd5,  0x9be5,
+0x9bf5,  0x9c05,  0x9c15,  0x9c25,  0x9c35,  0x9c45,
+0x9c55,  0x9c65,  0x9c75,  0x9c85,  0x9c95,  0x9ca5,
+0x9cb5,  0x9cc5,  0x9cd5,  0x9ce5,  0x9cf5,  0x9d05,
+0x9d15,  0x9d25,  0x9d35,  0x9d45,  0x9d55,  0x9d65,
+0x9d75,  0x9d85,  0x9d95,  0x9da5,  0x9db5,  0x9dc5,
+0x9dd5,  0x9de5,  0x9df5,  0x9e05,  0x9e15,  0x9e25,
+0x9e35,  0x9e45,  0x9e55,  0x9e65,  0x9e74,  0x9e84,
+0x9e94,  0x9ea4,  0x9eb4,  0x9ec4,  0x9ed4,  0x9ee4,
+0x9ef4,  0x9f04,  0x9f14,  0x9f23,  0x9f33,  0x9f43,
+0x9f53,  0x9f63,  0x9f73,  0x9f83,  0x9f93,  0x9fa3,
+0x9fb2,  0x9fc2,  0x9fd2,  0x9fe2,  0x9ff2,  0xa002,
+0xa012,  0xa021,  0xa031,  0xa041,  0xa051,  0xa061,
+0xa071,  0xa080,  0xa090,  0xa0a0,  0xa0b0,  0xa0c0,
+0xa0cf,  0xa0df,  0xa0ef,  0xa0ff,  0xa10f,  0xa11e,
+0xa12e,  0xa13e,  0xa14e,  0xa15e,  0xa16d,  0xa17d,
+0xa18d,  0xa19d,  0xa1ac,  0xa1bc,  0xa1cc,  0xa1dc,
+0xa1eb,  0xa1fb,  0xa20b,  0xa21b,  0xa22a,  0xa23a,
+0xa24a,  0xa25a,  0xa269,  0xa279,  0xa289,  0xa298,
+0xa2a8,  0xa2b8,  0xa2c8,  0xa2d7,  0xa2e7,  0xa2f7,
+0xa306,  0xa316,  0xa326,  0xa335,  0xa345,  0xa355,
+0xa364,  0xa374,  0xa384,  0xa393,  0xa3a3,  0xa3b3,
+0xa3c2,  0xa3d2,  0xa3e2,  0xa3f1,  0xa401,  0xa411,
+0xa420,  0xa430,  0xa440,  0xa44f,  0xa45f,  0xa46e,
+0xa47e,  0xa48e,  0xa49d,  0xa4ad,  0xa4bc,  0xa4cc,
+0xa4dc,  0xa4eb,  0xa4fb,  0xa50a,  0xa51a,  0xa52a,
+0xa539,  0xa549,  0xa558,  0xa568,  0xa577,  0xa587,
+0xa597,  0xa5a6,  0xa5b6,  0xa5c5,  0xa5d5,  0xa5e4,
+0xa5f4,  0xa603,  0xa613,  0xa622,  0xa632,  0xa641,
+0xa651,  0xa660,  0xa670,  0xa67f,  0xa68f,  0xa69e,
+0xa6ae,  0xa6bd,  0xa6cd,  0xa6dc,  0xa6ec,  0xa6fb,
+0xa70b,  0xa71a,  0xa72a,  0xa739,  0xa749,  0xa758,
+0xa768,  0xa777,  0xa787,  0xa796,  0xa7a5,  0xa7b5,
+0xa7c4,  0xa7d4,  0xa7e3,  0xa7f3,  0xa802,  0xa812,
+0xa821,  0xa830,  0xa840,  0xa84f,  0xa85f,  0xa86e,
+0xa87d,  0xa88d,  0xa89c,  0xa8ac,  0xa8bb,  0xa8ca,
+0xa8da,  0xa8e9,  0xa8f8,  0xa908,  0xa917,  0xa927,
+0xa936,  0xa945,  0xa955,  0xa964,  0xa973,  0xa983,
+0xa992,  0xa9a1,  0xa9b1,  0xa9c0,  0xa9cf,  0xa9df,
+0xa9ee,  0xa9fd,  0xaa0d,  0xaa1c,  0xaa2b,  0xaa3b,
+0xaa4a,  0xaa59,  0xaa69,  0xaa78,  0xaa87,  0xaa96,
+0xaaa6,  0xaab5,  0xaac4,  0xaad4,  0xaae3,  0xaaf2,
+0xab01,  0xab11,  0xab20,  0xab2f,  0xab3e,  0xab4e,
+0xab5d,  0xab6c,  0xab7b,  0xab8b,  0xab9a,  0xaba9,
+0xabb8,  0xabc7,  0xabd7,  0xabe6,  0xabf5,  0xac04,
+0xac14,  0xac23,  0xac32,  0xac41,  0xac50,  0xac60,
+0xac6f,  0xac7e,  0xac8d,  0xac9c,  0xacab,  0xacbb,
+0xacca,  0xacd9,  0xace8,  0xacf7,  0xad06,  0xad16,
+0xad25,  0xad34,  0xad43,  0xad52,  0xad61,  0xad70,
+0xad80,  0xad8f,  0xad9e,  0xadad,  0xadbc,  0xadcb,
+0xadda,  0xade9,  0xadf8,  0xae08,  0xae17,  0xae26,
+0xae35,  0xae44,  0xae53,  0xae62,  0xae71,  0xae80,
+0xae8f,  0xae9e,  0xaead,  0xaebd,  0xaecc,  0xaedb,
+0xaeea,  0xaef9,  0xaf08,  0xaf17,  0xaf26,  0xaf35,
+0xaf44,  0xaf53,  0xaf62,  0xaf71,  0xaf80,  0xaf8f,
+0xaf9e,  0xafad,  0xafbc,  0xafcb,  0xafda,  0xafe9,
+0xaff8,  0xb007,  0xb016,  0xb025,  0xb034,  0xb043,
+0xb052,  0xb061,  0xb070,  0xb07f,  0xb08e,  0xb09d,
+0xb0ac,  0xb0bb,  0xb0ca,  0xb0d9,  0xb0e8,  0xb0f6,
+0xb105,  0xb114,  0xb123,  0xb132,  0xb141,  0xb150,
+0xb15f,  0xb16e,  0xb17d,  0xb18c,  0xb19b,  0xb1aa,
+0xb1b8,  0xb1c7,  0xb1d6,  0xb1e5,  0xb1f4,  0xb203,
+0xb212,  0xb221,  0xb22f,  0xb23e,  0xb24d,  0xb25c,
+0xb26b,  0xb27a,  0xb289,  0xb297,  0xb2a6,  0xb2b5,
+0xb2c4,  0xb2d3,  0xb2e2,  0xb2f1,  0xb2ff,  0xb30e,
+0xb31d,  0xb32c,  0xb33b,  0xb349,  0xb358,  0xb367,
+0xb376,  0xb385,  0xb393,  0xb3a2,  0xb3b1,  0xb3c0,
+0xb3cf,  0xb3dd,  0xb3ec,  0xb3fb,  0xb40a,  0xb418,
+0xb427,  0xb436,  0xb445,  0xb453,  0xb462,  0xb471,
+0xb480,  0xb48e,  0xb49d,  0xb4ac,  0xb4bb,  0xb4c9,
+0xb4d8,  0xb4e7,  0xb4f6,  0xb504,  0xb513,  0xb522,
+0xb530,  0xb53f,  0xb54e,  0xb55c,  0xb56b,  0xb57a,
+0xb588,  0xb597,  0xb5a6,  0xb5b5,  0xb5c3,  0xb5d2,
+0xb5e1,  0xb5ef,  0xb5fe,  0xb60d,  0xb61b,  0xb62a,
+0xb638,  0xb647,  0xb656,  0xb664,  0xb673,  0xb682,
+0xb690,  0xb69f,  0xb6ae,  0xb6bc,  0xb6cb,  0xb6d9,
+0xb6e8,  0xb6f7,  0xb705,  0xb714,  0xb722,  0xb731,
+0xb740,  0xb74e,  0xb75d,  0xb76b,  0xb77a,  0xb788,
+0xb797,  0xb7a6,  0xb7b4,  0xb7c3,  0xb7d1,  0xb7e0,
+0xb7ee,  0xb7fd,  0xb80b,  0xb81a,  0xb829,  0xb837,
+0xb846,  0xb854,  0xb863,  0xb871,  0xb880,  0xb88e,
+0xb89d,  0xb8ab,  0xb8ba,  0xb8c8,  0xb8d7,  0xb8e5,
+0xb8f4,  0xb902,  0xb911,  0xb91f,  0xb92e,  0xb93c,
+0xb94b,  0xb959,  0xb968,  0xb976,  0xb984,  0xb993,
+0xb9a1,  0xb9b0,  0xb9be,  0xb9cd,  0xb9db,  0xb9ea,
+0xb9f8,  0xba06,  0xba15,  0xba23,  0xba32,  0xba40,
+0xba4f,  0xba5d,  0xba6b,  0xba7a,  0xba88,  0xba97,
+0xbaa5,  0xbab3,  0xbac2,  0xbad0,  0xbade,  0xbaed,
+0xbafb,  0xbb0a,  0xbb18,  0xbb26,  0xbb35,  0xbb43,
+0xbb51,  0xbb60,  0xbb6e,  0xbb7c,  0xbb8b,  0xbb99,
+0xbba8,  0xbbb6,  0xbbc4,  0xbbd3,  0xbbe1,  0xbbef,
+0xbbfd,  0xbc0c,  0xbc1a,  0xbc28,  0xbc37,  0xbc45,
+0xbc53,  0xbc62,  0xbc70,  0xbc7e,  0xbc8c,  0xbc9b,
+0xbca9,  0xbcb7,  0xbcc6,  0xbcd4,  0xbce2,  0xbcf0,
+0xbcff,  0xbd0d,  0xbd1b,  0xbd29,  0xbd38,  0xbd46,
+0xbd54,  0xbd62,  0xbd71,  0xbd7f,  0xbd8d,  0xbd9b,
+0xbdaa,  0xbdb8,  0xbdc6,  0xbdd4,  0xbde2,  0xbdf1,
+0xbdff,  0xbe0d,  0xbe1b,  0xbe29,  0xbe38,  0xbe46,
+0xbe54,  0xbe62,  0xbe70,  0xbe7f,  0xbe8d,  0xbe9b,
+0xbea9,  0xbeb7,  0xbec5,  0xbed4,  0xbee2,  0xbef0,
+0xbefe,  0xbf0c,  0xbf1a,  0xbf28,  0xbf37,  0xbf45,
+0xbf53,  0xbf61,  0xbf6f,  0xbf7d,  0xbf8b,  0xbf99,
+0xbfa7,  0xbfb6,  0xbfc4,  0xbfd2,  0xbfe0,  0xbfee,
+0xbffc,  0xc00a,  0xc018,  0xc026,  0xc034,  0xc042,
+0xc051,  0xc05f,  0xc06d,  0xc07b,  0xc089,  0xc097,
+0xc0a5,  0xc0b3,  0xc0c1,  0xc0cf,  0xc0dd,  0xc0eb,
+0xc0f9,  0xc107,  0xc115,  0xc123,  0xc131,  0xc13f,
+0xc14d,  0xc15b,  0xc169,  0xc177,  0xc185,  0xc193,
+0xc1a1,  0xc1af,  0xc1bd,  0xc1cb,  0xc1d9,  0xc1e7,
+0xc1f5,  0xc203,  0xc211,  0xc21f,  0xc22d,  0xc23b,
+0xc249,  0xc257,  0xc265,  0xc273,  0xc281,  0xc28f,
+0xc29d,  0xc2ab,  0xc2b8,  0xc2c6,  0xc2d4,  0xc2e2,
+0xc2f0,  0xc2fe,  0xc30c,  0xc31a,  0xc328,  0xc336,
+0xc344,  0xc352,  0xc35f,  0xc36d,  0xc37b,  0xc389,
+0xc397,  0xc3a5,  0xc3b3,  0xc3c1,  0xc3ce,  0xc3dc,
+0xc3ea,  0xc3f8,  0xc406,  0xc414,  0xc422,  0xc42f,
+0xc43d,  0xc44b,  0xc459,  0xc467,  0xc475,  0xc482,
+0xc490,  0xc49e,  0xc4ac,  0xc4ba,  0xc4c7,  0xc4d5,
+0xc4e3,  0xc4f1,  0xc4ff,  0xc50d,  0xc51a,  0xc528,
+0xc536,  0xc544,  0xc551,  0xc55f,  0xc56d,  0xc57b,
+0xc589,  0xc596,  0xc5a4,  0xc5b2,  0xc5c0,  0xc5cd,
+0xc5db,  0xc5e9,  0xc5f7,  0xc604,  0xc612,  0xc620,
+0xc62d,  0xc63b,  0xc649,  0xc657,  0xc664,  0xc672,
+0xc680,  0xc68d,  0xc69b,  0xc6a9,  0xc6b7,  0xc6c4,
+0xc6d2,  0xc6e0,  0xc6ed,  0xc6fb,  0xc709,  0xc716,
+0xc724,  0xc732,  0xc73f,  0xc74d,  0xc75b,  0xc768,
+0xc776,  0xc784,  0xc791,  0xc79f,  0xc7ad,  0xc7ba,
+0xc7c8,  0xc7d6,  0xc7e3,  0xc7f1,  0xc7fe,  0xc80c,
+0xc81a,  0xc827,  0xc835,  0xc842,  0xc850,  0xc85e,
+0xc86b,  0xc879,  0xc886,  0xc894,  0xc8a2,  0xc8af,
+0xc8bd,  0xc8ca,  0xc8d8,  0xc8e5,  0xc8f3,  0xc901,
+0xc90e,  0xc91c,  0xc929,  0xc937,  0xc944,  0xc952,
+0xc95f,  0xc96d,  0xc97b,  0xc988,  0xc996,  0xc9a3,
+0xc9b1,  0xc9be,  0xc9cc,  0xc9d9,  0xc9e7,  0xc9f4,
+0xca02,  0xca0f,  0xca1d,  0xca2a,  0xca38,  0xca45,
+0xca53,  0xca60,  0xca6e,  0xca7b,  0xca89,  0xca96,
+0xcaa4,  0xcab1,  0xcabe,  0xcacc,  0xcad9,  0xcae7,
+0xcaf4,  0xcb02,  0xcb0f,  0xcb1d,  0xcb2a,  0xcb37,
+0xcb45,  0xcb52,  0xcb60,  0xcb6d,  0xcb7b,  0xcb88,
+0xcb95,  0xcba3,  0xcbb0,  0xcbbe,  0xcbcb,  0xcbd8,
+0xcbe6,  0xcbf3,  0xcc01,  0xcc0e,  0xcc1b,  0xcc29,
+0xcc36,  0xcc43,  0xcc51,  0xcc5e,  0xcc6c,  0xcc79,
+0xcc86,  0xcc94,  0xcca1,  0xccae,  0xccbc,  0xccc9,
+0xccd6,  0xcce4,  0xccf1,  0xccfe,  0xcd0c,  0xcd19,
+0xcd26,  0xcd34,  0xcd41,  0xcd4e,  0xcd5b,  0xcd69,
+0xcd76,  0xcd83,  0xcd91,  0xcd9e,  0xcdab,  0xcdb9,
+0xcdc6,  0xcdd3,  0xcde0,  0xcdee,  0xcdfb,  0xce08,
+0xce15,  0xce23,  0xce30,  0xce3d,  0xce4a,  0xce58,
+0xce65,  0xce72,  0xce7f,  0xce8d,  0xce9a,  0xcea7,
+0xceb4,  0xcec2,  0xcecf,  0xcedc,  0xcee9,  0xcef6,
+0xcf04,  0xcf11,  0xcf1e,  0xcf2b,  0xcf38,  0xcf46,
+0xcf53,  0xcf60,  0xcf6d,  0xcf7a,  0xcf87,  0xcf95,
+0xcfa2,  0xcfaf,  0xcfbc,  0xcfc9,  0xcfd6,  0xcfe4,
+0xcff1,  0xcffe,  0xd00b,  0xd018,  0xd025,  0xd032,
+0xd040,  0xd04d,  0xd05a,  0xd067,  0xd074,  0xd081,
+0xd08e,  0xd09b,  0xd0a9,  0xd0b6,  0xd0c3,  0xd0d0,
+0xd0dd,  0xd0ea,  0xd0f7,  0xd104,  0xd111,  0xd11e,
+0xd12b,  0xd139,  0xd146,  0xd153,  0xd160,  0xd16d,
+0xd17a,  0xd187,  0xd194,  0xd1a1,  0xd1ae,  0xd1bb,
+0xd1c8,  0xd1d5,  0xd1e2,  0xd1ef,  0xd1fc,  0xd209,
+0xd216,  0xd223,  0xd230,  0xd23d,  0xd24a,  0xd257,
+0xd264,  0xd271,  0xd27e,  0xd28b,  0xd298,  0xd2a5,
+0xd2b2,  0xd2bf,  0xd2cc,  0xd2d9,  0xd2e6,  0xd2f3,
+0xd300,  0xd30d,  0xd31a,  0xd327,  0xd334,  0xd341,
+0xd34e,  0xd35b,  0xd368,  0xd375,  0xd382,  0xd38f,
+0xd39c,  0xd3a8,  0xd3b5,  0xd3c2,  0xd3cf,  0xd3dc,
+0xd3e9,  0xd3f6,  0xd403,  0xd410,  0xd41d,  0xd42a,
+0xd436,  0xd443,  0xd450,  0xd45d,  0xd46a,  0xd477,
+0xd484,  0xd491,  0xd49e,  0xd4aa,  0xd4b7,  0xd4c4,
+0xd4d1,  0xd4de,  0xd4eb,  0xd4f8,  0xd504,  0xd511,
+0xd51e,  0xd52b,  0xd538,  0xd545,  0xd551,  0xd55e,
+0xd56b,  0xd578,  0xd585,  0xd591,  0xd59e,  0xd5ab,
+0xd5b8,  0xd5c5,  0xd5d1,  0xd5de,  0xd5eb,  0xd5f8,
+0xd605,  0xd611,  0xd61e,  0xd62b,  0xd638,  0xd645,
+0xd651,  0xd65e,  0xd66b,  0xd678,  0xd684,  0xd691,
+0xd69e,  0xd6ab,  0xd6b7,  0xd6c4,  0xd6d1,  0xd6de,
+0xd6ea,  0xd6f7,  0xd704,  0xd710,  0xd71d,  0xd72a,
+0xd737,  0xd743,  0xd750,  0xd75d,  0xd769,  0xd776,
+0xd783,  0xd78f,  0xd79c,  0xd7a9,  0xd7b6,  0xd7c2,
+0xd7cf,  0xd7dc,  0xd7e8,  0xd7f5,  0xd802,  0xd80e,
+0xd81b,  0xd828,  0xd834,  0xd841,  0xd84e,  0xd85a,
+0xd867,  0xd873,  0xd880,  0xd88d,  0xd899,  0xd8a6,
+0xd8b3,  0xd8bf,  0xd8cc,  0xd8d8,  0xd8e5,  0xd8f2,
+0xd8fe,  0xd90b,  0xd917,  0xd924,  0xd931,  0xd93d,
+0xd94a,  0xd956,  0xd963,  0xd970,  0xd97c,  0xd989,
+0xd995,  0xd9a2,  0xd9ae,  0xd9bb,  0xd9c8,  0xd9d4,
+0xd9e1,  0xd9ed,  0xd9fa,  0xda06,  0xda13,  0xda1f,
+0xda2c,  0xda38,  0xda45,  0xda51,  0xda5e,  0xda6a,
+0xda77,  0xda84,  0xda90,  0xda9d,  0xdaa9,  0xdab6,
+0xdac2,  0xdacf,  0xdadb,  0xdae7,  0xdaf4,  0xdb00,
+0xdb0d,  0xdb19,  0xdb26,  0xdb32,  0xdb3f,  0xdb4b,
+0xdb58,  0xdb64,  0xdb71,  0xdb7d,  0xdb8a,  0xdb96,
+0xdba2,  0xdbaf,  0xdbbb,  0xdbc8,  0xdbd4,  0xdbe1,
+0xdbed,  0xdbf9,  0xdc06,  0xdc12,  0xdc1f,  0xdc2b,
+0xdc38,  0xdc44,  0xdc50,  0xdc5d,  0xdc69,  0xdc76,
+0xdc82,  0xdc8e,  0xdc9b,  0xdca7,  0xdcb3,  0xdcc0,
+0xdccc,  0xdcd9,  0xdce5,  0xdcf1,  0xdcfe,  0xdd0a,
+0xdd16,  0xdd23,  0xdd2f,  0xdd3b,  0xdd48,  0xdd54,
+0xdd60,  0xdd6d,  0xdd79,  0xdd85,  0xdd92,  0xdd9e,
+0xddaa,  0xddb7,  0xddc3,  0xddcf,  0xdddc,  0xdde8,
+0xddf4,  0xde01,  0xde0d,  0xde19,  0xde25,  0xde32,
+0xde3e,  0xde4a,  0xde57,  0xde63,  0xde6f,  0xde7b,
+0xde88,  0xde94,  0xdea0,  0xdeac,  0xdeb9,  0xdec5,
+0xded1,  0xdedd,  0xdeea,  0xdef6,  0xdf02,  0xdf0e,
+0xdf1b,  0xdf27,  0xdf33,  0xdf3f,  0xdf4c,  0xdf58,
+0xdf64,  0xdf70,  0xdf7c,  0xdf89,  0xdf95,  0xdfa1,
+0xdfad,  0xdfb9,  0xdfc6,  0xdfd2,  0xdfde,  0xdfea,
+0xdff6,  0xe003,  0xe00f,  0xe01b,  0xe027,  0xe033,
+0xe03f,  0xe04c,  0xe058,  0xe064,  0xe070,  0xe07c,
+0xe088,  0xe094,  0xe0a1,  0xe0ad,  0xe0b9,  0xe0c5,
+0xe0d1,  0xe0dd,  0xe0e9,  0xe0f5,  0xe102,  0xe10e,
+0xe11a,  0xe126,  0xe132,  0xe13e,  0xe14a,  0xe156,
+0xe162,  0xe16e,  0xe17b,  0xe187,  0xe193,  0xe19f,
+0xe1ab,  0xe1b7,  0xe1c3,  0xe1cf,  0xe1db,  0xe1e7,
+0xe1f3,  0xe1ff,  0xe20b,  0xe217,  0xe223,  0xe22f,
+0xe23c,  0xe248,  0xe254,  0xe260,  0xe26c,  0xe278,
+0xe284,  0xe290,  0xe29c,  0xe2a8,  0xe2b4,  0xe2c0,
+0xe2cc,  0xe2d8,  0xe2e4,  0xe2f0,  0xe2fc,  0xe308,
+0xe314,  0xe320,  0xe32c,  0xe338,  0xe344,  0xe350,
+0xe35c,  0xe368,  0xe374,  0xe380,  0xe38b,  0xe397,
+0xe3a3,  0xe3af,  0xe3bb,  0xe3c7,  0xe3d3,  0xe3df,
+0xe3eb,  0xe3f7,  0xe403,  0xe40f,  0xe41b,  0xe427,
+0xe433,  0xe43f,  0xe44a,  0xe456,  0xe462,  0xe46e,
+0xe47a,  0xe486,  0xe492,  0xe49e,  0xe4aa,  0xe4b6,
+0xe4c1,  0xe4cd,  0xe4d9,  0xe4e5,  0xe4f1,  0xe4fd,
+0xe509,  0xe515,  0xe520,  0xe52c,  0xe538,  0xe544,
+0xe550,  0xe55c,  0xe567,  0xe573,  0xe57f,  0xe58b,
+0xe597,  0xe5a3,  0xe5af,  0xe5ba,  0xe5c6,  0xe5d2,
+0xe5de,  0xe5ea,  0xe5f5,  0xe601,  0xe60d,  0xe619,
+0xe625,  0xe630,  0xe63c,  0xe648,  0xe654,  0xe660,
+0xe66b,  0xe677,  0xe683,  0xe68f,  0xe69a,  0xe6a6,
+0xe6b2,  0xe6be,  0xe6ca,  0xe6d5,  0xe6e1,  0xe6ed,
+0xe6f9,  0xe704,  0xe710,  0xe71c,  0xe727,  0xe733,
+0xe73f,  0xe74b,  0xe756,  0xe762,  0xe76e,  0xe77a,
+0xe785,  0xe791,  0xe79d,  0xe7a8,  0xe7b4,  0xe7c0,
+0xe7cb,  0xe7d7,  0xe7e3,  0xe7ef,  0xe7fa,  0xe806,
+0xe812,  0xe81d,  0xe829,  0xe835,  0xe840,  0xe84c,
+0xe858,  0xe863,  0xe86f,  0xe87b,  0xe886,  0xe892,
+0xe89e,  0xe8a9,  0xe8b5,  0xe8c0,  0xe8cc,  0xe8d8,
+0xe8e3,  0xe8ef,  0xe8fb,  0xe906,  0xe912,  0xe91d,
+0xe929,  0xe935,  0xe940,  0xe94c,  0xe958,  0xe963,
+0xe96f,  0xe97a,  0xe986,  0xe991,  0xe99d,  0xe9a9,
+0xe9b4,  0xe9c0,  0xe9cb,  0xe9d7,  0xe9e3,  0xe9ee,
+0xe9fa,  0xea05,  0xea11,  0xea1c,  0xea28,  0xea33,
+0xea3f,  0xea4a,  0xea56,  0xea62,  0xea6d,  0xea79,
+0xea84,  0xea90,  0xea9b,  0xeaa7,  0xeab2,  0xeabe,
+0xeac9,  0xead5,  0xeae0,  0xeaec,  0xeaf7,  0xeb03,
+0xeb0e,  0xeb1a,  0xeb25,  0xeb31,  0xeb3c,  0xeb48,
+0xeb53,  0xeb5f,  0xeb6a,  0xeb76,  0xeb81,  0xeb8d,
+0xeb98,  0xeba3,  0xebaf,  0xebba,  0xebc6,  0xebd1,
+0xebdd,  0xebe8,  0xebf4,  0xebff,  0xec0a,  0xec16,
+0xec21,  0xec2d,  0xec38,  0xec44,  0xec4f,  0xec5a,
+0xec66,  0xec71,  0xec7d,  0xec88,  0xec93,  0xec9f,
+0xecaa,  0xecb6,  0xecc1,  0xeccc,  0xecd8,  0xece3,
+0xecef,  0xecfa,  0xed05,  0xed11,  0xed1c,  0xed27,
+0xed33,  0xed3e,  0xed4a,  0xed55,  0xed60,  0xed6c,
+0xed77,  0xed82,  0xed8e,  0xed99,  0xeda4,  0xedb0,
+0xedbb,  0xedc6,  0xedd2,  0xeddd,  0xede8,  0xedf4,
+0xedff,  0xee0a,  0xee15,  0xee21,  0xee2c,  0xee37,
+0xee43,  0xee4e,  0xee59,  0xee65,  0xee70,  0xee7b,
+0xee86,  0xee92,  0xee9d,  0xeea8,  0xeeb3,  0xeebf,
+0xeeca,  0xeed5,  0xeee1,  0xeeec,  0xeef7,  0xef02,
+0xef0e,  0xef19,  0xef24,  0xef2f,  0xef3a,  0xef46,
+0xef51,  0xef5c,  0xef67,  0xef73,  0xef7e,  0xef89,
+0xef94,  0xef9f,  0xefab,  0xefb6,  0xefc1,  0xefcc,
+0xefd7,  0xefe3,  0xefee,  0xeff9,  0xf004,  0xf00f,
+0xf01b,  0xf026,  0xf031,  0xf03c,  0xf047,  0xf052,
+0xf05e,  0xf069,  0xf074,  0xf07f,  0xf08a,  0xf095,
+0xf0a1,  0xf0ac,  0xf0b7,  0xf0c2,  0xf0cd,  0xf0d8,
+0xf0e3,  0xf0ef,  0xf0fa,  0xf105,  0xf110,  0xf11b,
+0xf126,  0xf131,  0xf13c,  0xf147,  0xf153,  0xf15e,
+0xf169,  0xf174,  0xf17f,  0xf18a,  0xf195,  0xf1a0,
+0xf1ab,  0xf1b6,  0xf1c2,  0xf1cd,  0xf1d8,  0xf1e3,
+0xf1ee,  0xf1f9,  0xf204,  0xf20f,  0xf21a,  0xf225,
+0xf230,  0xf23b,  0xf246,  0xf251,  0xf25c,  0xf267,
+0xf272,  0xf27d,  0xf288,  0xf293,  0xf29f,  0xf2aa,
+0xf2b5,  0xf2c0,  0xf2cb,  0xf2d6,  0xf2e1,  0xf2ec,
+0xf2f7,  0xf302,  0xf30d,  0xf318,  0xf323,  0xf32e,
+0xf339,  0xf344,  0xf34f,  0xf35a,  0xf364,  0xf36f,
+0xf37a,  0xf385,  0xf390,  0xf39b,  0xf3a6,  0xf3b1,
+0xf3bc,  0xf3c7,  0xf3d2,  0xf3dd,  0xf3e8,  0xf3f3,
+0xf3fe,  0xf409,  0xf414,  0xf41f,  0xf42a,  0xf435,
+0xf43f,  0xf44a,  0xf455,  0xf460,  0xf46b,  0xf476,
+0xf481,  0xf48c,  0xf497,  0xf4a2,  0xf4ad,  0xf4b7,
+0xf4c2,  0xf4cd,  0xf4d8,  0xf4e3,  0xf4ee,  0xf4f9,
+0xf504,  0xf50f,  0xf519,  0xf524,  0xf52f,  0xf53a,
+0xf545,  0xf550,  0xf55b,  0xf565,  0xf570,  0xf57b,
+0xf586,  0xf591,  0xf59c,  0xf5a6,  0xf5b1,  0xf5bc,
+0xf5c7,  0xf5d2,  0xf5dd,  0xf5e7,  0xf5f2,  0xf5fd,
+0xf608,  0xf613,  0xf61d,  0xf628,  0xf633,  0xf63e,
+0xf649,  0xf653,  0xf65e,  0xf669,  0xf674,  0xf67f,
+0xf689,  0xf694,  0xf69f,  0xf6aa,  0xf6b4,  0xf6bf,
+0xf6ca,  0xf6d5,  0xf6e0,  0xf6ea,  0xf6f5,  0xf700,
+0xf70b,  0xf715,  0xf720,  0xf72b,  0xf736,  0xf740,
+0xf74b,  0xf756,  0xf760,  0xf76b,  0xf776,  0xf781,
+0xf78b,  0xf796,  0xf7a1,  0xf7ab,  0xf7b6,  0xf7c1,
+0xf7cc,  0xf7d6,  0xf7e1,  0xf7ec,  0xf7f6,  0xf801,
+0xf80c,  0xf816,  0xf821,  0xf82c,  0xf836,  0xf841,
+0xf84c,  0xf856,  0xf861,  0xf86c,  0xf876,  0xf881,
+0xf88c,  0xf896,  0xf8a1,  0xf8ac,  0xf8b6,  0xf8c1,
+0xf8cc,  0xf8d6,  0xf8e1,  0xf8ec,  0xf8f6,  0xf901,
+0xf90b,  0xf916,  0xf921,  0xf92b,  0xf936,  0xf941,
+0xf94b,  0xf956,  0xf960,  0xf96b,  0xf976,  0xf980,
+0xf98b,  0xf995,  0xf9a0,  0xf9aa,  0xf9b5,  0xf9c0,
+0xf9ca,  0xf9d5,  0xf9df,  0xf9ea,  0xf9f4,  0xf9ff,
+0xfa0a,  0xfa14,  0xfa1f,  0xfa29,  0xfa34,  0xfa3e,
+0xfa49,  0xfa53,  0xfa5e,  0xfa69,  0xfa73,  0xfa7e,
+0xfa88,  0xfa93,  0xfa9d,  0xfaa8,  0xfab2,  0xfabd,
+0xfac7,  0xfad2,  0xfadc,  0xfae7,  0xfaf1,  0xfafc,
+0xfb06,  0xfb11,  0xfb1b,  0xfb26,  0xfb30,  0xfb3b,
+0xfb45,  0xfb50,  0xfb5a,  0xfb65,  0xfb6f,  0xfb7a,
+0xfb84,  0xfb8f,  0xfb99,  0xfba4,  0xfbae,  0xfbb8,
+0xfbc3,  0xfbcd,  0xfbd8,  0xfbe2,  0xfbed,  0xfbf7,
+0xfc02,  0xfc0c,  0xfc16,  0xfc21,  0xfc2b,  0xfc36,
+0xfc40,  0xfc4b,  0xfc55,  0xfc5f,  0xfc6a,  0xfc74,
+0xfc7f,  0xfc89,  0xfc93,  0xfc9e,  0xfca8,  0xfcb3,
+0xfcbd,  0xfcc7,  0xfcd2,  0xfcdc,  0xfce7,  0xfcf1,
+0xfcfb,  0xfd06,  0xfd10,  0xfd1a,  0xfd25,  0xfd2f,
+0xfd3a,  0xfd44,  0xfd4e,  0xfd59,  0xfd63,  0xfd6d,
+0xfd78,  0xfd82,  0xfd8c,  0xfd97,  0xfda1,  0xfdab,
+0xfdb6,  0xfdc0,  0xfdca,  0xfdd5,  0xfddf,  0xfde9,
+0xfdf4,  0xfdfe,  0xfe08,  0xfe13,  0xfe1d,  0xfe27,
+0xfe32,  0xfe3c,  0xfe46,  0xfe50,  0xfe5b,  0xfe65,
+0xfe6f,  0xfe7a,  0xfe84,  0xfe8e,  0xfe98,  0xfea3,
+0xfead,  0xfeb7,  0xfec1,  0xfecc,  0xfed6,  0xfee0,
+0xfeeb,  0xfef5,  0xfeff,  0xff09,  0xff14,  0xff1e,
+0xff28,  0xff32,  0xff3c,  0xff47,  0xff51,  0xff5b,
+0xff65,  0xff70,  0xff7a,  0xff84,  0xff8e,  0xff98,
+0xffa3,  0xffad,  0xffb7,  0xffc1,  0xffcc,  0xffd6,
+0xffe0,  0xffea,  0xfff4,  0xffff
+};
+
+// max value is pi/4
+constexpr double SCALING_FACTOR = 4. / M_PI * 0xFFFF;
+
+inline double atan2_lookup(double y, double x)
+{
+    if (std::abs(x) < std::numeric_limits<double>::epsilon())
+    {
+        if (y >= 0.)
+        {
+            return M_PI / 2.;
+        }
+        else
+        {
+            return -M_PI / 2.;
+        }
+    }
+
+    unsigned octant = 0;
+
+    if (x < 0.)
+    {
+        octant = 1;
+        x = -x;
+    }
+    if (y < 0.)
+    {
+        octant |= 2;
+        y = -y;
+    }
+
+    double t = y / x;
+    if (t > 1.0)
+    {
+        octant |= 4;
+        t = 1.0 / t;
+    }
+
+    double angle = atan_table[(unsigned)(t * 4095)] / SCALING_FACTOR;
+
+    switch (octant)
+    {
+    case 0:
+        break;
+    case 1:
+        angle = M_PI - angle;
+        break;
+    case 2:
+        angle = -angle;
+        break;
+    case 3:
+        angle = -M_PI + angle;
+        break;
+    case 4:
+        angle = M_PI / 2.0 - angle;
+        break;
+    case 5:
+        angle = M_PI / 2.0 + angle;
+        break;
+    case 6:
+        angle = -M_PI / 2.0 + angle;
+        break;
+    case 7:
+        angle = -M_PI / 2.0 - angle;
+        break;
+    }
+    return angle;
+}
+
+#endif // TRIGONOMETRY_TABLES_H
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..7d6f835
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,67 @@
+environment:
+  matrix:
+  - configuration: Debug
+  - configuration: Release
+
+# branches to build
+branches:
+  # whitelist
+  only:
+    - develop
+
+# Operating system (build VM template)
+os: Windows Server 2012 R2
+
+# scripts that are called at very beginning, before repo cloning
+init:
+  - git config --global core.autocrlf input
+
+# clone directory
+clone_folder: c:\projects\osrm
+
+platform: x64
+
+install:
+  # by default, all script lines are interpreted as batch
+  - cd c:\projects\osrm
+  - curl -O http://build.project-osrm.org/libs_osrm_%Configuration%.7z
+  - 7z x libs_osrm_%Configuration%.7z | find ":"
+
+build_script:
+  - cd c:/projects/osrm
+  - mkdir build
+  - cd build
+  - echo Running cmake...
+  - call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64
+  - SET P=c:/projects/osrm
+  - set TBB_INSTALL_DIR=%P%/tbb
+  - set TBB_ARCH_PLATFORM=intel64/vc12
+  - cmake .. -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=%Configuration% -DBZIP2_INCLUDE_DIR=%P%/libs/include -DBZIP2_LIBRARIES=%P%/libs/lib/libbz2.lib -DCMAKE_INSTALL_PREFIX=%P%/libs -DBOOST_ROOT=%P%/boost_min -DBoost_USE_STATIC_LIBS=ON
+  - nmake
+  - if "%APPVEYOR_REPO_BRANCH%"=="develop" (7z a %P%/osrm_%Configuration%.zip *.exe *.pdb %P%/libs/bin/*.dll -tzip)
+
+test: off
+
+artifacts:
+  - path: osrm_Debug.zip
+    name: osrm_Debug.zip
+  - path: osrm_Release.zip
+    name: osrm_Release.zip
+
+deploy:
+  provider: FTP
+  server:
+    secure: ef7oiQTTXFGt8NdNiOHm/uRFVrUttzyFbIlnaeHhQvw=
+  username:
+    secure: Bw+Se2GTJxA6+GtRkEc//tQSBHOuFIuJHBjFwR9cD+8=
+  password:
+    secure: eqwESZqxMXC/j5mOCpaXuw==
+  folder: /
+  enable_ssl: true
+  active_mode: false
+
+# notifications:
+#   - provider: HipChat
+#     auth_token:
+#       secure: boLE7BjcahdIUxv9jkN7U3F8iOASF+MkhtctlVoWJoo=
+#     room: Directions
diff --git a/cmake/CheckCXXCompilerFlag.cmake b/cmake/CheckCXXCompilerFlag.cmake
new file mode 100644
index 0000000..e396f75
--- /dev/null
+++ b/cmake/CheckCXXCompilerFlag.cmake
@@ -0,0 +1,29 @@
+# - Check whether the CXX compiler supports a given flag.
+# CHECK_CXX_COMPILER_FLAG(<flag> <var>)
+#  <flag> - the compiler flag
+#  <var>  - variable to store the result
+# This internally calls the check_cxx_source_compiles macro.  See help
+# for CheckCXXSourceCompiles for a listing of variables that can
+# modify the build.
+
+# Copyright (c) 2006, Alexander Neundorf, <neundorf at kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+
+INCLUDE(CheckCXXSourceCompiles)
+
+MACRO (CHECK_CXX_COMPILER_FLAG _FLAG _RESULT)
+   SET(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
+   SET(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
+   CHECK_CXX_SOURCE_COMPILES("int main() { return 0;}" ${_RESULT}
+     # Some compilers do not fail with a bad flag
+     FAIL_REGEX "unrecognized .*option"                     # GNU
+     FAIL_REGEX "ignoring unknown option"                   # MSVC
+     FAIL_REGEX "[Uu]nknown option"                         # HP
+     FAIL_REGEX "[Ww]arning: [Oo]ption"                     # SunPro
+     FAIL_REGEX "command option .* is not recognized"       # XL
+     )
+   SET (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
+ENDMACRO (CHECK_CXX_COMPILER_FLAG)
diff --git a/cmake/FindLua52.cmake b/cmake/FindLua52.cmake
new file mode 100644
index 0000000..d17fbf6
--- /dev/null
+++ b/cmake/FindLua52.cmake
@@ -0,0 +1,82 @@
+# Locate Lua library
+# This module defines
+#  LUA52_FOUND, if false, do not try to link to Lua
+#  LUA_LIBRARIES
+#  LUA_INCLUDE_DIR, where to find lua.h
+#  LUA_VERSION_STRING, the version of Lua found (since CMake 2.8.8)
+#
+# Note that the expected include convention is
+#  #include "lua.h"
+# and not
+#  #include <lua/lua.h>
+# This is because, the lua location is not standardized and may exist
+# in locations other than lua/
+
+#=============================================================================
+# Copyright 2007-2009 Kitware, Inc.
+# Copyright 2013 for Project-OSRM, Lua5.1 => Lua5.2
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+find_path(LUA_INCLUDE_DIR lua.h
+  HINTS
+    ENV LUA_DIR
+  PATH_SUFFIXES include/lua52 include/lua5.2 include/lua-5.2 include/lua include
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /sw # Fink
+  /opt/local # DarwinPorts
+  /opt/csw # Blastwave
+  /opt
+)
+
+find_library(LUA_LIBRARY
+  NAMES lua52 lua5.2 lua-5.2 lua
+  HINTS
+    ENV LUA_DIR
+  PATH_SUFFIXES lib
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /sw
+  /opt/local
+  /opt/csw
+  /opt
+)
+
+if(LUA_LIBRARY)
+  # include the math library for Unix
+  if(UNIX AND NOT APPLE AND NOT BEOS)
+    find_library(LUA_MATH_LIBRARY m)
+    set( LUA_LIBRARIES "${LUA_LIBRARY};${LUA_MATH_LIBRARY}" CACHE STRING "Lua Libraries")
+  # For Windows and Mac, don't need to explicitly include the math library
+  else()
+    set( LUA_LIBRARIES "${LUA_LIBRARY}" CACHE STRING "Lua Libraries")
+  endif()
+endif()
+
+if(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/lua.h")
+  file(STRINGS "${LUA_INCLUDE_DIR}/lua.h" lua_version_str REGEX "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua .+\"")
+
+  string(REGEX REPLACE "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([^\"]+)\".*" "\\1" LUA_VERSION_STRING "${lua_version_str}")
+  unset(lua_version_str)
+endif()
+
+include(FindPackageHandleStandardArgs)
+# handle the QUIETLY and REQUIRED arguments and set LUA_FOUND to TRUE if
+# all listed variables are TRUE
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lua52
+                                  REQUIRED_VARS LUA_LIBRARIES LUA_INCLUDE_DIR
+                                  VERSION_VAR LUA_VERSION_STRING)
+
+mark_as_advanced(LUA_INCLUDE_DIR LUA_LIBRARIES LUA_LIBRARY LUA_MATH_LIBRARY)
+
diff --git a/cmake/FindLuaJIT.cmake b/cmake/FindLuaJIT.cmake
new file mode 100644
index 0000000..5d5e6ac
--- /dev/null
+++ b/cmake/FindLuaJIT.cmake
@@ -0,0 +1,93 @@
+# Locate Lua library
+# This module defines
+#  LUAJIT_FOUND, if false, do not try to link to Lua
+#  LUAJIT_LIBRARIES
+#  LUAJIT_INCLUDE_DIR, where to find lua.h
+#
+# Note that the expected include convention is
+#  #include "lua.h"
+# and not
+#  #include <lua/lua.h>
+# This is because, the lua location is not standardized and may exist
+# in locations other than lua/
+
+#=============================================================================
+# Copyright 2007-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distributed this file outside of CMake, substitute the full
+#  License text for the above reference.)
+#
+# ################
+# 2010 - modified for cronkite to find luajit instead of lua, as it was before.
+#
+
+if ( NOT LuaJIT_FIND_VERSION )
+  MESSAGE(FATAL_ERROR "You need to specify a version of libluajit to use")
+ENDIF()
+
+IF( NOT LUAJIT_FIND_QUIETLY )
+  MESSAGE(STATUS "Looking for LuaJIT ${LuaJIT_FIND_VERSION}")
+ENDIF()
+
+FIND_PATH(LUAJIT_INCLUDE_DIR lua.h
+  HINTS
+  $ENV{LUAJIT_DIR}
+  PATH_SUFFIXES include/luajit-2.0 include/luajit2.0 include/luajit include
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw # Fink
+  /opt/local # DarwinPorts
+  /opt/csw # Blastwave
+  /opt
+)
+
+FIND_LIBRARY(LUAJIT_LIBRARY
+  NAMES luajit-${LuaJIT_FIND_VERSION_MAJOR}${LuaJIT_FIND_VERSION_MINOR} luajit-${LuaJIT_FIND_VERSION}
+  HINTS
+  $ENV{LUAJIT_DIR}
+  PATH_SUFFIXES lib64 lib
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw
+  /opt/local
+  /opt/csw
+  /opt
+)
+
+IF(LUAJIT_LIBRARY)
+  # include the math library for Unix
+  IF(UNIX AND NOT APPLE)
+    FIND_LIBRARY(LUAJIT_MATH_LIBRARY m)
+    SET( LUAJIT_LIBRARIES "${LUAJIT_LIBRARY};${LUAJIT_MATH_LIBRARY}" CACHE STRING "Lua Libraries")
+  # For Windows and Mac, don't need to explicitly include the math library
+  ELSE(UNIX AND NOT APPLE)
+    SET( LUAJIT_LIBRARIES "${LUAJIT_LIBRARY}" CACHE STRING "Lua Libraries")
+  ENDIF(UNIX AND NOT APPLE)
+ENDIF(LUAJIT_LIBRARY)
+
+INCLUDE(FindPackageHandleStandardArgs)
+# handle the QUIETLY and REQUIRED arguments and set LUAJIT_FOUND to TRUE if
+# all listed variables are TRUE
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LUAJIT  DEFAULT_MSG  LUAJIT_LIBRARIES LUAJIT_INCLUDE_DIR)
+
+IF( NOT LUAJIT_FIND_QUIETLY )
+  IF( LUAJIT_FOUND AND LUAJIT_LIBRARIES)
+    MESSAGE(STATUS "Found LuaJIT: ${LUAJIT_LIBRARY}" )
+    MARK_AS_ADVANCED(LUAJIT_INCLUDE_DIR LUAJIT_LIBRARIES LUAJIT_LIBRARY LUAJIT_MATH_LIBRARY)
+  ELSE()
+    SET ( LUAJIT_FOUND FALSE )
+  ENDIF()
+ENDIF()
diff --git a/cmake/FindLuabind.cmake b/cmake/FindLuabind.cmake
index 39b3250..4b99b3c 100644
--- a/cmake/FindLuabind.cmake
+++ b/cmake/FindLuabind.cmake
@@ -27,7 +27,7 @@ FIND_PATH(LUABIND_INCLUDE_DIR luabind.hpp
 )
 
 FIND_LIBRARY(LUABIND_LIBRARY
-  NAMES luabind
+  NAMES luabind luabind09
   HINTS
   $ENV{LUABIND_DIR}
   PATH_SUFFIXES lib64 lib
@@ -72,4 +72,4 @@ IF( NOT LUABIND_FIND_QUIETLY )
     ENDIF()
 ENDIF()
 
-MARK_AS_ADVANCED(LUABIND_INCLUDE_DIR LUABIND_LIBRARIES LUABIND_LIBRARY LUABIND_LIBRARY_DBG) 
+MARK_AS_ADVANCED(LUABIND_INCLUDE_DIR LUABIND_LIBRARIES LUABIND_LIBRARY LUABIND_LIBRARY_DBG)
diff --git a/cmake/FindSTXXL.cmake b/cmake/FindSTXXL.cmake
index 52d508c..76a2722 100644
--- a/cmake/FindSTXXL.cmake
+++ b/cmake/FindSTXXL.cmake
@@ -48,4 +48,4 @@ IF( NOT STXXL_FIND_QUIETLY )
     ENDIF()
 ENDIF()
 
-MARK_AS_ADVANCED(STXXL_INCLUDE_DIR STXXL_LIBRARY) 
+MARK_AS_ADVANCED(STXXL_INCLUDE_DIR STXXL_LIBRARY)
diff --git a/cmake/FindTBB.cmake b/cmake/FindTBB.cmake
new file mode 100644
index 0000000..f9e3e0f
--- /dev/null
+++ b/cmake/FindTBB.cmake
@@ -0,0 +1,283 @@
+# Locate Intel Threading Building Blocks include paths and libraries
+# FindTBB.cmake can be found at https://code.google.com/p/findtbb/
+# Written by Hannes Hofmann <hannes.hofmann _at_ informatik.uni-erlangen.de>
+# Improvements by Gino van den Bergen <gino _at_ dtecta.com>,
+#   Florian Uhlig <F.Uhlig _at_ gsi.de>,
+#   Jiri Marsik <jiri.marsik89 _at_ gmail.com>
+
+# The MIT License
+#
+# Copyright (c) 2011 Hannes Hofmann
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+# GvdB: This module uses the environment variable TBB_ARCH_PLATFORM which defines architecture and compiler.
+#   e.g. "ia32/vc8" or "em64t/cc4.1.0_libc2.4_kernel2.6.16.21"
+#   TBB_ARCH_PLATFORM is set by the build script tbbvars[.bat|.sh|.csh], which can be found
+#   in the TBB installation directory (TBB_INSTALL_DIR).
+#
+# GvdB: Mac OS X distribution places libraries directly in lib directory.
+#
+# For backwards compatibility, you may explicitely set the CMake variables TBB_ARCHITECTURE and TBB_COMPILER.
+# TBB_ARCHITECTURE [ ia32 | em64t | itanium ]
+#   which architecture to use
+# TBB_COMPILER e.g. vc9 or cc3.2.3_libc2.3.2_kernel2.4.21 or cc4.0.1_os10.4.9
+#   which compiler to use (detected automatically on Windows)
+
+# This module respects
+# TBB_INSTALL_DIR or $ENV{TBB21_INSTALL_DIR} or $ENV{TBB_INSTALL_DIR}
+
+# This module defines
+# TBB_INCLUDE_DIRS, where to find task_scheduler_init.h, etc.
+# TBB_LIBRARY_DIRS, where to find libtbb, libtbbmalloc
+# TBB_DEBUG_LIBRARY_DIRS, where to find libtbb_debug, libtbbmalloc_debug
+# TBB_INSTALL_DIR, the base TBB install directory
+# TBB_LIBRARIES, the libraries to link against to use TBB.
+# TBB_DEBUG_LIBRARIES, the libraries to link against to use TBB with debug symbols.
+# TBB_FOUND, If false, don't try to use TBB.
+# TBB_INTERFACE_VERSION, as defined in tbb/tbb_stddef.h
+
+
+if (WIN32)
+    # has em64t/vc8 em64t/vc9
+    # has ia32/vc7.1 ia32/vc8 ia32/vc9
+    set(_TBB_DEFAULT_INSTALL_DIR "C:/Program Files/Intel/TBB" "C:/Program Files (x86)/Intel/TBB")
+    set(_TBB_LIB_NAME "tbb")
+    set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc")
+    set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug")
+    set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug")
+    if (MSVC71)
+        set (_TBB_COMPILER "vc7.1")
+    endif(MSVC71)
+    if (MSVC80)
+        set(_TBB_COMPILER "vc8")
+    endif(MSVC80)
+    if (MSVC90)
+        set(_TBB_COMPILER "vc9")
+    endif(MSVC90)
+    if(MSVC10)
+        set(_TBB_COMPILER "vc10")
+    endif(MSVC10)
+    # Todo: add other Windows compilers such as ICL.
+    set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE})
+endif (WIN32)
+
+if (UNIX)
+    if (APPLE)
+        # MAC
+        set(_TBB_DEFAULT_INSTALL_DIR "/Library/Frameworks/Intel_TBB.framework/Versions")
+        # libs: libtbb.dylib, libtbbmalloc.dylib, *_debug
+        set(_TBB_LIB_NAME "tbb")
+        set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc")
+        set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug")
+        set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug")
+        # default flavor on apple: ia32/cc4.0.1_os10.4.9
+        # Jiri: There is no reason to presume there is only one flavor and
+        #       that user's setting of variables should be ignored.
+        if(NOT TBB_COMPILER)
+            set(_TBB_COMPILER "cc4.0.1_os10.4.9")
+        elseif (NOT TBB_COMPILER)
+            set(_TBB_COMPILER ${TBB_COMPILER})
+        endif(NOT TBB_COMPILER)
+        if(NOT TBB_ARCHITECTURE)
+            set(_TBB_ARCHITECTURE "ia32")
+        elseif(NOT TBB_ARCHITECTURE)
+            set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE})
+        endif(NOT TBB_ARCHITECTURE)
+    else (APPLE)
+        # LINUX
+        set(_TBB_DEFAULT_INSTALL_DIR "/opt/intel/tbb" "/usr/local/include" "/usr/include")
+        set(_TBB_LIB_NAME "tbb")
+        set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc")
+        set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug")
+        set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug")
+        # has em64t/cc3.2.3_libc2.3.2_kernel2.4.21 em64t/cc3.3.3_libc2.3.3_kernel2.6.5 em64t/cc3.4.3_libc2.3.4_kernel2.6.9 em64t/cc4.1.0_libc2.4_kernel2.6.16.21
+        # has ia32/*
+        # has itanium/*
+        set(_TBB_COMPILER ${TBB_COMPILER})
+        set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE})
+    endif (APPLE)
+endif (UNIX)
+
+if (CMAKE_SYSTEM MATCHES "SunOS.*")
+# SUN
+# not yet supported
+# has em64t/cc3.4.3_kernel5.10
+# has ia32/*
+endif (CMAKE_SYSTEM MATCHES "SunOS.*")
+
+
+#-- Clear the public variables
+set (TBB_FOUND "NO")
+
+
+#-- Find TBB install dir and set ${_TBB_INSTALL_DIR} and cached ${TBB_INSTALL_DIR}
+# first: use CMake variable TBB_INSTALL_DIR
+if (TBB_INSTALL_DIR)
+    set (_TBB_INSTALL_DIR ${TBB_INSTALL_DIR})
+endif (TBB_INSTALL_DIR)
+# second: use environment variable
+if (NOT _TBB_INSTALL_DIR)
+    if (NOT "$ENV{TBB_INSTALL_DIR}" STREQUAL "")
+        set (_TBB_INSTALL_DIR $ENV{TBB_INSTALL_DIR})
+    endif (NOT "$ENV{TBB_INSTALL_DIR}" STREQUAL "")
+    # Intel recommends setting TBB21_INSTALL_DIR
+    if (NOT "$ENV{TBB21_INSTALL_DIR}" STREQUAL "")
+        set (_TBB_INSTALL_DIR $ENV{TBB21_INSTALL_DIR})
+    endif (NOT "$ENV{TBB21_INSTALL_DIR}" STREQUAL "")
+    if (NOT "$ENV{TBB22_INSTALL_DIR}" STREQUAL "")
+        set (_TBB_INSTALL_DIR $ENV{TBB22_INSTALL_DIR})
+    endif (NOT "$ENV{TBB22_INSTALL_DIR}" STREQUAL "")
+    if (NOT "$ENV{TBB30_INSTALL_DIR}" STREQUAL "")
+        set (_TBB_INSTALL_DIR $ENV{TBB30_INSTALL_DIR})
+    endif (NOT "$ENV{TBB30_INSTALL_DIR}" STREQUAL "")
+endif (NOT _TBB_INSTALL_DIR)
+# third: try to find path automatically
+if (NOT _TBB_INSTALL_DIR)
+    if (_TBB_DEFAULT_INSTALL_DIR)
+        set (_TBB_INSTALL_DIR ${_TBB_DEFAULT_INSTALL_DIR})
+    endif (_TBB_DEFAULT_INSTALL_DIR)
+endif (NOT _TBB_INSTALL_DIR)
+# sanity check
+if (NOT _TBB_INSTALL_DIR)
+    message ("ERROR: Unable to find Intel TBB install directory. ${_TBB_INSTALL_DIR}")
+else (NOT _TBB_INSTALL_DIR)
+# finally: set the cached CMake variable TBB_INSTALL_DIR
+if (NOT TBB_INSTALL_DIR)
+    set (TBB_INSTALL_DIR ${_TBB_INSTALL_DIR} CACHE PATH "Intel TBB install directory")
+    mark_as_advanced(TBB_INSTALL_DIR)
+endif (NOT TBB_INSTALL_DIR)
+
+
+#-- A macro to rewrite the paths of the library. This is necessary, because
+#   find_library() always found the em64t/vc9 version of the TBB libs
+macro(TBB_CORRECT_LIB_DIR var_name)
+#    if (NOT "${_TBB_ARCHITECTURE}" STREQUAL "em64t")
+        string(REPLACE em64t "${_TBB_ARCHITECTURE}" ${var_name} ${${var_name}})
+#    endif (NOT "${_TBB_ARCHITECTURE}" STREQUAL "em64t")
+    string(REPLACE ia32 "${_TBB_ARCHITECTURE}" ${var_name} ${${var_name}})
+    string(REPLACE vc7.1 "${_TBB_COMPILER}" ${var_name} ${${var_name}})
+    string(REPLACE vc8 "${_TBB_COMPILER}" ${var_name} ${${var_name}})
+    string(REPLACE vc9 "${_TBB_COMPILER}" ${var_name} ${${var_name}})
+    string(REPLACE vc10 "${_TBB_COMPILER}" ${var_name} ${${var_name}})
+endmacro(TBB_CORRECT_LIB_DIR var_content)
+
+
+#-- Look for include directory and set ${TBB_INCLUDE_DIR}
+set (TBB_INC_SEARCH_DIR ${_TBB_INSTALL_DIR}/include)
+# Jiri: tbbvars now sets the CPATH environment variable to the directory
+#       containing the headers.
+find_path(TBB_INCLUDE_DIR
+    tbb/task_scheduler_init.h
+    PATHS ${TBB_INC_SEARCH_DIR} ENV CPATH
+)
+mark_as_advanced(TBB_INCLUDE_DIR)
+
+
+#-- Look for libraries
+# GvdB: $ENV{TBB_ARCH_PLATFORM} is set by the build script tbbvars[.bat|.sh|.csh]
+if (NOT $ENV{TBB_ARCH_PLATFORM} STREQUAL "")
+    set (_TBB_LIBRARY_DIR 
+         ${_TBB_INSTALL_DIR}/lib/$ENV{TBB_ARCH_PLATFORM}
+         ${_TBB_INSTALL_DIR}/$ENV{TBB_ARCH_PLATFORM}/lib
+        )
+endif (NOT $ENV{TBB_ARCH_PLATFORM} STREQUAL "")
+# Jiri: This block isn't mutually exclusive with the previous one
+#       (hence no else), instead I test if the user really specified
+#       the variables in question.
+if ((NOT ${TBB_ARCHITECTURE} STREQUAL "") AND (NOT ${TBB_COMPILER} STREQUAL ""))
+    # HH: deprecated
+    message(STATUS "[Warning] FindTBB.cmake: The use of TBB_ARCHITECTURE and TBB_COMPILER is deprecated and may not be supported in future versions. Please set \$ENV{TBB_ARCH_PLATFORM} (using tbbvars.[bat|csh|sh]).")
+    # Jiri: It doesn't hurt to look in more places, so I store the hints from
+    #       ENV{TBB_ARCH_PLATFORM} and the TBB_ARCHITECTURE and TBB_COMPILER
+    #       variables and search them both.
+    set (_TBB_LIBRARY_DIR "${_TBB_INSTALL_DIR}/${_TBB_ARCHITECTURE}/${_TBB_COMPILER}/lib" ${_TBB_LIBRARY_DIR})
+endif ((NOT ${TBB_ARCHITECTURE} STREQUAL "") AND (NOT ${TBB_COMPILER} STREQUAL ""))
+
+# GvdB: Mac OS X distribution places libraries directly in lib directory.
+list(APPEND _TBB_LIBRARY_DIR ${_TBB_INSTALL_DIR}/lib)
+
+# Jiri: No reason not to check the default paths. From recent versions,
+#       tbbvars has started exporting the LIBRARY_PATH and LD_LIBRARY_PATH
+#       variables, which now point to the directories of the lib files.
+#       It all makes more sense to use the ${_TBB_LIBRARY_DIR} as a HINTS
+#       argument instead of the implicit PATHS as it isn't hard-coded
+#       but computed by system introspection. Searching the LIBRARY_PATH
+#       and LD_LIBRARY_PATH environment variables is now even more important
+#       that tbbvars doesn't export TBB_ARCH_PLATFORM and it facilitates
+#       the use of TBB built from sources.
+find_library(TBB_LIBRARY ${_TBB_LIB_NAME} HINTS ${_TBB_LIBRARY_DIR}
+        PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
+find_library(TBB_MALLOC_LIBRARY ${_TBB_LIB_MALLOC_NAME} HINTS ${_TBB_LIBRARY_DIR}
+        PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
+
+#Extract path from TBB_LIBRARY name
+get_filename_component(TBB_LIBRARY_DIR ${TBB_LIBRARY} PATH)
+
+#TBB_CORRECT_LIB_DIR(TBB_LIBRARY)
+#TBB_CORRECT_LIB_DIR(TBB_MALLOC_LIBRARY)
+mark_as_advanced(TBB_LIBRARY TBB_MALLOC_LIBRARY)
+
+#-- Look for debug libraries
+# Jiri: Changed the same way as for the release libraries.
+find_library(TBB_LIBRARY_DEBUG ${_TBB_LIB_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR}
+        PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
+find_library(TBB_MALLOC_LIBRARY_DEBUG ${_TBB_LIB_MALLOC_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR}
+        PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
+
+# Jiri: Self-built TBB stores the debug libraries in a separate directory.
+#       Extract path from TBB_LIBRARY_DEBUG name
+get_filename_component(TBB_LIBRARY_DEBUG_DIR ${TBB_LIBRARY_DEBUG} PATH)
+
+#TBB_CORRECT_LIB_DIR(TBB_LIBRARY_DEBUG)
+#TBB_CORRECT_LIB_DIR(TBB_MALLOC_LIBRARY_DEBUG)
+mark_as_advanced(TBB_LIBRARY_DEBUG TBB_MALLOC_LIBRARY_DEBUG)
+
+
+if (TBB_INCLUDE_DIR)
+    if (TBB_LIBRARY)
+        set (TBB_FOUND "YES")
+        set (TBB_LIBRARIES ${TBB_LIBRARY} ${TBB_MALLOC_LIBRARY} ${TBB_LIBRARIES})
+        set (TBB_DEBUG_LIBRARIES ${TBB_LIBRARY_DEBUG} ${TBB_MALLOC_LIBRARY_DEBUG} ${TBB_DEBUG_LIBRARIES})
+        set (TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR} CACHE PATH "TBB include directory" FORCE)
+        set (TBB_LIBRARY_DIRS ${TBB_LIBRARY_DIR} CACHE PATH "TBB library directory" FORCE)
+        # Jiri: Self-built TBB stores the debug libraries in a separate directory.
+        set (TBB_DEBUG_LIBRARY_DIRS ${TBB_LIBRARY_DEBUG_DIR} CACHE PATH "TBB debug library directory" FORCE)
+        mark_as_advanced(TBB_INCLUDE_DIRS TBB_LIBRARY_DIRS TBB_DEBUG_LIBRARY_DIRS TBB_LIBRARIES TBB_DEBUG_LIBRARIES)
+        message(STATUS "Found Intel TBB")
+    endif (TBB_LIBRARY)
+endif (TBB_INCLUDE_DIR)
+
+if (NOT TBB_FOUND)
+    message("ERROR: Intel TBB NOT found!")
+    message(STATUS "Looked for Threading Building Blocks in ${_TBB_INSTALL_DIR}")
+    # do only throw fatal, if this pkg is REQUIRED
+    if (TBB_FIND_REQUIRED)
+        message(FATAL_ERROR "Could NOT find TBB library.")
+    endif (TBB_FIND_REQUIRED)
+endif (NOT TBB_FOUND)
+
+endif (NOT _TBB_INSTALL_DIR)
+
+if (TBB_FOUND)
+	set(TBB_INTERFACE_VERSION 0)
+	FILE(READ "${TBB_INCLUDE_DIRS}/tbb/tbb_stddef.h" _TBB_VERSION_CONTENTS)
+	STRING(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" TBB_INTERFACE_VERSION "${_TBB_VERSION_CONTENTS}")
+	set(TBB_INTERFACE_VERSION "${TBB_INTERFACE_VERSION}")
+endif (TBB_FOUND)
diff --git a/cmake/FingerPrint-Config.cmake b/cmake/FingerPrint-Config.cmake
new file mode 100644
index 0000000..7b45d5c
--- /dev/null
+++ b/cmake/FingerPrint-Config.cmake
@@ -0,0 +1,10 @@
+set(OLDFILE ${SOURCE_DIR}/Util/FingerPrint.cpp)
+if (EXISTS ${OLDFILE})
+	file(REMOVE_RECURSE ${OLDFILE})
+endif()
+file(MD5 ${SOURCE_DIR}/prepare.cpp MD5PREPARE)
+file(MD5 ${SOURCE_DIR}/DataStructures/StaticRTree.h MD5RTREE)
+file(MD5 ${SOURCE_DIR}/Util/GraphLoader.h MD5GRAPH)
+file(MD5 ${SOURCE_DIR}/Server/DataStructures/InternalDataFacade.h MD5OBJECTS)
+
+CONFIGURE_FILE( ${SOURCE_DIR}/Util/FingerPrint.cpp.in ${SOURCE_DIR}/Util/FingerPrint.cpp )
diff --git a/cmake/GetGitRevisionDescription.cmake.in b/cmake/GetGitRevisionDescription.cmake.in
new file mode 100644
index 0000000..888ce13
--- /dev/null
+++ b/cmake/GetGitRevisionDescription.cmake.in
@@ -0,0 +1,38 @@
+# 
+# Internal file for GetGitRevisionDescription.cmake
+#
+# Requires CMake 2.6 or newer (uses the 'function' command)
+#
+# Original Author:
+# 2009-2010 Ryan Pavlik <rpavlik at iastate.edu> <abiryan at ryand.net>
+# http://academic.cleardefinition.com
+# Iowa State University HCI Graduate Program/VRAC
+#
+# Copyright Iowa State University 2009-2010.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+set(HEAD_HASH)
+
+file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
+
+string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
+if(HEAD_CONTENTS MATCHES "ref")
+	# named branch
+	string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
+	if(EXISTS "@GIT_DIR@/${HEAD_REF}")
+		configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
+	elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}")
+		configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
+		set(HEAD_HASH "${HEAD_REF}")
+	endif()
+else()
+	# detached HEAD
+	configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
+endif()
+
+if(NOT HEAD_HASH)
+	file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
+	string(STRIP "${HEAD_HASH}" HEAD_HASH)
+endif()
diff --git a/cmake/cmake_options_script.py b/cmake/cmake_options_script.py
new file mode 100644
index 0000000..52e943e
--- /dev/null
+++ b/cmake/cmake_options_script.py
@@ -0,0 +1,45 @@
+# Based on @berenm's pull request https://github.com/quarnster/SublimeClang/pull/135
+# Create the database with cmake with for example: cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
+# or you could have set(CMAKE_EXPORT_COMPILE_COMMANDS ON) in your CMakeLists.txt
+# Usage within SublimeClang:
+#   "sublimeclang_options_script": "python ${home}/code/cmake_options_script.py ${project_path:build}/compile_commands.json",
+
+
+import re
+import os
+import os.path
+import pickle
+import sys
+import json
+
+compilation_database_pattern = re.compile('(?<=\s)-[DIOUWfgs][^=\s]+(?:=\\"[^"]+\\"|=[^"]\S+)?')
+
+def load_db(filename):
+    compilation_database = {}
+    with open(filename) as compilation_database_file:
+        compilation_database_entries = json.load(compilation_database_file)
+
+    total = len(compilation_database_entries)
+    entry = 0
+    for compilation_entry in compilation_database_entries:
+        entry = entry + 1
+        compilation_database[compilation_entry["file"]] = [ p.strip() for p in compilation_database_pattern.findall(compilation_entry["command"]) ]
+    return compilation_database
+
+scriptpath = os.path.dirname(os.path.abspath(sys.argv[1]))
+cache_file = "%s/cached_options.txt" % (scriptpath)
+
+db = None
+if os.access(cache_file, os.R_OK) == 0:
+    db = load_db(sys.argv[1])
+    f = open(cache_file, "wb")
+    pickle.dump(db, f)
+    f.close()
+else:
+    f = open(cache_file)
+    db = pickle.load(f)
+    f.close()
+
+if db and sys.argv[2] in db:
+    for option in db[sys.argv[2]]:
+        print option
diff --git a/cmake/pkgconfig.in b/cmake/pkgconfig.in
new file mode 100644
index 0000000..e81feba
--- /dev/null
+++ b/cmake/pkgconfig.in
@@ -0,0 +1,11 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+includedir=${prefix}/include/osrm
+libdir=${prefix}/lib
+
+Name: libOSRM
+Description: Project OSRM library
+Version: @GIT_DESCRIPTION@
+Requires:
+Libs: -L${libdir} -lOSRM
+Libs.private: @BOOST_LIBRARY_LISTING@
+Cflags: -I${includedir}
diff --git a/config/cucumber.yml b/config/cucumber.yml
index 5a9fa4e..2cdea36 100644
--- a/config/cucumber.yml
+++ b/config/cucumber.yml
@@ -1,5 +1,9 @@
 # config/cucumber.yml
 ##YAML Template
 ---
-default: --require features
-verify: --require features --tags ~@todo --tag ~@stress -f progress
\ No newline at end of file
+default: --require features --tags ~@todo --tags ~@bug --tag ~@stress
+verify: --require features --tags ~@todo --tags ~@bug --tags ~@stress -f progress
+jenkins: --require features --tags ~@todo --tags ~@bug --tags ~@stress --tags ~@options -f progress
+bugs: --require features --tags @bug
+todo: --require features --tags @todo
+all: --require features
diff --git a/contractor.ini b/contractor.ini
deleted file mode 100644
index 4da33c7..0000000
--- a/contractor.ini
+++ /dev/null
@@ -1 +0,0 @@
-Threads = 4
diff --git a/createHierarchy.cpp b/createHierarchy.cpp
deleted file mode 100644
index 5e6343d..0000000
--- a/createHierarchy.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-
-#include "Algorithms/IteratorBasedCRC32.h"
-#include "Contractor/Contractor.h"
-#include "Contractor/EdgeBasedGraphFactory.h"
-#include "DataStructures/BinaryHeap.h"
-#include "DataStructures/DeallocatingVector.h"
-#include "DataStructures/QueryEdge.h"
-#include "DataStructures/StaticGraph.h"
-#include "DataStructures/StaticRTree.h"
-#include "Util/BaseConfiguration.h"
-#include "Util/GraphLoader.h"
-#include "Util/InputFileUtil.h"
-#include "Util/LuaUtil.h"
-#include "Util/OpenMPWrapper.h"
-#include "Util/StringUtil.h"
-#include "typedefs.h"
-
-#include <boost/foreach.hpp>
-
-#include <luabind/luabind.hpp>
-
-#include <fstream>
-#include <istream>
-#include <iostream>
-#include <cstring>
-#include <string>
-#include <vector>
-
-typedef QueryEdge::EdgeData EdgeData;
-typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
-typedef StaticGraph<EdgeData>::InputEdge StaticEdge;
-typedef BaseConfiguration ContractorConfiguration;
-
-std::vector<NodeInfo> internalToExternalNodeMapping;
-std::vector<_Restriction> inputRestrictions;
-std::vector<NodeID> bollardNodes;
-std::vector<NodeID> trafficLightNodes;
-std::vector<ImportEdge> edgeList;
-
-int main (int argc, char *argv[]) {
-    try {
-        if(argc < 3) {
-            ERR("usage: " << std::endl << argv[0] << " <osrm-data> <osrm-restrictions> [<profile>]");
-        }
-
-        double startupTime = get_timestamp();
-        unsigned numberOfThreads = omp_get_num_procs();
-        if(testDataFile("contractor.ini")) {
-            ContractorConfiguration contractorConfig("contractor.ini");
-            unsigned rawNumber = stringToInt(contractorConfig.GetParameter("Threads"));
-            if(rawNumber != 0 && rawNumber <= numberOfThreads)
-                numberOfThreads = rawNumber;
-        }
-        omp_set_num_threads(numberOfThreads);
-
-        INFO("Using restrictions from file: " << argv[2]);
-        std::ifstream restrictionsInstream(argv[2], std::ios::binary);
-        if(!restrictionsInstream.good()) {
-            ERR("Could not access <osrm-restrictions> files");
-        }
-        _Restriction restriction;
-        unsigned usableRestrictionsCounter(0);
-        restrictionsInstream.read((char*)&usableRestrictionsCounter, sizeof(unsigned));
-        inputRestrictions.resize(usableRestrictionsCounter);
-        restrictionsInstream.read((char *)&(inputRestrictions[0]), usableRestrictionsCounter*sizeof(_Restriction));
-        restrictionsInstream.close();
-
-        std::ifstream in;
-        in.open (argv[1], std::ifstream::in | std::ifstream::binary);
-        if (!in.is_open()) {
-            ERR("Cannot open " << argv[1]);
-        }
-
-        std::string nodeOut(argv[1]);		nodeOut += ".nodes";
-        std::string edgeOut(argv[1]);		edgeOut += ".edges";
-        std::string graphOut(argv[1]);		graphOut += ".hsgr";
-        std::string rtree_nodes_path(argv[1]);  rtree_nodes_path += ".ramIndex";
-        std::string rtree_leafs_path(argv[1]);  rtree_leafs_path += ".fileIndex";
-
-        /*** Setup Scripting Environment ***/
-        if(!testDataFile( (argc > 3 ? argv[3] : "profile.lua") )) {
-            ERR("Need profile.lua to apply traffic signal penalty");
-        }
-
-        // Create a new lua state
-        lua_State *myLuaState = luaL_newstate();
-
-        // Connect LuaBind to this lua state
-        luabind::open(myLuaState);
-
-        //open utility libraries string library;
-        luaL_openlibs(myLuaState);
-
-        //adjust lua load path
-        luaAddScriptFolderToLoadPath( myLuaState, (argc > 3 ? argv[3] : "profile.lua") );
-
-        // Now call our function in a lua script
-        INFO("Parsing speedprofile from " << (argc > 3 ? argv[3] : "profile.lua") );
-        if(0 != luaL_dofile(myLuaState, (argc > 3 ? argv[3] : "profile.lua") )) {
-            ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
-        }
-
-        EdgeBasedGraphFactory::SpeedProfileProperties speedProfile;
-
-        if(0 != luaL_dostring( myLuaState, "return traffic_signal_penalty\n")) {
-            ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
-        }
-        speedProfile.trafficSignalPenalty = 10*lua_tointeger(myLuaState, -1);
-
-        if(0 != luaL_dostring( myLuaState, "return u_turn_penalty\n")) {
-            ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
-        }
-        speedProfile.uTurnPenalty = 10*lua_tointeger(myLuaState, -1);
-
-        speedProfile.has_turn_penalty_function = lua_function_exists( myLuaState, "turn_function" );
-
-        std::vector<ImportEdge> edgeList;
-        NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions);
-        in.close();
-        INFO(inputRestrictions.size() << " restrictions, " << bollardNodes.size() << " bollard nodes, " << trafficLightNodes.size() << " traffic lights");
-        if(0 == edgeList.size())
-            ERR("The input data is broken. It is impossible to do any turns in this graph");
-
-
-        /***
-         * Building an edge-expanded graph from node-based input an turn restrictions
-         */
-
-        INFO("Generating edge-expanded graph representation");
-        EdgeBasedGraphFactory * edgeBasedGraphFactory = new EdgeBasedGraphFactory (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping, speedProfile);
-        std::vector<ImportEdge>().swap(edgeList);
-        edgeBasedGraphFactory->Run(edgeOut.c_str(), myLuaState);
-        std::vector<_Restriction>().swap(inputRestrictions);
-        std::vector<NodeID>().swap(bollardNodes);
-        std::vector<NodeID>().swap(trafficLightNodes);
-        NodeID edgeBasedNodeNumber = edgeBasedGraphFactory->GetNumberOfNodes();
-        DeallocatingVector<EdgeBasedEdge> edgeBasedEdgeList;
-        edgeBasedGraphFactory->GetEdgeBasedEdges(edgeBasedEdgeList);
-        std::vector<EdgeBasedGraphFactory::EdgeBasedNode> nodeBasedEdgeList;
-        edgeBasedGraphFactory->GetEdgeBasedNodes(nodeBasedEdgeList);
-        delete edgeBasedGraphFactory;
-
-        /***
-         * Writing info on original (node-based) nodes
-         */
-
-        INFO("writing node map ...");
-        std::ofstream mapOutFile(nodeOut.c_str(), std::ios::binary);
-        mapOutFile.write((char *)&(internalToExternalNodeMapping[0]), internalToExternalNodeMapping.size()*sizeof(NodeInfo));
-        mapOutFile.close();
-        std::vector<NodeInfo>().swap(internalToExternalNodeMapping);
-
-        double expansionHasFinishedTime = get_timestamp() - startupTime;
-
-        /***
-         * Building grid-like nearest-neighbor data structure
-         */
-
-        INFO("building r-tree ...");
-        StaticRTree<EdgeBasedGraphFactory::EdgeBasedNode> * rtree =
-                new StaticRTree<EdgeBasedGraphFactory::EdgeBasedNode>(
-                        nodeBasedEdgeList,
-                        rtree_nodes_path.c_str(),
-                        rtree_leafs_path.c_str()
-                );
-        delete rtree;
-        IteratorbasedCRC32<std::vector<EdgeBasedGraphFactory::EdgeBasedNode> > crc32;
-        unsigned crc32OfNodeBasedEdgeList = crc32(nodeBasedEdgeList.begin(), nodeBasedEdgeList.end() );
-        nodeBasedEdgeList.clear();
-        INFO("CRC32 based checksum is " << crc32OfNodeBasedEdgeList);
-
-        /***
-         * Contracting the edge-expanded graph
-         */
-
-        INFO("initializing contractor");
-        Contractor* contractor = new Contractor( edgeBasedNodeNumber, edgeBasedEdgeList );
-        double contractionStartedTimestamp(get_timestamp());
-        contractor->Run();
-        INFO("Contraction took " << get_timestamp() - contractionStartedTimestamp << " sec");
-
-        DeallocatingVector< QueryEdge > contractedEdgeList;
-        contractor->GetEdges( contractedEdgeList );
-        delete contractor;
-
-        /***
-         * Sorting contracted edges in a way that the static query graph can read some in in-place.
-         */
-
-        INFO("Building Node Array");
-        std::sort(contractedEdgeList.begin(), contractedEdgeList.end());
-        unsigned numberOfNodes = 0;
-        unsigned numberOfEdges = contractedEdgeList.size();
-        INFO("Serializing compacted graph of " << numberOfEdges << " edges");
-        std::ofstream edgeOutFile(graphOut.c_str(), std::ios::binary);
-
-        BOOST_FOREACH(const QueryEdge & edge, contractedEdgeList) {
-            if(edge.source > numberOfNodes) {
-                numberOfNodes = edge.source;
-            }
-            if(edge.target > numberOfNodes) {
-                numberOfNodes = edge.target;
-            }
-        }
-        numberOfNodes+=1;
-
-        std::vector< StaticGraph<EdgeData>::_StrNode > _nodes;
-        _nodes.resize( numberOfNodes + 1 );
-
-        StaticGraph<EdgeData>::EdgeIterator edge = 0;
-        StaticGraph<EdgeData>::EdgeIterator position = 0;
-        for ( StaticGraph<EdgeData>::NodeIterator node = 0; node <= numberOfNodes; ++node ) {
-            StaticGraph<EdgeData>::EdgeIterator lastEdge = edge;
-            while ( edge < numberOfEdges && contractedEdgeList[edge].source == node )
-                ++edge;
-            _nodes[node].firstEdge = position; //=edge
-            position += edge - lastEdge; //remove
-        }
-        ++numberOfNodes;
-        //Serialize numberOfNodes, nodes
-        edgeOutFile.write((char*) &crc32OfNodeBasedEdgeList, sizeof(unsigned));
-        edgeOutFile.write((char*) &numberOfNodes, sizeof(unsigned));
-        edgeOutFile.write((char*) &_nodes[0], sizeof(StaticGraph<EdgeData>::_StrNode)*(numberOfNodes));
-        //Serialize number of Edges
-        edgeOutFile.write((char*) &position, sizeof(unsigned));
-        --numberOfNodes;
-        edge = 0;
-        int usedEdgeCounter = 0;
-        StaticGraph<EdgeData>::_StrEdge currentEdge;
-        for ( StaticGraph<EdgeData>::NodeIterator node = 0; node < numberOfNodes; ++node ) {
-            for ( StaticGraph<EdgeData>::EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) {
-                assert(node != contractedEdgeList[edge].target);
-                currentEdge.target = contractedEdgeList[edge].target;
-                currentEdge.data = contractedEdgeList[edge].data;
-                if(currentEdge.data.distance <= 0) {
-                    INFO("Edge: " << i << ",source: " << contractedEdgeList[edge].source << ", target: " << contractedEdgeList[edge].target << ", dist: " << currentEdge.data.distance);
-                    ERR("Failed at edges of node " << node << " of " << numberOfNodes);
-                }
-                //Serialize edges
-                edgeOutFile.write((char*) &currentEdge, sizeof(StaticGraph<EdgeData>::_StrEdge));
-                ++edge;
-                ++usedEdgeCounter;
-            }
-        }
-        double endTime = (get_timestamp() - startupTime);
-        INFO("Expansion  : " << (nodeBasedNodeNumber/expansionHasFinishedTime) << " nodes/sec and "<< (edgeBasedNodeNumber/expansionHasFinishedTime) << " edges/sec");
-        INFO("Contraction: " << (edgeBasedNodeNumber/expansionHasFinishedTime) << " nodes/sec and "<< usedEdgeCounter/endTime << " edges/sec");
-
-        edgeOutFile.close();
-        //cleanedEdgeList.clear();
-        _nodes.clear();
-        INFO("finished preprocessing");
-    } catch (std::exception &e) {
-        ERR("Exception occured: " << e.what());
-    }
-    return 0;
-}
diff --git a/datastore.cpp b/datastore.cpp
new file mode 100644
index 0000000..10d5bf5
--- /dev/null
+++ b/datastore.cpp
@@ -0,0 +1,575 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "DataStructures/OriginalEdgeData.h"
+#include "DataStructures/RangeTable.h"
+#include "DataStructures/QueryEdge.h"
+#include "DataStructures/SharedMemoryFactory.h"
+#include "DataStructures/SharedMemoryVectorWrapper.h"
+#include "DataStructures/StaticGraph.h"
+#include "DataStructures/StaticRTree.h"
+#include "DataStructures/TurnInstructions.h"
+#include "Server/DataStructures/BaseDataFacade.h"
+#include "Server/DataStructures/SharedDataType.h"
+#include "Server/DataStructures/SharedBarriers.h"
+#include "Util/BoostFileSystemFix.h"
+#include "Util/DataStoreOptions.h"
+#include "Util/SimpleLogger.h"
+#include "Util/FingerPrint.h"
+#include "typedefs.h"
+
+#include <osrm/Coordinate.h>
+
+typedef BaseDataFacade<QueryEdge::EdgeData>::RTreeLeaf RTreeLeaf;
+typedef StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>::TreeNode RTreeNode;
+typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
+
+#ifdef __linux__
+#include <sys/mman.h>
+#endif
+
+#include <boost/filesystem/fstream.hpp>
+#include <boost/iostreams/seek.hpp>
+
+#include <cstdint>
+
+#include <fstream>
+#include <string>
+
+int main(const int argc, const char *argv[])
+{
+    LogPolicy::GetInstance().Unmute();
+    SharedBarriers barrier;
+
+#ifdef __linux__
+    const bool lock_flags = MCL_CURRENT | MCL_FUTURE;
+    if (-1 == mlockall(lock_flags))
+    {
+        SimpleLogger().Write(logWARNING) << "Process " << argv[0] << " could not request RAM lock";
+    }
+#endif
+
+    try
+    {
+        try
+        {
+            boost::interprocess::scoped_lock<boost::interprocess::named_mutex> pending_lock(
+                barrier.pending_update_mutex);
+        }
+        catch (...)
+        {
+            // hard unlock in case of any exception.
+            barrier.pending_update_mutex.unlock();
+        }
+    }
+    catch (const std::exception &e)
+    {
+        SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
+    }
+
+    try
+    {
+        SimpleLogger().Write(logDEBUG) << "Checking input parameters";
+
+        ServerPaths server_paths;
+        bool springclean = false;
+        if (!GenerateDataStoreOptions(argc, argv, server_paths, springclean))
+        {
+            return 0;
+        }
+        if (springclean)
+        {
+            SimpleLogger().Write() << "spring-cleaning all shared memory regions";
+            // find all existing shmem regions and remove them.
+            if (SharedMemory::RegionExists(DATA_1) && !SharedMemory::Remove(DATA_1))
+            {
+                SimpleLogger().Write(logWARNING) << "could not delete DATA_1";
+            }
+            if (SharedMemory::RegionExists(LAYOUT_1) && !SharedMemory::Remove(LAYOUT_1))
+            {
+                SimpleLogger().Write(logWARNING) << "could not delete LAYOUT_1";
+            }
+            if (SharedMemory::RegionExists(DATA_2) && !SharedMemory::Remove(DATA_2))
+            {
+                SimpleLogger().Write(logWARNING) << "could not delete DATA_2";
+            }
+            if (SharedMemory::RegionExists(LAYOUT_2) && !SharedMemory::Remove(LAYOUT_2))
+            {
+                SimpleLogger().Write(logWARNING) << "could not delete LAYOUT_2";
+            }
+            if (SharedMemory::RegionExists(CURRENT_REGIONS) &&
+                !SharedMemory::Remove(CURRENT_REGIONS))
+            {
+                SimpleLogger().Write(logWARNING) << "could not delete CURRENT_REGIONS";
+            }
+            return 0;
+        }
+
+        if (server_paths.find("hsgrdata") == server_paths.end())
+        {
+            throw OSRMException("no hsgr file found");
+        }
+        if (server_paths.find("ramindex") == server_paths.end())
+        {
+            throw OSRMException("no ram index file found");
+        }
+        if (server_paths.find("fileindex") == server_paths.end())
+        {
+            throw OSRMException("no leaf index file found");
+        }
+        if (server_paths.find("nodesdata") == server_paths.end())
+        {
+            throw OSRMException("no nodes file found");
+        }
+        if (server_paths.find("edgesdata") == server_paths.end())
+        {
+            throw OSRMException("no edges file found");
+        }
+        if (server_paths.find("namesdata") == server_paths.end())
+        {
+            throw OSRMException("no names file found");
+        }
+        if (server_paths.find("geometry") == server_paths.end())
+        {
+            throw OSRMException("no geometry file found");
+        }
+
+        ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata");
+        BOOST_ASSERT(server_paths.end() != paths_iterator);
+        BOOST_ASSERT(!paths_iterator->second.empty());
+        const boost::filesystem::path &hsgr_path = paths_iterator->second;
+        paths_iterator = server_paths.find("timestamp");
+        BOOST_ASSERT(server_paths.end() != paths_iterator);
+        BOOST_ASSERT(!paths_iterator->second.empty());
+        const boost::filesystem::path &timestamp_path = paths_iterator->second;
+        paths_iterator = server_paths.find("ramindex");
+        BOOST_ASSERT(server_paths.end() != paths_iterator);
+        BOOST_ASSERT(!paths_iterator->second.empty());
+        const boost::filesystem::path &ram_index_path = paths_iterator->second;
+        paths_iterator = server_paths.find("fileindex");
+        BOOST_ASSERT(server_paths.end() != paths_iterator);
+        BOOST_ASSERT(!paths_iterator->second.empty());
+        const boost::filesystem::path index_file_path_absolute =
+            boost::filesystem::portable_canonical(paths_iterator->second);
+        const std::string &file_index_path = index_file_path_absolute.string();
+        paths_iterator = server_paths.find("nodesdata");
+        BOOST_ASSERT(server_paths.end() != paths_iterator);
+        BOOST_ASSERT(!paths_iterator->second.empty());
+        const boost::filesystem::path &nodes_data_path = paths_iterator->second;
+        paths_iterator = server_paths.find("edgesdata");
+        BOOST_ASSERT(server_paths.end() != paths_iterator);
+        BOOST_ASSERT(!paths_iterator->second.empty());
+        const boost::filesystem::path &edges_data_path = paths_iterator->second;
+        paths_iterator = server_paths.find("namesdata");
+        BOOST_ASSERT(server_paths.end() != paths_iterator);
+        BOOST_ASSERT(!paths_iterator->second.empty());
+        const boost::filesystem::path &names_data_path = paths_iterator->second;
+        paths_iterator = server_paths.find("geometry");
+        BOOST_ASSERT(server_paths.end() != paths_iterator);
+        BOOST_ASSERT(!paths_iterator->second.empty());
+        const boost::filesystem::path &geometries_data_path = paths_iterator->second;
+
+        // get the shared memory segment to use
+        bool use_first_segment = SharedMemory::RegionExists(LAYOUT_2);
+        const SharedDataType LAYOUT = [&]
+        {
+            if (use_first_segment)
+            {
+                return LAYOUT_1;
+            }
+            return LAYOUT_2;
+        }();
+        const SharedDataType DATA = [&]
+        {
+            if (use_first_segment)
+            {
+                return DATA_1;
+            }
+            return DATA_2;
+        }();
+
+        // Allocate a memory layout in shared memory, deallocate previous
+        SharedMemory *layout_memory = SharedMemoryFactory::Get(LAYOUT, sizeof(SharedDataLayout));
+        SharedDataLayout *shared_layout_ptr = static_cast<SharedDataLayout *>(layout_memory->Ptr());
+        shared_layout_ptr = new (layout_memory->Ptr()) SharedDataLayout();
+
+        shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::FILE_INDEX_PATH,
+                                              file_index_path.length() + 1);
+
+        // collect number of elements to store in shared memory object
+        SimpleLogger().Write() << "load names from: " << names_data_path;
+        // number of entries in name index
+        boost::filesystem::ifstream name_stream(names_data_path, std::ios::binary);
+        unsigned name_blocks = 0;
+        name_stream.read((char *)&name_blocks, sizeof(unsigned));
+        shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::NAME_OFFSETS, name_blocks);
+        shared_layout_ptr->SetBlockSize<typename RangeTable<16, true>::BlockT>(
+            SharedDataLayout::NAME_BLOCKS, name_blocks);
+        SimpleLogger().Write() << "name offsets size: " << name_blocks;
+        BOOST_ASSERT_MSG(0 != name_blocks, "name file broken");
+
+        unsigned number_of_chars = 0;
+        name_stream.read((char *)&number_of_chars, sizeof(unsigned));
+        shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::NAME_CHAR_LIST, number_of_chars);
+
+        // Loading information for original edges
+        boost::filesystem::ifstream edges_input_stream(edges_data_path, std::ios::binary);
+        unsigned number_of_original_edges = 0;
+        edges_input_stream.read((char *)&number_of_original_edges, sizeof(unsigned));
+
+        // note: settings this all to the same size is correct, we extract them from the same struct
+        shared_layout_ptr->SetBlockSize<NodeID>(SharedDataLayout::VIA_NODE_LIST,
+                                                number_of_original_edges);
+        shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::NAME_ID_LIST,
+                                                  number_of_original_edges);
+        shared_layout_ptr->SetBlockSize<TurnInstruction>(SharedDataLayout::TURN_INSTRUCTION,
+                                                         number_of_original_edges);
+        // note: there are 32 geometry indicators in one unsigned block
+        shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::GEOMETRIES_INDICATORS,
+                                                  number_of_original_edges);
+
+        boost::filesystem::ifstream hsgr_input_stream(hsgr_path, std::ios::binary);
+
+        FingerPrint fingerprint_loaded, fingerprint_orig;
+        hsgr_input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
+        if (fingerprint_loaded.TestGraphUtil(fingerprint_orig))
+        {
+            SimpleLogger().Write(logDEBUG) << "Fingerprint checked out ok";
+        }
+        else
+        {
+            SimpleLogger().Write(logWARNING) << ".hsgr was prepared with different build. "
+                                                "Reprocess to get rid of this warning.";
+        }
+
+        // load checksum
+        unsigned checksum = 0;
+        hsgr_input_stream.read((char *)&checksum, sizeof(unsigned));
+        shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::HSGR_CHECKSUM, 1);
+        // load graph node size
+        unsigned number_of_graph_nodes = 0;
+        hsgr_input_stream.read((char *)&number_of_graph_nodes, sizeof(unsigned));
+
+        BOOST_ASSERT_MSG((0 != number_of_graph_nodes), "number of nodes is zero");
+        shared_layout_ptr->SetBlockSize<QueryGraph::NodeArrayEntry>(
+            SharedDataLayout::GRAPH_NODE_LIST, number_of_graph_nodes);
+
+        // load graph edge size
+        unsigned number_of_graph_edges = 0;
+        hsgr_input_stream.read((char *)&number_of_graph_edges, sizeof(unsigned));
+        BOOST_ASSERT_MSG(0 != number_of_graph_edges, "number of graph edges is zero");
+        shared_layout_ptr->SetBlockSize<QueryGraph::EdgeArrayEntry>(
+            SharedDataLayout::GRAPH_EDGE_LIST, number_of_graph_edges);
+
+        // load rsearch tree size
+        boost::filesystem::ifstream tree_node_file(ram_index_path, std::ios::binary);
+
+        uint32_t tree_size = 0;
+        tree_node_file.read((char *)&tree_size, sizeof(uint32_t));
+        shared_layout_ptr->SetBlockSize<RTreeNode>(SharedDataLayout::R_SEARCH_TREE, tree_size);
+
+        // load timestamp size
+        std::string m_timestamp;
+        if (boost::filesystem::exists(timestamp_path))
+        {
+            boost::filesystem::ifstream timestamp_stream(timestamp_path);
+            if (!timestamp_stream)
+            {
+                SimpleLogger().Write(logWARNING) << timestamp_path
+                                                 << " not found. setting to default";
+            }
+            else
+            {
+                getline(timestamp_stream, m_timestamp);
+                timestamp_stream.close();
+            }
+        }
+        if (m_timestamp.empty())
+        {
+            m_timestamp = "n/a";
+        }
+        if (25 < m_timestamp.length())
+        {
+            m_timestamp.resize(25);
+        }
+        shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::TIMESTAMP, m_timestamp.length());
+
+        // load coordinate size
+        boost::filesystem::ifstream nodes_input_stream(nodes_data_path, std::ios::binary);
+        unsigned coordinate_list_size = 0;
+        nodes_input_stream.read((char *)&coordinate_list_size, sizeof(unsigned));
+        shared_layout_ptr->SetBlockSize<FixedPointCoordinate>(SharedDataLayout::COORDINATE_LIST,
+                                                              coordinate_list_size);
+
+        // load geometries sizes
+        std::ifstream geometry_input_stream(geometries_data_path.string().c_str(),
+                                            std::ios::binary);
+        unsigned number_of_geometries_indices = 0;
+        unsigned number_of_compressed_geometries = 0;
+
+        geometry_input_stream.read((char *)&number_of_geometries_indices, sizeof(unsigned));
+        shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::GEOMETRIES_INDEX,
+                                                  number_of_geometries_indices);
+        boost::iostreams::seek(
+            geometry_input_stream, number_of_geometries_indices * sizeof(unsigned), BOOST_IOS::cur);
+        geometry_input_stream.read((char *)&number_of_compressed_geometries, sizeof(unsigned));
+        shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::GEOMETRIES_LIST,
+                                                  number_of_compressed_geometries);
+
+        // allocate shared memory block
+        SimpleLogger().Write() << "allocating shared memory of "
+                               << shared_layout_ptr->GetSizeOfLayout() << " bytes";
+        SharedMemory *shared_memory =
+            SharedMemoryFactory::Get(DATA, shared_layout_ptr->GetSizeOfLayout());
+        char *shared_memory_ptr = static_cast<char *>(shared_memory->Ptr());
+
+        // read actual data into shared memory object //
+
+        // hsgr checksum
+        unsigned *checksum_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
+            shared_memory_ptr, SharedDataLayout::HSGR_CHECKSUM);
+        *checksum_ptr = checksum;
+
+        // ram index file name
+        char *file_index_path_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
+            shared_memory_ptr, SharedDataLayout::FILE_INDEX_PATH);
+        // make sure we have 0 ending
+        std::fill(file_index_path_ptr,
+                  file_index_path_ptr +
+                      shared_layout_ptr->GetBlockSize(SharedDataLayout::FILE_INDEX_PATH),
+                  0);
+        std::copy(file_index_path.begin(), file_index_path.end(), file_index_path_ptr);
+
+        // Loading street names
+        unsigned *name_offsets_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
+            shared_memory_ptr, SharedDataLayout::NAME_OFFSETS);
+        if (shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_OFFSETS) > 0)
+        {
+            name_stream.read((char *)name_offsets_ptr,
+                             shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_OFFSETS));
+        }
+
+        unsigned *name_blocks_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
+            shared_memory_ptr, SharedDataLayout::NAME_BLOCKS);
+        if (shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_BLOCKS) > 0)
+        {
+            name_stream.read((char *)name_blocks_ptr,
+                             shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_BLOCKS));
+        }
+
+        char *name_char_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
+            shared_memory_ptr, SharedDataLayout::NAME_CHAR_LIST);
+        unsigned temp_length;
+        name_stream.read((char *)&temp_length, sizeof(unsigned));
+
+        BOOST_ASSERT_MSG(temp_length ==
+                             shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_CHAR_LIST),
+                         "Name file corrupted!");
+
+        if (shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_CHAR_LIST) > 0)
+        {
+            name_stream.read(name_char_ptr,
+                             shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_CHAR_LIST));
+        }
+
+        name_stream.close();
+
+        // load original edge information
+        NodeID *via_node_ptr = shared_layout_ptr->GetBlockPtr<NodeID, true>(
+            shared_memory_ptr, SharedDataLayout::VIA_NODE_LIST);
+
+        unsigned *name_id_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
+            shared_memory_ptr, SharedDataLayout::NAME_ID_LIST);
+
+        TurnInstruction *turn_instructions_ptr =
+            shared_layout_ptr->GetBlockPtr<TurnInstruction, true>(
+                shared_memory_ptr, SharedDataLayout::TURN_INSTRUCTION);
+
+        unsigned *geometries_indicator_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
+            shared_memory_ptr, SharedDataLayout::GEOMETRIES_INDICATORS);
+
+        OriginalEdgeData current_edge_data;
+        for (unsigned i = 0; i < number_of_original_edges; ++i)
+        {
+            edges_input_stream.read((char *)&(current_edge_data), sizeof(OriginalEdgeData));
+            via_node_ptr[i] = current_edge_data.via_node;
+            name_id_ptr[i] = current_edge_data.name_id;
+            turn_instructions_ptr[i] = current_edge_data.turn_instruction;
+
+            const unsigned bucket = i / 32;
+            const unsigned offset = i % 32;
+            const unsigned value = [&]
+            {
+                unsigned return_value = 0;
+                if (0 != offset)
+                {
+                    return_value = geometries_indicator_ptr[bucket];
+                }
+                return return_value;
+            }();
+            if (current_edge_data.compressed_geometry)
+            {
+                geometries_indicator_ptr[bucket] = (value | (1 << offset));
+            }
+        }
+        edges_input_stream.close();
+
+        // load compressed geometry
+        unsigned temporary_value;
+        unsigned *geometries_index_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
+            shared_memory_ptr, SharedDataLayout::GEOMETRIES_INDEX);
+        geometry_input_stream.seekg(0, geometry_input_stream.beg);
+        geometry_input_stream.read((char *)&temporary_value, sizeof(unsigned));
+        BOOST_ASSERT(temporary_value ==
+                     shared_layout_ptr->num_entries[SharedDataLayout::GEOMETRIES_INDEX]);
+
+        if (shared_layout_ptr->GetBlockSize(SharedDataLayout::GEOMETRIES_INDEX) > 0)
+        {
+            geometry_input_stream.read(
+                (char *)geometries_index_ptr,
+                shared_layout_ptr->GetBlockSize(SharedDataLayout::GEOMETRIES_INDEX));
+        }
+        unsigned *geometries_list_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
+            shared_memory_ptr, SharedDataLayout::GEOMETRIES_LIST);
+
+        geometry_input_stream.read((char *)&temporary_value, sizeof(unsigned));
+        BOOST_ASSERT(temporary_value ==
+                     shared_layout_ptr->num_entries[SharedDataLayout::GEOMETRIES_LIST]);
+
+        if (shared_layout_ptr->GetBlockSize(SharedDataLayout::GEOMETRIES_LIST) > 0)
+        {
+            geometry_input_stream.read(
+                (char *)geometries_list_ptr,
+                shared_layout_ptr->GetBlockSize(SharedDataLayout::GEOMETRIES_LIST));
+        }
+
+        // Loading list of coordinates
+        FixedPointCoordinate *coordinates_ptr =
+            shared_layout_ptr->GetBlockPtr<FixedPointCoordinate, true>(
+                shared_memory_ptr, SharedDataLayout::COORDINATE_LIST);
+
+        NodeInfo current_node;
+        for (unsigned i = 0; i < coordinate_list_size; ++i)
+        {
+            nodes_input_stream.read((char *)&current_node, sizeof(NodeInfo));
+            coordinates_ptr[i] = FixedPointCoordinate(current_node.lat, current_node.lon);
+        }
+        nodes_input_stream.close();
+
+        // store timestamp
+        char *timestamp_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
+            shared_memory_ptr, SharedDataLayout::TIMESTAMP);
+        std::copy(m_timestamp.c_str(), m_timestamp.c_str() + m_timestamp.length(), timestamp_ptr);
+
+        // store search tree portion of rtree
+        char *rtree_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
+            shared_memory_ptr, SharedDataLayout::R_SEARCH_TREE);
+
+        if (tree_size > 0)
+        {
+            tree_node_file.read(rtree_ptr, sizeof(RTreeNode) * tree_size);
+        }
+        tree_node_file.close();
+
+        // load the nodes of the search graph
+        QueryGraph::NodeArrayEntry *graph_node_list_ptr =
+            shared_layout_ptr->GetBlockPtr<QueryGraph::NodeArrayEntry, true>(
+                shared_memory_ptr, SharedDataLayout::GRAPH_NODE_LIST);
+        if (shared_layout_ptr->GetBlockSize(SharedDataLayout::GRAPH_NODE_LIST) > 0)
+        {
+            hsgr_input_stream.read(
+                (char *)graph_node_list_ptr,
+                shared_layout_ptr->GetBlockSize(SharedDataLayout::GRAPH_NODE_LIST));
+        }
+
+        // load the edges of the search graph
+        QueryGraph::EdgeArrayEntry *graph_edge_list_ptr =
+            shared_layout_ptr->GetBlockPtr<QueryGraph::EdgeArrayEntry, true>(
+                shared_memory_ptr, SharedDataLayout::GRAPH_EDGE_LIST);
+        if (shared_layout_ptr->GetBlockSize(SharedDataLayout::GRAPH_EDGE_LIST) > 0)
+        {
+            hsgr_input_stream.read(
+                (char *)graph_edge_list_ptr,
+                shared_layout_ptr->GetBlockSize(SharedDataLayout::GRAPH_EDGE_LIST));
+        }
+        hsgr_input_stream.close();
+
+        // acquire lock
+        SharedMemory *data_type_memory =
+            SharedMemoryFactory::Get(CURRENT_REGIONS, sizeof(SharedDataTimestamp), true, false);
+        SharedDataTimestamp *data_timestamp_ptr =
+            static_cast<SharedDataTimestamp *>(data_type_memory->Ptr());
+
+        boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
+            barrier.query_mutex);
+
+        // notify all processes that were waiting for this condition
+        if (0 < barrier.number_of_queries)
+        {
+            barrier.no_running_queries_condition.wait(query_lock);
+        }
+
+        data_timestamp_ptr->layout = LAYOUT;
+        data_timestamp_ptr->data = DATA;
+        data_timestamp_ptr->timestamp += 1;
+        if (use_first_segment)
+        {
+            BOOST_ASSERT(DATA == DATA_1);
+            BOOST_ASSERT(LAYOUT == LAYOUT_1);
+            if (!SharedMemory::Remove(DATA_2))
+            {
+                SimpleLogger().Write(logWARNING) << "could not delete DATA_2";
+            }
+            if (!SharedMemory::Remove(LAYOUT_2))
+            {
+                SimpleLogger().Write(logWARNING) << "could not delete LAYOUT_2";
+            }
+        }
+        else
+        {
+            BOOST_ASSERT(DATA == DATA_2);
+            BOOST_ASSERT(LAYOUT == LAYOUT_2);
+            if (!SharedMemory::Remove(DATA_1))
+            {
+                SimpleLogger().Write(logWARNING) << "could not delete DATA_1";
+            }
+            if (!SharedMemory::Remove(LAYOUT_1))
+            {
+                SimpleLogger().Write(logWARNING) << "could not delete LAYOUT_1";
+            }
+        }
+        SimpleLogger().Write() << "all data loaded";
+
+        shared_layout_ptr->PrintInformation();
+    }
+    catch (const std::exception &e)
+    {
+        SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
+    }
+
+    return 0;
+}
diff --git a/extractor.cpp b/extractor.cpp
index 3beeef5..b170b74 100644
--- a/extractor.cpp
+++ b/extractor.cpp
@@ -1,123 +1,286 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, others 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
 
 #include "Extractor/ExtractorCallbacks.h"
 #include "Extractor/ExtractionContainers.h"
 #include "Extractor/ScriptingEnvironment.h"
 #include "Extractor/PBFParser.h"
 #include "Extractor/XMLParser.h"
-#include "Util/BaseConfiguration.h"
-#include "Util/InputFileUtil.h"
+#include "Util/FingerPrint.h"
+#include "Util/GitDescription.h"
 #include "Util/MachineInfo.h"
-#include "Util/OpenMPWrapper.h"
+#include "Util/OSRMException.h"
+#include "Util/ProgramOptions.h"
+#include "Util/SimpleLogger.h"
 #include "Util/StringUtil.h"
+#include "Util/TimingUtil.h"
 #include "typedefs.h"
 
 #include <cstdlib>
+
+#include <thread>
+#include <chrono>
 #include <iostream>
 #include <fstream>
-
 #include <string>
+#include <unordered_map>
 
-typedef BaseConfiguration ExtractorConfiguration;
+#include <tbb/task_scheduler_init.h>
 
-ExtractorCallbacks * extractCallBacks;
+ExtractorCallbacks *extractor_callbacks;
+FingerPrint fingerprint;
 
-int main (int argc, char *argv[]) {
-    double earliestTime = get_timestamp();
+int main(int argc, char *argv[])
+{
+    try
+    {
+        LogPolicy::GetInstance().Unmute();
 
-    if(argc < 2) {
-        ERR("usage: \n" << argv[0] << " <file.osm/.osm.bz2/.osm.pbf> [<profile.lua>]");
-    }
+        TIMER_START(extracting);
 
-    /*** Setup Scripting Environment ***/
-    ScriptingEnvironment scriptingEnvironment((argc > 2 ? argv[2] : "profile.lua"));
+        boost::filesystem::path config_file_path, input_path, profile_path;
+        unsigned requested_num_threads;
 
-    unsigned numberOfThreads = omp_get_num_procs();
-    if(testDataFile("extractor.ini")) {
-        ExtractorConfiguration extractorConfig("extractor.ini");
-        unsigned rawNumber = stringToInt(extractorConfig.GetParameter("Threads"));
-        if( rawNumber != 0 && rawNumber <= numberOfThreads)
-            numberOfThreads = rawNumber;
-    }
-    omp_set_num_threads(numberOfThreads);
-
-    INFO("extracting data from input file " << argv[1]);
-    bool isPBF(false);
-    std::string outputFileName(argv[1]);
-    std::string restrictionsFileName(argv[1]);
-    std::string::size_type pos = outputFileName.find(".osm.bz2");
-    if(pos==std::string::npos) {
-        pos = outputFileName.find(".osm.pbf");
-        if(pos!=std::string::npos) {
-            isPBF = true;
+        // declare a group of options that will be allowed only on command line
+        boost::program_options::options_description generic_options("Options");
+        generic_options.add_options()("version,v", "Show version")("help,h",
+                                                                   "Show this help message")(
+            "config,c",
+            boost::program_options::value<boost::filesystem::path>(&config_file_path)
+                ->default_value("extractor.ini"),
+            "Path to a configuration file.");
+
+        // declare a group of options that will be allowed both on command line and in config file
+        boost::program_options::options_description config_options("Configuration");
+        config_options.add_options()("profile,p",
+                                     boost::program_options::value<boost::filesystem::path>(
+                                         &profile_path)->default_value("profile.lua"),
+                                     "Path to LUA routing profile")(
+            "threads,t",
+            boost::program_options::value<unsigned int>(&requested_num_threads)->default_value(tbb::task_scheduler_init::default_num_threads()),
+            "Number of threads to use");
+
+        // hidden options, will be allowed both on command line and in config file, but will not be
+        // shown to the user
+        boost::program_options::options_description hidden_options("Hidden options");
+        hidden_options.add_options()(
+            "input,i",
+            boost::program_options::value<boost::filesystem::path>(&input_path),
+            "Input file in .osm, .osm.bz2 or .osm.pbf format");
+
+        // positional option
+        boost::program_options::positional_options_description positional_options;
+        positional_options.add("input", 1);
+
+        // combine above options for parsing
+        boost::program_options::options_description cmdline_options;
+        cmdline_options.add(generic_options).add(config_options).add(hidden_options);
+
+        boost::program_options::options_description config_file_options;
+        config_file_options.add(config_options).add(hidden_options);
+
+        boost::program_options::options_description visible_options(
+            boost::filesystem::basename(argv[0]) + " <input.osm/.osm.bz2/.osm.pbf> [options]");
+        visible_options.add(generic_options).add(config_options);
+
+        // parse command line options
+        boost::program_options::variables_map option_variables;
+        boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
+                                          .options(cmdline_options)
+                                          .positional(positional_options)
+                                          .run(),
+                                      option_variables);
+
+        if (option_variables.count("version"))
+        {
+            SimpleLogger().Write() << g_GIT_DESCRIPTION;
+            return 0;
         }
-    }
-    if(pos!=std::string::npos) {
-        outputFileName.replace(pos, 8, ".osrm");
-        restrictionsFileName.replace(pos, 8, ".osrm.restrictions");
-    } else {
-        pos=outputFileName.find(".osm");
-        if(pos!=std::string::npos) {
-            outputFileName.replace(pos, 5, ".osrm");
-            restrictionsFileName.replace(pos, 5, ".osrm.restrictions");
-        } else {
-            outputFileName.append(".osrm");
-            restrictionsFileName.append(".osrm.restrictions");
+
+        if (option_variables.count("help"))
+        {
+            SimpleLogger().Write() << visible_options;
+            return 0;
         }
-    }
 
-    unsigned amountOfRAM = 1;
-    unsigned installedRAM = GetPhysicalmemory();
-    if(installedRAM < 2048264) {
-        WARN("Machine has less than 2GB RAM.");
-    }
+        boost::program_options::notify(option_variables);
 
-    StringMap stringMap;
-    ExtractionContainers externalMemory;
+        // parse config file
+        if (boost::filesystem::is_regular_file(config_file_path))
+        {
+            SimpleLogger().Write() << "Reading options from: " << config_file_path.string();
+            std::string ini_file_contents = ReadIniFileAndLowerContents(config_file_path);
+            std::stringstream config_stream(ini_file_contents);
+            boost::program_options::store(parse_config_file(config_stream, config_file_options),
+                                          option_variables);
+            boost::program_options::notify(option_variables);
+        }
 
-    stringMap[""] = 0;
-    extractCallBacks = new ExtractorCallbacks(&externalMemory, &stringMap);
-    BaseParser* parser;
-    if(isPBF) {
-        parser = new PBFParser(argv[1], extractCallBacks, scriptingEnvironment);
-    } else {
-        parser = new XMLParser(argv[1], extractCallBacks, scriptingEnvironment);
-    }
+        if (!option_variables.count("input"))
+        {
+            SimpleLogger().Write() << visible_options;
+            return 0;
+        }
 
-    if(!parser->ReadHeader()) {
-        ERR("Parser not initialized!");
-    }
-    INFO("Parsing in progress..");
-    double time = get_timestamp();
-    parser->Parse();
-    INFO("Parsing finished after " << get_timestamp() - time << " seconds");
+        if (1 > requested_num_threads)
+        {
+            SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
+            return 1;
+        }
 
-    externalMemory.PrepareData(outputFileName, restrictionsFileName, amountOfRAM);
+        if (!boost::filesystem::is_regular_file(input_path))
+        {
+            SimpleLogger().Write(logWARNING) << "Input file " << input_path.string()
+                                             << " not found!";
+            return 1;
+        }
 
-    stringMap.clear();
-    delete parser;
-    delete extractCallBacks;
-    INFO("finished after " << get_timestamp() - earliestTime << "s");
+        if (!boost::filesystem::is_regular_file(profile_path))
+        {
+            SimpleLogger().Write(logWARNING) << "Profile " << profile_path.string()
+                                             << " not found!";
+            return 1;
+        }
 
-    std::cout << "\nRun:\n"
-                   "./osrm-prepare " << outputFileName << " " << restrictionsFileName << std::endl;
+        const unsigned recommended_num_threads = tbb::task_scheduler_init::default_num_threads();
+
+        SimpleLogger().Write() << "Input file: " << input_path.filename().string();
+        SimpleLogger().Write() << "Profile: " << profile_path.filename().string();
+        SimpleLogger().Write() << "Threads: " << requested_num_threads;
+        if (recommended_num_threads != requested_num_threads)
+        {
+            SimpleLogger().Write(logWARNING) << "The recommended number of threads is "
+                                             << recommended_num_threads
+                                             << "! This setting may have performance side-effects.";
+        }
+
+        tbb::task_scheduler_init init(requested_num_threads);
+
+        /*** Setup Scripting Environment ***/
+        ScriptingEnvironment scripting_environment(profile_path.string().c_str());
+
+        bool file_has_pbf_format(false);
+        std::string output_file_name = input_path.string();
+        std::string restriction_fileName = input_path.string();
+        std::string::size_type pos = output_file_name.find(".osm.bz2");
+        if (pos == std::string::npos)
+        {
+            pos = output_file_name.find(".osm.pbf");
+            if (pos != std::string::npos)
+            {
+                file_has_pbf_format = true;
+            } else {
+                pos = output_file_name.find(".osm.xml");
+            }
+        }
+        if (pos == std::string::npos)
+        {
+            pos = output_file_name.find(".pbf");
+            if (pos != std::string::npos)
+            {
+                file_has_pbf_format = true;
+            }
+        }
+        if (pos == std::string::npos)
+        {
+            pos = output_file_name.find(".osm");
+            if (pos == std::string::npos)
+            {
+                output_file_name.append(".osrm");
+                restriction_fileName.append(".osrm.restrictions");
+            }
+            else
+            {
+                output_file_name.replace(pos, 5, ".osrm");
+                restriction_fileName.replace(pos, 5, ".osrm.restrictions");
+            }
+        }
+        else
+        {
+            output_file_name.replace(pos, 8, ".osrm");
+            restriction_fileName.replace(pos, 8, ".osrm.restrictions");
+        }
+
+        std::unordered_map<std::string, NodeID> string_map;
+        ExtractionContainers extraction_containers;
+
+        string_map[""] = 0;
+        extractor_callbacks = new ExtractorCallbacks(extraction_containers, string_map);
+        BaseParser *parser;
+        if (file_has_pbf_format)
+        {
+            parser = new PBFParser(input_path.string().c_str(),
+                                   extractor_callbacks,
+                                   scripting_environment,
+                                   requested_num_threads);
+        }
+        else
+        {
+            parser = new XMLParser(input_path.string().c_str(), extractor_callbacks, scripting_environment);
+        }
+
+        if (!parser->ReadHeader())
+        {
+            throw OSRMException("Parser not initialized!");
+        }
+        SimpleLogger().Write() << "Parsing in progress..";
+        TIMER_START(parsing);
+
+        parser->Parse();
+        delete parser;
+        delete extractor_callbacks;
+
+        TIMER_STOP(parsing);
+        SimpleLogger().Write() << "Parsing finished after " << TIMER_SEC(parsing)
+                               << " seconds";
+
+        if (extraction_containers.all_edges_list.empty())
+        {
+            SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
+            return 1;
+        }
+
+        extraction_containers.PrepareData(output_file_name, restriction_fileName);
+
+        TIMER_STOP(extracting);
+        SimpleLogger().Write() << "extraction finished after " << TIMER_SEC(extracting)
+                               << "s";
+        SimpleLogger().Write() << "To prepare the data for routing, run: "
+                               << "./osrm-prepare " << output_file_name << std::endl;
+    }
+    catch (boost::program_options::too_many_positional_options_error &)
+    {
+        SimpleLogger().Write(logWARNING) << "Only one input file can be specified";
+        return 1;
+    }
+    catch (std::exception &e)
+    {
+        SimpleLogger().Write(logWARNING) << e.what();
+        return 1;
+    }
     return 0;
 }
diff --git a/extractor.ini b/extractor.ini
deleted file mode 100644
index 8dd11de..0000000
--- a/extractor.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-Memory = 2
-Threads = 10
diff --git a/features/bicycle/access.feature b/features/bicycle/access.feature
index cb1fc0d..2087327 100644
--- a/features/bicycle/access.feature
+++ b/features/bicycle/access.feature
@@ -1,173 +1,173 @@
 @routing @bicycle @access
 Feature: Bike - Access tags on ways
-Reference: http://wiki.openstreetmap.org/wiki/Key:access
+# Reference: http://wiki.openstreetmap.org/wiki/Key:access
 
-	Background:
-		Given the profile "bicycle"
-		
-	Scenario: Bike - Access tag hierachy on ways
-		Then routability should be
-		 | highway | access | vehicle | bicycle | bothw |
-		 |         |        |         |         | x     |
-		 |         | yes    |         |         | x     |
-		 |         | no     |         |         |       |
-		 |         |        | yes     |         | x     |
-		 |         |        | no      |         |       |
-		 |         | no     | yes     |         | x     |
-		 |         | yes    | no      |         |       |
-		 |         |        |         | yes     | x     |
-		 |         |        |         | no      |       |
-		 |         | no     |         | yes     | x     |
-		 |         | yes    |         | no      |       |
-		 |         |        | no      | yes     | x     |
-		 |         |        | yes     | no      |       |
-		 | runway  |        |         |         |       |
-		 | runway  | yes    |         |         | x     |
-		 | runway  | no     |         |         |       |
-		 | runway  |        | yes     |         | x     |
-		 | runway  |        | no      |         |       |
-		 | runway  | no     | yes     |         | x     |
-		 | runway  | yes    | no      |         |       |
-		 | runway  |        |         | yes     | x     |
-		 | runway  |        |         | no      |       |
-		 | runway  | no     |         | yes     | x     |
-		 | runway  | yes    |         | no      |       |
-		 | runway  |        | no      | yes     | x     |
-		 | runway  |        | yes     | no      |       |
+    Background:
+        Given the profile "bicycle"
+
+    Scenario: Bike - Access tag hierachy on ways
+        Then routability should be
+            | highway | access | vehicle | bicycle | bothw |
+            |         |        |         |         | x     |
+            |         | yes    |         |         | x     |
+            |         | no     |         |         |       |
+            |         |        | yes     |         | x     |
+            |         |        | no      |         |       |
+            |         | no     | yes     |         | x     |
+            |         | yes    | no      |         |       |
+            |         |        |         | yes     | x     |
+            |         |        |         | no      |       |
+            |         | no     |         | yes     | x     |
+            |         | yes    |         | no      |       |
+            |         |        | no      | yes     | x     |
+            |         |        | yes     | no      |       |
+            | runway  |        |         |         |       |
+            | runway  | yes    |         |         | x     |
+            | runway  | no     |         |         |       |
+            | runway  |        | yes     |         | x     |
+            | runway  |        | no      |         |       |
+            | runway  | no     | yes     |         | x     |
+            | runway  | yes    | no      |         |       |
+            | runway  |        |         | yes     | x     |
+            | runway  |        |         | no      |       |
+            | runway  | no     |         | yes     | x     |
+            | runway  | yes    |         | no      |       |
+            | runway  |        | no      | yes     | x     |
+            | runway  |        | yes     | no      |       |
 
     @todo
-  	Scenario: Bike - Access tag in forward direction
-  		Then routability should be
-  		 | highway | access:forward | vehicle:forward | bicycle:forward | forw | backw |
-  		 |         |                |                 |                 | x    |       |
-  		 |         | yes            |                 |                 | x    |       |
-  		 |         | no             |                 |                 |      |       |
-  		 |         |                | yes             |                 | x    |       |
-  		 |         |                | no              |                 |      |       |
-  		 |         | no             | yes             |                 | x    |       |
-  		 |         | yes            | no              |                 |      |       |
-  		 |         |                |                 | yes             | x    |       |
-  		 |         |                |                 | no              |      |       |
-  		 |         | no             |                 | yes             | x    |       |
-  		 |         | yes            |                 | no              |      |       |
-  		 |         |                | no              | yes             | x    |       |
-  		 |         |                | yes             | no              |      |       |
-  		 | runway  |                |                 |                 | x    |       |
-  		 | runway  | yes            |                 |                 | x    |       |
-  		 | runway  | no             |                 |                 |      |       |
-  		 | runway  |                | yes             |                 | x    |       |
-  		 | runway  |                | no              |                 |      |       |
-  		 | runway  | no             | yes             |                 | x    |       |
-  		 | runway  | yes            | no              |                 |      |       |
-  		 | runway  |                |                 | yes             | x    |       |
-  		 | runway  |                |                 | no              |      |       |
-  		 | runway  | no             |                 | yes             | x    |       |
-  		 | runway  | yes            |                 | no              |      |       |
-  		 | runway  |                | no              | yes             | x    |       |
-  		 | runway  |                | yes             | no              |      |       |
+    Scenario: Bike - Access tag in forward direction
+        Then routability should be
+            | highway | access:forward | vehicle:forward | bicycle:forward | forw | backw |
+            |         |                |                 |                 | x    |       |
+            |         | yes            |                 |                 | x    |       |
+            |         | no             |                 |                 |      |       |
+            |         |                | yes             |                 | x    |       |
+            |         |                | no              |                 |      |       |
+            |         | no             | yes             |                 | x    |       |
+            |         | yes            | no              |                 |      |       |
+            |         |                |                 | yes             | x    |       |
+            |         |                |                 | no              |      |       |
+            |         | no             |                 | yes             | x    |       |
+            |         | yes            |                 | no              |      |       |
+            |         |                | no              | yes             | x    |       |
+            |         |                | yes             | no              |      |       |
+            | runway  |                |                 |                 | x    |       |
+            | runway  | yes            |                 |                 | x    |       |
+            | runway  | no             |                 |                 |      |       |
+            | runway  |                | yes             |                 | x    |       |
+            | runway  |                | no              |                 |      |       |
+            | runway  | no             | yes             |                 | x    |       |
+            | runway  | yes            | no              |                 |      |       |
+            | runway  |                |                 | yes             | x    |       |
+            | runway  |                |                 | no              |      |       |
+            | runway  | no             |                 | yes             | x    |       |
+            | runway  | yes            |                 | no              |      |       |
+            | runway  |                | no              | yes             | x    |       |
+            | runway  |                | yes             | no              |      |       |
 
     @todo
-   	Scenario: Bike - Access tag in backward direction
-   		Then routability should be
-   		 | highway | access:forward | vehicle:forward | bicycle:forward | forw | backw |
-   		 |         |                |                 |                 |      | x     |
-   		 |         | yes            |                 |                 |      | x     |
-   		 |         | no             |                 |                 |      |       |
-   		 |         |                | yes             |                 |      | x     |
-   		 |         |                | no              |                 |      |       |
-   		 |         | no             | yes             |                 |      | x     |
-   		 |         | yes            | no              |                 |      |       |
-   		 |         |                |                 | yes             |      | x     |
-   		 |         |                |                 | no              |      |       |
-   		 |         | no             |                 | yes             |      | x     |
-   		 |         | yes            |                 | no              |      |       |
-   		 |         |                | no              | yes             |      | x     |
-   		 |         |                | yes             | no              |      |       |
-   		 | runway  |                |                 |                 |      | x     |
-   		 | runway  | yes            |                 |                 |      | x     |
-   		 | runway  | no             |                 |                 |      |       |
-   		 | runway  |                | yes             |                 |      | x     |
-   		 | runway  |                | no              |                 |      |       |
-   		 | runway  | no             | yes             |                 |      | x     |
-   		 | runway  | yes            | no              |                 |      |       |
-   		 | runway  |                |                 | yes             |      | x     |
-   		 | runway  |                |                 | no              |      |       |
-   		 | runway  | no             |                 | yes             |      | x     |
-   		 | runway  | yes            |                 | no              |      |       |
-   		 | runway  |                | no              | yes             |      | x     |
-   		 | runway  |                | yes             | no              |      |       |
+    Scenario: Bike - Access tag in backward direction
+        Then routability should be
+            | highway | access:forward | vehicle:forward | bicycle:forward | forw | backw |
+            |         |                |                 |                 |      | x     |
+            |         | yes            |                 |                 |      | x     |
+            |         | no             |                 |                 |      |       |
+            |         |                | yes             |                 |      | x     |
+            |         |                | no              |                 |      |       |
+            |         | no             | yes             |                 |      | x     |
+            |         | yes            | no              |                 |      |       |
+            |         |                |                 | yes             |      | x     |
+            |         |                |                 | no              |      |       |
+            |         | no             |                 | yes             |      | x     |
+            |         | yes            |                 | no              |      |       |
+            |         |                | no              | yes             |      | x     |
+            |         |                | yes             | no              |      |       |
+            | runway  |                |                 |                 |      | x     |
+            | runway  | yes            |                 |                 |      | x     |
+            | runway  | no             |                 |                 |      |       |
+            | runway  |                | yes             |                 |      | x     |
+            | runway  |                | no              |                 |      |       |
+            | runway  | no             | yes             |                 |      | x     |
+            | runway  | yes            | no              |                 |      |       |
+            | runway  |                |                 | yes             |      | x     |
+            | runway  |                |                 | no              |      |       |
+            | runway  | no             |                 | yes             |      | x     |
+            | runway  | yes            |                 | no              |      |       |
+            | runway  |                | no              | yes             |      | x     |
+            | runway  |                | yes             | no              |      |       |
 
-	Scenario: Bike - Overwriting implied acccess on ways
-		Then routability should be
-		 | highway  | access | vehicle | bicycle | bothw |
-		 | cycleway |        |         |         | x     |
-		 | runway   |        |         |         |       |
-		 | cycleway | no     |         |         |       |
-		 | cycleway |        | no      |         |       |
-		 | cycleway |        |         | no      |       |
-		 | runway   | yes    |         |         | x     |
-		 | runway   |        | yes     |         | x     |
-		 | runway   |        |         | yes     | x     |
+    Scenario: Bike - Overwriting implied acccess on ways
+        Then routability should be
+            | highway  | access | vehicle | bicycle | bothw |
+            | cycleway |        |         |         | x     |
+            | runway   |        |         |         |       |
+            | cycleway | no     |         |         |       |
+            | cycleway |        | no      |         |       |
+            | cycleway |        |         | no      |       |
+            | runway   | yes    |         |         | x     |
+            | runway   |        | yes     |         | x     |
+            | runway   |        |         | yes     | x     |
 
-	Scenario: Bike - Access tags on ways
-	 	Then routability should be
-		 | access       | vehicle      | bicycle      | bothw |
-		 |              |              |              | x     |
-		 | yes          |              |              | x     |
-		 | permissive   |              |              | x     |
-		 | designated   |              |              | x     |
-		 | some_tag     |              |              | x     |
-		 | no           |              |              |       |
-		 | private      |              |              |       |
-		 | agricultural |              |              |       |
-		 | forestery    |              |              |       |
-		 |              | yes          |              | x     |
-		 |              | permissive   |              | x     |
-		 |              | designated   |              | x     |
-		 |              | some_tag     |              | x     |
-		 |              | no           |              |       |
-		 |              | private      |              |       |
-		 |              | agricultural |              |       |
-		 |              | forestery    |              |       |
-		 |              |              | yes          | x     |
-		 |              |              | permissive   | x     |
-		 |              |              | designated   | x     |
-		 |              |              | some_tag     | x     |
-		 |              |              | no           |       |
-		 |              |              | private      |       |
-		 |              |              | agricultural |       |
-		 |              |              | forestery    |       |
+    Scenario: Bike - Access tags on ways
+        Then routability should be
+            | access       | vehicle      | bicycle      | bothw |
+            |              |              |              | x     |
+            | yes          |              |              | x     |
+            | permissive   |              |              | x     |
+            | designated   |              |              | x     |
+            | some_tag     |              |              | x     |
+            | no           |              |              |       |
+            | private      |              |              |       |
+            | agricultural |              |              |       |
+            | forestery    |              |              |       |
+            |              | yes          |              | x     |
+            |              | permissive   |              | x     |
+            |              | designated   |              | x     |
+            |              | some_tag     |              | x     |
+            |              | no           |              |       |
+            |              | private      |              |       |
+            |              | agricultural |              |       |
+            |              | forestery    |              |       |
+            |              |              | yes          | x     |
+            |              |              | permissive   | x     |
+            |              |              | designated   | x     |
+            |              |              | some_tag     | x     |
+            |              |              | no           |       |
+            |              |              | private      |       |
+            |              |              | agricultural |       |
+            |              |              | forestery    |       |
 
-	Scenario: Bike - Access tags on both node and way
-	 	Then routability should be
-		 | access   | node/access | bothw |
-		 | yes      | yes         | x     |
-		 | yes      | no          |       |
-		 | yes      | some_tag    | x     |
-		 | no       | yes         |       |
-		 | no       | no          |       |
-		 | no       | some_tag    |       |
-		 | some_tag | yes         | x     |
-		 | some_tag | no          |       |
-		 | some_tag | some_tag    | x     |
+    Scenario: Bike - Access tags on both node and way
+        Then routability should be
+            | access   | node/access | bothw |
+            | yes      | yes         | x     |
+            | yes      | no          |       |
+            | yes      | some_tag    | x     |
+            | no       | yes         |       |
+            | no       | no          |       |
+            | no       | some_tag    |       |
+            | some_tag | yes         | x     |
+            | some_tag | no          |       |
+            | some_tag | some_tag    | x     |
 
-	Scenario: Bike - Access combinations
-	 	Then routability should be
-		 | highway     | access     | vehicle    | bicycle    | bothw |
-		 | runway      | private    |            | yes        | x     |
-		 | footway     |            | no         | permissive | x     |
-		 | motorway    |            |            | yes        | x     |
-		 | track       | forestry   |            | permissive | x     |
-		 | cycleway    | yes        | designated | no         |       |
-		 | primary     |            | yes        | private    |       |
-		 | residential | permissive |            | no         |       |
+    Scenario: Bike - Access combinations
+        Then routability should be
+            | highway     | access     | vehicle    | bicycle    | forw | backw |
+            | runway      | private    |            | yes        | x    | x     |
+            | footway     |            | no         | permissive | x    | x     |
+            | motorway    |            |            | yes        | x    |       |
+            | track       | forestry   |            | permissive | x    | x     |
+            | cycleway    | yes        | designated | no         |      |       |
+            | primary     |            | yes        | private    |      |       |
+            | residential | permissive |            | no         |      |       |
 
-	Scenario: Bike - Ignore access tags for other modes
-	 	Then routability should be
-		 | highway  | boat | motor_vehicle | moped | bothw |
-		 | river    | yes  |               |       |       |
-		 | cycleway | no   |               |       | x     |
-		 | runway   |      | yes           |       |       |
-		 | cycleway |      | no            |       | x     |
-		 | runway   |      |               | yes   |       |
-		 | cycleway |      |               | no    | x     |
+    Scenario: Bike - Ignore access tags for other modes
+        Then routability should be
+            | highway  | boat | motor_vehicle | moped | bothw |
+            | river    | yes  |               |       |       |
+            | cycleway | no   |               |       | x     |
+            | runway   |      | yes           |       |       |
+            | cycleway |      | no            |       | x     |
+            | runway   |      |               | yes   |       |
+            | cycleway |      |               | no    | x     |
diff --git a/features/bicycle/access_node.feature b/features/bicycle/access_node.feature
index eba808d..5a6f2b5 100644
--- a/features/bicycle/access_node.feature
+++ b/features/bicycle/access_node.feature
@@ -1,64 +1,64 @@
 @routing @bicycle @access
 Feature: Bike - Access tags on nodes
-Reference: http://wiki.openstreetmap.org/wiki/Key:access
+# Reference: http://wiki.openstreetmap.org/wiki/Key:access
 
-	Background:
-		Given the profile "bicycle"
+    Background:
+        Given the profile "bicycle"
 
-	Scenario: Bike - Access tag hierachy on nodes
-		Then routability should be
-		 | node/access | node/vehicle | node/bicycle | bothw |
-		 |             |              |              | x     |
-		 | yes         |              |              | x     |
-		 | no          |              |              |       |
-		 |             | yes          |              | x     |
-		 |             | no           |              |       |
-		 | no          | yes          |              | x     |
-		 | yes         | no           |              |       |
-		 |             |              | yes          | x     |
-		 |             |              | no           |       |
-		 | no          |              | yes          | x     |
-		 | yes         |              | no           |       |
-		 |             | no           | yes          | x     |
-		 |             | yes          | no           |       |
+    Scenario: Bike - Access tag hierachy on nodes
+        Then routability should be
+            | node/access | node/vehicle | node/bicycle | bothw |
+            |             |              |              | x     |
+            | yes         |              |              | x     |
+            | no          |              |              |       |
+            |             | yes          |              | x     |
+            |             | no           |              |       |
+            | no          | yes          |              | x     |
+            | yes         | no           |              |       |
+            |             |              | yes          | x     |
+            |             |              | no           |       |
+            | no          |              | yes          | x     |
+            | yes         |              | no           |       |
+            |             | no           | yes          | x     |
+            |             | yes          | no           |       |
 
-	Scenario: Bike - Overwriting implied acccess on nodes
-		Then routability should be
-		 | highway  | node/access | node/vehicle | node/bicycle | bothw |
-		 | cycleway |             |              |              | x     |
-		 | runway   |             |              |              |       |
-		 | cycleway | no          |              |              |       |
-		 | cycleway |             | no           |              |       |
-		 | cycleway |             |              | no           |       |
-		 | runway   | yes         |              |              |       |
-		 | runway   |             | yes          |              |       |
-		 | runway   |             |              | yes          |       |
+    Scenario: Bike - Overwriting implied acccess on nodes doesn't overwrite way
+        Then routability should be
+            | highway  | node/access | node/vehicle | node/bicycle | bothw |
+            | cycleway |             |              |              | x     |
+            | runway   |             |              |              |       |
+            | cycleway | no          |              |              |       |
+            | cycleway |             | no           |              |       |
+            | cycleway |             |              | no           |       |
+            | runway   | yes         |              |              |       |
+            | runway   |             | yes          |              |       |
+            | runway   |             |              | yes          |       |
 
-	Scenario: Bike - Access tags on nodes
-	 	Then routability should be
-		 | node/access  | node/vehicle | node/bicycle | bothw |
-		 |              |              |              | x     |
-		 | yes          |              |              | x     |
-		 | permissive   |              |              | x     |
-		 | designated   |              |              | x     |
-		 | some_tag     |              |              | x     |
-		 | no           |              |              |       |
-		 | private      |              |              |       |
-		 | agricultural |              |              |       |
-		 | forestery    |              |              |       |
-		 |              | yes          |              | x     |
-		 |              | permissive   |              | x     |
-		 |              | designated   |              | x     |
-		 |              | some_tag     |              | x     |
-		 |              | no           |              |       |
-		 |              | private      |              |       |
-		 |              | agricultural |              |       |
-		 |              | forestery    |              |       |
-		 |              |              | yes          | x     |
-		 |              |              | permissive   | x     |
-		 |              |              | designated   | x     |
-		 |              |              | some_tag     | x     |
-		 |              |              | no           |       |
-		 |              |              | private      |       |
-		 |              |              | agricultural |       |
-		 |              |              | forestery    |       |
\ No newline at end of file
+    Scenario: Bike - Access tags on nodes
+        Then routability should be
+            | node/access  | node/vehicle | node/bicycle | bothw |
+            |              |              |              | x     |
+            | yes          |              |              | x     |
+            | permissive   |              |              | x     |
+            | designated   |              |              | x     |
+            | some_tag     |              |              | x     |
+            | no           |              |              |       |
+            | private      |              |              |       |
+            | agricultural |              |              |       |
+            | forestery    |              |              |       |
+            |              | yes          |              | x     |
+            |              | permissive   |              | x     |
+            |              | designated   |              | x     |
+            |              | some_tag     |              | x     |
+            |              | no           |              |       |
+            |              | private      |              |       |
+            |              | agricultural |              |       |
+            |              | forestery    |              |       |
+            |              |              | yes          | x     |
+            |              |              | permissive   | x     |
+            |              |              | designated   | x     |
+            |              |              | some_tag     | x     |
+            |              |              | no           |       |
+            |              |              | private      |       |
+            |              |              | agricultural |       |
+            |              |              | forestery    |       |
diff --git a/features/bicycle/area.feature b/features/bicycle/area.feature
index 541f026..062e86f 100644
--- a/features/bicycle/area.feature
+++ b/features/bicycle/area.feature
@@ -1,103 +1,103 @@
 @routing @bicycle @area
 Feature: Bike - Squares and other areas
 
-	Background:
-		Given the profile "bicycle"
-	
-	@square	
-	Scenario: Bike - Route along edge of a squares
-		Given the node map
-		 | x |   |
-		 | a | b |
-		 | d | c |
+    Background:
+        Given the profile "bicycle"
 
-		And the ways
-		 | nodes | area | highway     |
-		 | xa    |      | primary     |
-		 | abcda | yes  | residential |
-		
-		When I route I should get
-		 | from | to | route |
-		 | a    | b  | abcda |
-		 | a    | d  | abcda |
-		 | b    | c  | abcda |
-		 | c    | b  | abcda |
-		 | c    | d  | abcda |
-		 | d    | c  | abcda |
-		 | d    | a  | abcda |
-		 | a    | d  | abcda |
-	
-	@building
-	Scenario: Bike - Don't route on buildings
-		Given the node map
-		 | x |   |
-		 | a | b |
-		 | d | c |
+    @square
+    Scenario: Bike - Route along edge of a squares
+        Given the node map
+            | x |   |
+            | a | b |
+            | d | c |
 
-		And the ways
-		 | nodes | highway | area | building | access |
-		 | xa    | primary |      |          |        |
-		 | abcda | (nil)   | yes  | yes      | yes    |
+        And the ways
+            | nodes | area | highway     |
+            | xa    |      | primary     |
+            | abcda | yes  | residential |
 
-		When I route I should get
-		 | from | to | route |
-		 | a    | b  | xa    |
-		 | a    | d  | xa    |
-		 | b    | c  | xa    |
-		 | c    | b  | xa    |
-		 | c    | d  | xa    |
-		 | d    | c  | xa    |
-		 | d    | a  | xa    |
-		 | a    | d  | xa    |
-	
-	@parking
-	Scenario: Bike - parking areas
-		Given the node map
-		 | e |   |   | f |
-		 | x | a | b | y |
-		 |   | d | c |   |
+        When I route I should get
+            | from | to | route |
+            | a    | b  | abcda |
+            | a    | d  | abcda |
+            | b    | c  | abcda |
+            | c    | b  | abcda |
+            | c    | d  | abcda |
+            | d    | c  | abcda |
+            | d    | a  | abcda |
+            | a    | d  | abcda |
 
-		And the ways
-		 | nodes | highway | amenity |
-		 | xa    | primary |         |
-		 | by    | primary |         |
-		 | xefy  | primary |         |
-		 | abcda | (nil)   | parking |
+    @building
+    Scenario: Bike - Don't route on buildings
+        Given the node map
+            | x |   |
+            | a | b |
+            | d | c |
 
-		When I route I should get
-		 | from | to | route       |
-		 | x    | y  | xa,abcda,by |
-		 | y    | x  | by,abcda,xa |
-		 | a    | b  | abcda       |
-		 | a    | d  | abcda       |
-		 | b    | c  | abcda       |
-		 | c    | b  | abcda       |
-		 | c    | d  | abcda       |
-		 | d    | c  | abcda       |
-		 | d    | a  | abcda       |
-		 | a    | d  | abcda       |
-		
-	@train @platform
-	Scenario: Bike - railway platforms
-		Given the node map
-		 | x | a | b | y |
-		 |   | d | c |   |
+        And the ways
+            | nodes | highway | area | building | access |
+            | xa    | primary |      |          |        |
+            | abcda | (nil)   | yes  | yes      | yes    |
 
-		And the ways
-		 | nodes | highway | railway  |
-		 | xa    | primary |          |
-		 | by    | primary |          |
-		 | abcda | (nil)   | platform |
+        When I route I should get
+            | from | to | route |
+            | a    | b  | xa    |
+            | a    | d  | xa    |
+            | b    | c  | xa    |
+            | c    | b  | xa    |
+            | c    | d  | xa    |
+            | d    | c  | xa    |
+            | d    | a  | xa    |
+            | a    | d  | xa    |
 
-		When I route I should get
-		 | from | to | route       |
-		 | x    | y  | xa,abcda,by |
-		 | y    | x  | by,abcda,xa |
-		 | a    | b  | abcda       |
-		 | a    | d  | abcda       |
-		 | b    | c  | abcda       |
-		 | c    | b  | abcda       |
-		 | c    | d  | abcda       |
-		 | d    | c  | abcda       |
-		 | d    | a  | abcda       |
-		 | a    | d  | abcda       |
\ No newline at end of file
+    @parking
+    Scenario: Bike - parking areas
+        Given the node map
+            | e |   |   | f |
+            | x | a | b | y |
+            |   | d | c |   |
+
+        And the ways
+            | nodes | highway | amenity |
+            | xa    | primary |         |
+            | by    | primary |         |
+            | xefy  | primary |         |
+            | abcda | (nil)   | parking |
+
+        When I route I should get
+            | from | to | route       |
+            | x    | y  | xa,abcda,by |
+            | y    | x  | by,abcda,xa |
+            | a    | b  | abcda       |
+            | a    | d  | abcda       |
+            | b    | c  | abcda       |
+            | c    | b  | abcda       |
+            | c    | d  | abcda       |
+            | d    | c  | abcda       |
+            | d    | a  | abcda       |
+            | a    | d  | abcda       |
+
+    @train @platform
+    Scenario: Bike - railway platforms
+        Given the node map
+            | x | a | b | y |
+            |   | d | c |   |
+
+        And the ways
+            | nodes | highway | railway  |
+            | xa    | primary |          |
+            | by    | primary |          |
+            | abcda | (nil)   | platform |
+
+        When I route I should get
+            | from | to | route       |
+            | x    | y  | xa,abcda,by |
+            | y    | x  | by,abcda,xa |
+            | a    | b  | abcda       |
+            | a    | d  | abcda       |
+            | b    | c  | abcda       |
+            | c    | b  | abcda       |
+            | c    | d  | abcda       |
+            | d    | c  | abcda       |
+            | d    | a  | abcda       |
+            | a    | d  | abcda       |
diff --git a/features/bicycle/barrier.feature b/features/bicycle/barrier.feature
index ed387c1..d39a570 100644
--- a/features/bicycle/barrier.feature
+++ b/features/bicycle/barrier.feature
@@ -1,39 +1,39 @@
 @routing @bicycle @barrier
 Feature: Barriers
 
-	Background:
-		Given the profile "bicycle"
+    Background:
+        Given the profile "bicycle"
 
-	Scenario: Bike - Barriers 
-		Then routability should be
-		 | node/barrier   | bothw |
-		 |                | x     |
-		 | bollard        | x     |
-		 | gate           | x     |
-		 | cycle_barrier  | x     |
-		 | cattle_grid    | x     |
-		 | border_control | x     |
-		 | toll_booth     | x     |
-		 | sally_port     | x     |
-		 | entrance       | x     |
-		 | wall           |       |
-		 | fence          |       |
-		 | some_tag       |       |
+    Scenario: Bike - Barriers
+        Then routability should be
+            | node/barrier   | bothw |
+            |                | x     |
+            | bollard        | x     |
+            | gate           | x     |
+            | cycle_barrier  | x     |
+            | cattle_grid    | x     |
+            | border_control | x     |
+            | toll_booth     | x     |
+            | sally_port     | x     |
+            | entrance       | x     |
+            | wall           |       |
+            | fence          |       |
+            | some_tag       |       |
 
-	Scenario: Bike - Access tag trumphs barriers
-		Then routability should be
-		 | node/barrier | node/access   | bothw |
-		 | bollard      |               | x     |
-		 | bollard      | yes           | x     |
-		 | bollard      | permissive    | x     |
-		 | bollard      | designated    | x     |
-		 | bollard      | no            |       |
-		 | bollard      | private       |       |
-		 | bollard      | agricultural  |       |
-		 | wall         |               |       |
-		 | wall         | yes           | x     |
-		 | wall         | permissive    | x     |
-		 | wall         | designated    | x     |
-		 | wall         | no            |       |
-		 | wall         | private       |       |
-		 | wall         | agricultural  |       |
+    Scenario: Bike - Access tag trumphs barriers
+        Then routability should be
+            | node/barrier | node/access  | bothw |
+            | bollard      |              | x     |
+            | bollard      | yes          | x     |
+            | bollard      | permissive   | x     |
+            | bollard      | designated   | x     |
+            | bollard      | no           |       |
+            | bollard      | private      |       |
+            | bollard      | agricultural |       |
+            | wall         |              |       |
+            | wall         | yes          | x     |
+            | wall         | permissive   | x     |
+            | wall         | designated   | x     |
+            | wall         | no           |       |
+            | wall         | private      |       |
+            | wall         | agricultural |       |
diff --git a/features/bicycle/cycleway.feature b/features/bicycle/cycleway.feature
index f260294..643fdce 100644
--- a/features/bicycle/cycleway.feature
+++ b/features/bicycle/cycleway.feature
@@ -1,81 +1,81 @@
 @routing @bicycle @cycleway
 Feature: Bike - Cycle tracks/lanes
-Reference: http://wiki.openstreetmap.org/wiki/Key:cycleway
+# Reference: http://wiki.openstreetmap.org/wiki/Key:cycleway
 
-	Background:
-		Given the profile "bicycle"
-		
-	Scenario: Bike - Cycle tracks/lanes should enable biking		
-	 	Then routability should be
-		 | highway     | cycleway     | bothw |
-		 | motorway    |              |       |
-		 | motorway    | track        | x     |
-		 | motorway    | lane         | x     |
-		 | motorway    | shared       | x     |
-		 | motorway    | share_busway | x     |
-		 | motorway    | sharrow      | x     |
-		 | some_tag    | track        | x     |
-		 | some_tag    | lane         | x     |
-		 | some_tag    | shared       | x     |
-		 | some_tag    | share_busway | x     |
-		 | some_tag    | sharrow      | x     |
-		 | residential | track        | x     |
-		 | residential | lane         | x     |
-		 | residential | shared       | x     |
-		 | residential | share_busway | x     |
-		 | residential | sharrow      | x     |
+    Background:
+        Given the profile "bicycle"
 
-	Scenario: Bike - Left/right side cycleways on implied bidirectionals   
-	 	Then routability should be
-		 | highway | cycleway | cycleway:left | cycleway:right | forw | backw |
-		 | primary |          |               |                | x    | x     |
-		 | primary | track    |               |                | x    | x     |
-		 | primary | opposite |               |                | x    | x     |
-		 | primary |          | track         |                | x    | x     |
-		 | primary |          | opposite      |                | x    | x     |
-		 | primary |          |               | track          | x    | x     |
-		 | primary |          |               | opposite       | x    | x     |
-		 | primary |          | track         | track          | x    | x     |
-		 | primary |          | opposite      | opposite       | x    | x     |
-		 | primary |          | track         | opposite       | x    | x     |
-		 | primary |          | opposite      | track          | x    | x     |
+    Scenario: Bike - Cycle tracks/lanes should enable biking
+        Then routability should be
+            | highway     | cycleway     | forw | backw |
+            | motorway    |              |      |       |
+            | motorway    | track        | x    |       |
+            | motorway    | lane         | x    |       |
+            | motorway    | shared       | x    |       |
+            | motorway    | share_busway | x    |       |
+            | motorway    | sharrow      | x    |       |
+            | some_tag    | track        | x    | x     |
+            | some_tag    | lane         | x    | x     |
+            | some_tag    | shared       | x    | x     |
+            | some_tag    | share_busway | x    | x     |
+            | some_tag    | sharrow      | x    | x     |
+            | residential | track        | x    | x     |
+            | residential | lane         | x    | x     |
+            | residential | shared       | x    | x     |
+            | residential | share_busway | x    | x     |
+            | residential | sharrow      | x    | x     |
 
-	Scenario: Bike - Left/right side cycleways on implied oneways   
-	 	Then routability should be
-		 | highway  | cycleway | cycleway:left | cycleway:right | forw | backw |
-		 | primary  |          |               |                | x    | x     |
-		 | motorway |          |               |                |      |       |
-		 | motorway | track    |               |                | x    |       |
-		 | motorway | opposite |               |                |      | x     |
-		 | motorway |          | track         |                |      | x     |
-		 | motorway |          | opposite      |                |      | x     |
-		 | motorway |          |               | track          | x    |       |
-		 | motorway |          |               | opposite       | x    |       |
-		 | motorway |          | track         | track          | x    | x     |
-		 | motorway |          | opposite      | opposite       | x    | x     |
-		 | motorway |          | track         | opposite       | x    | x     |
-		 | motorway |          | opposite      | track          | x    | x     |
+    Scenario: Bike - Left/right side cycleways on implied bidirectionals
+        Then routability should be
+            | highway | cycleway | cycleway:left | cycleway:right | forw | backw |
+            | primary |          |               |                | x    | x     |
+            | primary | track    |               |                | x    | x     |
+            | primary | opposite |               |                | x    | x     |
+            | primary |          | track         |                | x    | x     |
+            | primary |          | opposite      |                | x    | x     |
+            | primary |          |               | track          | x    | x     |
+            | primary |          |               | opposite       | x    | x     |
+            | primary |          | track         | track          | x    | x     |
+            | primary |          | opposite      | opposite       | x    | x     |
+            | primary |          | track         | opposite       | x    | x     |
+            | primary |          | opposite      | track          | x    | x     |
 
-	Scenario: Bike - Invalid cycleway tags		
-	 	Then routability should be
-		 | highway  | cycleway   | bothw |
-		 | primary  |            | x     |
-		 | primary  | yes        | x     |
-		 | primary  | no         | x     |
-		 | primary  | some_track | x     |
-		 | motorway |            |       |
-		 | motorway | yes        |       |
-		 | motorway | no         |       |
-		 | motorway | some_track |       |
-			
-	Scenario: Bike - Access tags should overwrite cycleway access		
-	 	Then routability should be
-		 | highway     | cycleway | access | bothw |
-		 | motorway    | track    | no     |       |
-		 | residential | track    | no     |       |
-		 | footway     | track    | no     |       |
-		 | cycleway    | track    | no     |       |
-		 | motorway    | lane     | yes    | x     |
-		 | residential | lane     | yes    | x     |
-		 | footway     | lane     | yes    | x     |
-		 | cycleway    | lane     | yes    | x     |
+    Scenario: Bike - Left/right side cycleways on implied oneways
+        Then routability should be
+            | highway  | cycleway | cycleway:left | cycleway:right | forw | backw |
+            | primary  |          |               |                | x    | x     |
+            | motorway |          |               |                |      |       |
+            | motorway | track    |               |                | x    |       |
+            | motorway | opposite |               |                |      | x     |
+            | motorway |          | track         |                |      | x     |
+            | motorway |          | opposite      |                |      | x     |
+            | motorway |          |               | track          | x    |       |
+            | motorway |          |               | opposite       | x    |       |
+            | motorway |          | track         | track          | x    | x     |
+            | motorway |          | opposite      | opposite       | x    | x     |
+            | motorway |          | track         | opposite       | x    | x     |
+            | motorway |          | opposite      | track          | x    | x     |
+
+    Scenario: Bike - Invalid cycleway tags
+        Then routability should be
+            | highway  | cycleway   | bothw |
+            | primary  |            | x     |
+            | primary  | yes        | x     |
+            | primary  | no         | x     |
+            | primary  | some_track | x     |
+            | motorway |            |       |
+            | motorway | yes        |       |
+            | motorway | no         |       |
+            | motorway | some_track |       |
+
+    Scenario: Bike - Access tags should overwrite cycleway access
+        Then routability should be
+            | highway     | cycleway | access | forw | backw |
+            | motorway    | track    | no     |      |       |
+            | residential | track    | no     |      |       |
+            | footway     | track    | no     |      |       |
+            | cycleway    | track    | no     |      |       |
+            | motorway    | lane     | yes    | x    |       |
+            | residential | lane     | yes    | x    | x     |
+            | footway     | lane     | yes    | x    | x     |
+            | cycleway    | lane     | yes    | x    | x     |
diff --git a/features/bicycle/destination.feature b/features/bicycle/destination.feature
index b3f8b5b..9c71198 100644
--- a/features/bicycle/destination.feature
+++ b/features/bicycle/destination.feature
@@ -1,77 +1,77 @@
 @routing @bicycle @destination @todo
 Feature: Bike - Destination only, no passing through
 
-	Background:
-		Given the profile "bicycle"
-		
-	Scenario: Bike - Destination only street
-		Given the node map
-		 | a |   |   |   | e |
-		 |   | b | c | d |   |
-		 |   |   |   |   |   |
-		 | x |   |   |   | y |
+    Background:
+        Given the profile "bicycle"
 
-		And the ways
-		 | nodes | access      |
-		 | ab    |             |
-		 | bcd   | destination |
-		 | de    |             |
-		 | axye  |             |
+    Scenario: Bike - Destination only street
+        Given the node map
+            | a |   |   |   | e |
+            |   | b | c | d |   |
+            |   |   |   |   |   |
+            | x |   |   |   | y |
 
-		When I route I should get
-		 | from | to | route     |
-		 | a    | b  | ab        |
-		 | a    | c  | ab,bcd    |
-		 | a    | d  | ab,bcd    |
-		 | a    | e  | axye      |
-		 | e    | d  | de        |
-		 | e    | c  | de,bcd    |
-		 | e    | b  | de,bcd    |
-		 | e    | a  | axye      |
-		
-	Scenario: Bike - Destination only street
-		Given the node map
-		 | a |   |   |   | e |
-		 |   | b | c | d |   |
-		 |   |   |   |   |   |
-		 | x |   |   |   | y |
+        And the ways
+            | nodes | access      |
+            | ab    |             |
+            | bcd   | destination |
+            | de    |             |
+            | axye  |             |
 
-		And the ways
-		 | nodes | access      |
-		 | ab    |             |
-		 | bc    | destination |
-		 | cd    | destination |
-		 | de    |             |
-		 | axye  |             |
+        When I route I should get
+            | from | to | route  |
+            | a    | b  | ab     |
+            | a    | c  | ab,bcd |
+            | a    | d  | ab,bcd |
+            | a    | e  | axye   |
+            | e    | d  | de     |
+            | e    | c  | de,bcd |
+            | e    | b  | de,bcd |
+            | e    | a  | axye   |
 
-		When I route I should get
-		 | from | to | route    |
-		 | a    | b  | ab       |
-		 | a    | c  | ab,bc    |
-		 | a    | d  | ab,bc,cd |
-		 | a    | e  | axye     |
-		 | e    | d  | de       |
-		 | e    | c  | de,dc    |
-		 | e    | b  | de,dc,bc |
-		 | e    | a  | axye     |
+    Scenario: Bike - Destination only street
+        Given the node map
+            | a |   |   |   | e |
+            |   | b | c | d |   |
+            |   |   |   |   |   |
+            | x |   |   |   | y |
 
-	Scenario: Bike - Routing inside a destination only area
-		Given the node map
-		 | a |   | c |   | e |
-		 |   | b |   | d |   |
-		 | x |   |   |   | y |
+        And the ways
+            | nodes | access      |
+            | ab    |             |
+            | bc    | destination |
+            | cd    | destination |
+            | de    |             |
+            | axye  |             |
 
-		And the ways
-		 | nodes | access      |
-		 | ab    | destination |
-		 | bc    | destination |
-		 | cd    | destination |
-		 | de    | destination |
-		 | axye  |             |
+        When I route I should get
+            | from | to | route    |
+            | a    | b  | ab       |
+            | a    | c  | ab,bc    |
+            | a    | d  | ab,bc,cd |
+            | a    | e  | axye     |
+            | e    | d  | de       |
+            | e    | c  | de,dc    |
+            | e    | b  | de,dc,bc |
+            | e    | a  | axye     |
 
-		When I route I should get
-		 | from | to | route       |
-		 | a    | e  | ab,bc,cd,de |
-		 | e    | a  | de,cd,bc,ab |
-		 | b    | d  | bc,cd       |
-		 | d    | b  | cd,bc       |
\ No newline at end of file
+    Scenario: Bike - Routing inside a destination only area
+        Given the node map
+            | a |   | c |   | e |
+            |   | b |   | d |   |
+            | x |   |   |   | y |
+
+        And the ways
+            | nodes | access      |
+            | ab    | destination |
+            | bc    | destination |
+            | cd    | destination |
+            | de    | destination |
+            | axye  |             |
+
+        When I route I should get
+            | from | to | route       |
+            | a    | e  | ab,bc,cd,de |
+            | e    | a  | de,cd,bc,ab |
+            | b    | d  | bc,cd       |
+            | d    | b  | cd,bc       |
diff --git a/features/bicycle/ferry.feature b/features/bicycle/ferry.feature
index 5d67df7..85c925f 100644
--- a/features/bicycle/ferry.feature
+++ b/features/bicycle/ferry.feature
@@ -1,63 +1,63 @@
 @routing @bicycle @ferry
 Feature: Bike - Handle ferry routes
 
-	Background:
-		Given the profile "bicycle"
-	
-	Scenario: Bike - Ferry route
-		Given the node map
-		 | a | b | c |   |   |
-		 |   |   | d |   |   |
-		 |   |   | e | f | g |
-	
-		And the ways
-		 | nodes | highway | route | bicycle |
-		 | abc   | primary |       |         |
-		 | cde   |         | ferry | yes     |
-		 | efg   | primary |       |         |
-   
-		When I route I should get
-		 | from | to | route       |
-		 | a    | g  | abc,cde,efg |
-		 | b    | f  | abc,cde,efg |
-		 | e    | c  | cde         |
-		 | e    | b  | cde,abc     |
-		 | e    | a  | cde,abc     |
-		 | c    | e  | cde         |
-		 | c    | f  | cde,efg     |
-		 | c    | g  | cde,efg     |
-
-	Scenario: Bike - Ferry duration, single node
-		Given the node map
-		 | a | b | c | d |
-		 |   |   | e | f |
-		 |   |   | g | h |
-		 |   |   | i | j |
-		 
-		And the ways
-		 | nodes | highway | route | bicycle | duration |
-		 | ab    | primary |       |         |          |
-		 | cd    | primary |       |         |          |
-		 | ef    | primary |       |         |          |
-		 | gh    | primary |       |         |          |
-		 | ij    | primary |       |         |          |
-		 | bc    |         | ferry | yes     | 0:01     |
-		 | be    |         | ferry | yes     | 0:10     |
-		 | bg    |         | ferry | yes     | 1:00     |
-		 | bi    |         | ferry | yes     | 10:00    |
-
-	Scenario: Bike - Ferry duration, multiple nodes
-		Given the node map
-		  | x |   |   |   |   | y |
-		  |   | a | b | c | d |   |
-
-		And the ways
-		 | nodes | highway | route | bicycle | duration |
-		 | xa    | primary |       |         |          |
-		 | yd    | primary |       |         |          |
-		 | abcd  |         | ferry | yes     | 1:00     |
-
-		When I route I should get
-		 | from | to | route | time       |
-		 | a    | d  | abcd  | 3600s +-10 |
-		 | d    | a  | abcd  | 3600s +-10 |
+    Background:
+        Given the profile "bicycle"
+
+    Scenario: Bike - Ferry route
+        Given the node map
+            | a | b | c |   |   |
+            |   |   | d |   |   |
+            |   |   | e | f | g |
+
+        And the ways
+            | nodes | highway | route | bicycle |
+            | abc   | primary |       |         |
+            | cde   |         | ferry | yes     |
+            | efg   | primary |       |         |
+
+        When I route I should get
+            | from | to | route       |
+            | a    | g  | abc,cde,efg |
+            | b    | f  | abc,cde,efg |
+            | e    | c  | cde         |
+            | e    | b  | cde,abc     |
+            | e    | a  | cde,abc     |
+            | c    | e  | cde         |
+            | c    | f  | cde,efg     |
+            | c    | g  | cde,efg     |
+
+    Scenario: Bike - Ferry duration, single node
+        Given the node map
+            | a | b | c | d |
+            |   |   | e | f |
+            |   |   | g | h |
+            |   |   | i | j |
+
+        And the ways
+            | nodes | highway | route | bicycle | duration |
+            | ab    | primary |       |         |          |
+            | cd    | primary |       |         |          |
+            | ef    | primary |       |         |          |
+            | gh    | primary |       |         |          |
+            | ij    | primary |       |         |          |
+            | bc    |         | ferry | yes     | 0:01     |
+            | be    |         | ferry | yes     | 0:10     |
+            | bg    |         | ferry | yes     | 1:00     |
+            | bi    |         | ferry | yes     | 10:00    |
+
+    Scenario: Bike - Ferry duration, multiple nodes
+        Given the node map
+            | x |   |   |   |   | y |
+            |   | a | b | c | d |   |
+
+        And the ways
+            | nodes | highway | route | bicycle | duration |
+            | xa    | primary |       |         |          |
+            | yd    | primary |       |         |          |
+            | abcd  |         | ferry | yes     | 1:00     |
+
+        When I route I should get
+            | from | to | route | time       |
+            | a    | d  | abcd  | 3600s +-10 |
+            | d    | a  | abcd  | 3600s +-10 |
diff --git a/features/bicycle/maxspeed.feature b/features/bicycle/maxspeed.feature
index 9924f55..ba5bfba 100644
--- a/features/bicycle/maxspeed.feature
+++ b/features/bicycle/maxspeed.feature
@@ -1,70 +1,88 @@
 @routing @maxspeed @bicycle
 Feature: Bike - Max speed restrictions
 
-	Background: Use specific speeds
-		Given the profile "bicycle"
+    Background: Use specific speeds
+        Given the profile "bicycle"
+        And a grid size of 1000 meters
 
-	Scenario: Bicycle - Respect maxspeeds when lower that way type speed
-    	Then routability should be
-    	 | highway     | maxspeed | bothw    |
-    	 | residential |          | 49s ~10% |
-    	 | residential | 10       | 72s ~10% |
+    Scenario: Bicycle - Respect maxspeeds when lower that way type speed
+        Then routability should be
+            | highway     | maxspeed | bothw   |
+            | residential |          | 15 km/h |
+            | residential | 10       | 10 km/h |
+
+    Scenario: Bicycle - Ignore maxspeed when higher than way speed
+        Then routability should be
+            | highway     | maxspeed | bothw   |
+            | residential |          | 15 km/h |
+            | residential | 80       | 15 km/h |
 
-	Scenario: Bicycle - Ignore maxspeed when higher than way speed
-    	Then routability should be
-    	 | highway     | maxspeed | bothw    |
-    	 | residential |          | 49s ~10% |
-    	 | residential | 80       | 49s ~10% |
-    
     @todo
-  	Scenario: Bicycle - Maxspeed formats
- 		Then routability should be
- 		 | highway     | maxspeed  | bothw     |
- 		 | residential |           | 49s ~10%  |
- 		 | residential | 5         | 144s ~10% |
- 		 | residential | 5mph      | 90s ~10%  |
- 		 | residential | 5 mph     | 90s ~10%  |
- 		 | residential | 5MPH      | 90s ~10%  |
- 		 | residential | 5 MPH     | 90s ~10%  |
- 		 | trunk       | 5unknown  | 49s ~10%  |
- 		 | trunk       | 5 unknown | 49s ~10%  |
+    Scenario: Bicycle - Maxspeed formats
+        Then routability should be
+            | highway     | maxspeed  | bothw     |
+            | residential |           | 49s ~10%  |
+            | residential | 5         | 144s ~10% |
+            | residential | 5mph      | 90s ~10%  |
+            | residential | 5 mph     | 90s ~10%  |
+            | residential | 5MPH      | 90s ~10%  |
+            | residential | 5 MPH     | 90s ~10%  |
+            | trunk       | 5unknown  | 49s ~10%  |
+            | trunk       | 5 unknown | 49s ~10%  |
 
     @todo
-   	Scenario: Bicycle - Maxspeed special tags
-  		Then routability should be
-  		 | highway     | maxspeed | bothw    |
-  		 | residential |          | 49s ~10% |
-  		 | residential | none     | 49s ~10% |
-  		 | residential | signals  | 49s ~10% |
+    Scenario: Bicycle - Maxspeed special tags
+        Then routability should be
+            | highway     | maxspeed | bothw    |
+            | residential |          | 49s ~10% |
+            | residential | none     | 49s ~10% |
+            | residential | signals  | 49s ~10% |
 
-	Scenario: Bike - Do not use maxspeed when higher that way type speed
-		Given the node map
-		 | a | b | c |
+    Scenario: Bike - Do not use maxspeed when higher that way type speed
+        Given the node map
+            | a | b | c |
 
-		And the ways
-		 | nodes | highway     | maxspeed |
-		 | ab    | residential |          |
-		 | bc    | residential | 80       |
+        And the ways
+            | nodes | highway     | maxspeed |
+            | ab    | residential |          |
+            | bc    | residential | 80       |
 
-		When I route I should get
-		 | from | to | route | time    |
-		 | a    | b  | ab    | 24s ~5% |
-		 | b    | c  | bc    | 24s ~5% |
+        When I route I should get
+            | from | to | route | speed   |
+            | a    | b  | ab    | 15 km/h |
+            | b    | c  | bc    | 15 km/h |
 
-     Scenario: Bike - Forward/backward maxspeed
+    Scenario: Bike - Forward/backward maxspeed
         Given the shortcuts
- 		 | key   | value    |
- 		 | bike  | 49s ~10% |
- 		 | run   | 73s ~10% |
- 		 | walk  | 145s ~10% |
- 		 | snail | 720s ~10% |
+            | key   | value     |
+            | bike  | 49s ~10%  |
+            | run   | 73s ~10%  |
+            | walk  | 145s ~10% |
+            | snail | 720s ~10% |
+
+        Then routability should be
+            | maxspeed | maxspeed:forward | maxspeed:backward | forw    | backw   |
+            |          |                  |                   | 15 km/h | 15 km/h |
+            | 10       |                  |                   | 10 km/h | 10 km/h |
+            |          | 10               |                   | 10 km/h | 15 km/h |
+            |          |                  | 10                | 15 km/h | 10 km/h |
+            | 2        | 10               |                   | 10 km/h | 2 km/h  |
+            | 2        |                  | 10                | 2 km/h  | 10 km/h |
+            | 2        | 5                | 10                | 5 km/h  | 10 km/h |
 
-  	 	Then routability should be
-     	 | maxspeed | maxspeed:forward | maxspeed:backward | forw  | backw |
-     	 |          |                  |                   | bike  | bike   |
-     	 | 10       |                  |                   | run   | run    |
-     	 |          | 10               |                   | run   | bike   |
-     	 |          |                  | 10                | bike  | run    |
-     	 | 1        | 10               |                   | run   | snail  |
-     	 | 1        |                  | 10                | snail | run    |
-     	 | 1        | 5                | 10                | walk  | run    |
+    Scenario: Bike - Maxspeed should not allow routing on unroutable ways
+        Then routability should be
+            | highway   | railway | access | maxspeed | maxspeed:forward | maxspeed:backward | bothw |
+            | primary   |         |        |          |                  |                   | x     |
+            | secondary |         | no     |          |                  |                   |       |
+            | secondary |         | no     | 100      |                  |                   |       |
+            | secondary |         | no     |          | 100              |                   |       |
+            | secondary |         | no     |          |                  | 100               |       |
+            | (nil)     | train   |        |          |                  |                   |       |
+            | (nil)     | train   |        | 100      |                  |                   |       |
+            | (nil)     | train   |        |          | 100              |                   |       |
+            | (nil)     | train   |        |          |                  | 100               |       |
+            | runway    |         |        |          |                  |                   |       |
+            | runway    |         |        | 100      |                  |                   |       |
+            | runway    |         |        |          | 100              |                   |       |
+            | runway    |         |        |          |                  | 100               |       |
diff --git a/features/bicycle/mode.feature b/features/bicycle/mode.feature
index c24af46..eac0430 100644
--- a/features/bicycle/mode.feature
+++ b/features/bicycle/mode.feature
@@ -1,89 +1,89 @@
 @routing @bicycle @mode
 Feature: Bike - Mode flag
 
-	Background:
-		Given the profile "bicycle"
-    
+    Background:
+        Given the profile "bicycle"
+
     @todo
     Scenario: Bike - Mode when using a ferry
-    	Given the node map
-    	 | a | b |   |
-    	 |   | c | d |
+        Given the node map
+            | a | b |   |
+            |   | c | d |
 
-    	And the ways
-    	 | nodes | highway | route | duration |
-    	 | ab    | primary |       |          |
-    	 | bc    |         | ferry | 0:01     |
-    	 | cd    | primary |       |          |
+        And the ways
+            | nodes | highway | route | duration |
+            | ab    | primary |       |          |
+            | bc    |         | ferry | 0:01     |
+            | cd    | primary |       |          |
 
-    	When I route I should get
-    	 | from | to | route    | turns                        | modes           |
-    	 | a    | d  | ab,bc,cd | head,right,left, destination | bike,ferry,bike |
-    	 | d    | a  | cd,bc,ab | head,right,left, destination | bike,ferry,bike |
-    	 | c    | a  | bc,ab    | head,left,destination        | ferry,bike      |
-    	 | d    | b  | cd,bc    | head,right,destination       | bike,ferry      |
-    	 | a    | c  | ab,bc    | head,right,destination       | bike,ferry      |
-    	 | b    | d  | bc,cd    | head,left,destination        | ferry,bike      |
+        When I route I should get
+            | from | to | route    | turns                        | modes           |
+            | a    | d  | ab,bc,cd | head,right,left, destination | bike,ferry,bike |
+            | d    | a  | cd,bc,ab | head,right,left, destination | bike,ferry,bike |
+            | c    | a  | bc,ab    | head,left,destination        | ferry,bike      |
+            | d    | b  | cd,bc    | head,right,destination       | bike,ferry      |
+            | a    | c  | ab,bc    | head,right,destination       | bike,ferry      |
+            | b    | d  | bc,cd    | head,left,destination        | ferry,bike      |
 
-     @todo
-     Scenario: Bike - Mode when pushing bike against oneways
-     	Given the node map
-     	 | a | b |   |
-     	 |   | c | d |
+    @todo
+    Scenario: Bike - Mode when pushing bike against oneways
+        Given the node map
+            | a | b |   |
+            |   | c | d |
 
-     	And the ways
-     	 | nodes | highway | oneway |
-     	 | ab    | primary |        |
-     	 | bc    | primary | yes    |
-     	 | cd    | primary |        |
+        And the ways
+            | nodes | highway | oneway |
+            | ab    | primary |        |
+            | bc    | primary | yes    |
+            | cd    | primary |        |
 
-     	When I route I should get
-     	 | from | to | route    | turns                       | modes          |
-     	 | a    | d  | ab,bc,cd | head,right,left,destination | bike,push,bike |
-     	 | d    | a  | cd,bc,ab | head,right,left,destination | bike,push,bike |
-     	 | c    | a  | bc,ab    | head,left,destination       | push,bike      |
-     	 | d    | b  | cd,bc    | head,right,destination      | bike,push      |
-     	 | a    | c  | ab,bc    | head,right,destination      | bike,push      |
-     	 | b    | d  | bc,cd    | head,left,destination       | push,bike      |
+        When I route I should get
+            | from | to | route    | turns                       | modes          |
+            | a    | d  | ab,bc,cd | head,right,left,destination | bike,push,bike |
+            | d    | a  | cd,bc,ab | head,right,left,destination | bike,push,bike |
+            | c    | a  | bc,ab    | head,left,destination       | push,bike      |
+            | d    | b  | cd,bc    | head,right,destination      | bike,push      |
+            | a    | c  | ab,bc    | head,right,destination      | bike,push      |
+            | b    | d  | bc,cd    | head,left,destination       | push,bike      |
 
-     @todo
-     Scenario: Bike - Mode when pushing on pedestrain streets
-     	Given the node map
-     	 | a | b |   |
-     	 |   | c | d |
+    @todo
+    Scenario: Bike - Mode when pushing on pedestrain streets
+        Given the node map
+            | a | b |   |
+            |   | c | d |
 
-     	And the ways
-     	 | nodes | highway    |
-     	 | ab    | primary    |
-     	 | bc    | pedestrian |
-     	 | cd    | primary    |
+        And the ways
+            | nodes | highway    |
+            | ab    | primary    |
+            | bc    | pedestrian |
+            | cd    | primary    |
 
-     	When I route I should get
-     	 | from | to | route    | turns                       | modes          |
-     	 | a    | d  | ab,bc,cd | head,right,left,destination | bike,push,bike |
-     	 | d    | a  | cd,bc,ab | head,right,left,destination | bike,push,bike |
-     	 | c    | a  | bc,ab    | head,left,destination       | push,bike      |
-     	 | d    | b  | cd,bc    | head,right,destination      | bike,push      |
-     	 | a    | c  | ab,bc    | head,right,destination      | bike,push      |
-     	 | b    | d  | bc,cd    | head,left,destination       | push,bike      |
+        When I route I should get
+            | from | to | route    | turns                       | modes          |
+            | a    | d  | ab,bc,cd | head,right,left,destination | bike,push,bike |
+            | d    | a  | cd,bc,ab | head,right,left,destination | bike,push,bike |
+            | c    | a  | bc,ab    | head,left,destination       | push,bike      |
+            | d    | b  | cd,bc    | head,right,destination      | bike,push      |
+            | a    | c  | ab,bc    | head,right,destination      | bike,push      |
+            | b    | d  | bc,cd    | head,left,destination       | push,bike      |
 
-     @todo
-     Scenario: Bike - Mode when pushing on pedestrain areas
-     	Given the node map
-     	 | a | b |   |   |
-     	 |   | c | d | f |
+    @todo
+    Scenario: Bike - Mode when pushing on pedestrain areas
+        Given the node map
+            | a | b |   |   |
+            |   | c | d | f |
 
-     	And the ways
-     	 | nodes | highway    | area |
-     	 | ab    | primary    |      |
-     	 | bcd   | pedestrian | yes  |
-     	 | df    | primary    |      |
+        And the ways
+            | nodes | highway    | area |
+            | ab    | primary    |      |
+            | bcd   | pedestrian | yes  |
+            | df    | primary    |      |
 
-     	When I route I should get
-     	 | from | to | route     | modes          |
-     	 | a    | f  | ab,bcd,df | bike,push,bike |
-     	 | f    | a  | df,bcd,ab | bike,push,bike |
-     	 | d    | a  | bcd,ab    | push,bike      |
-     	 | f    | b  | df,bcd    | bike,push      |
-     	 | a    | d  | ab,bcd    | bike,push      |
-     	 | b    | f  | bcd,df    | push,bike      |
+        When I route I should get
+            | from | to | route     | modes          |
+            | a    | f  | ab,bcd,df | bike,push,bike |
+            | f    | a  | df,bcd,ab | bike,push,bike |
+            | d    | a  | bcd,ab    | push,bike      |
+            | f    | b  | df,bcd    | bike,push      |
+            | a    | d  | ab,bcd    | bike,push      |
+            | b    | f  | bcd,df    | push,bike      |
diff --git a/features/bicycle/names.feature b/features/bicycle/names.feature
index d8a1ecf..b0e2ec0 100644
--- a/features/bicycle/names.feature
+++ b/features/bicycle/names.feature
@@ -1,49 +1,33 @@
 @routing @bicycle @names
 Feature: Bike - Street names in instructions
 
-	Background:
-		Given the profile "bicycle"
-	
-	Scenario: Bike - A named street
-		Given the node map
-		 | a | b |
-		 |   | c |
-	
-		And the ways
-		 | nodes | name     |
-		 | ab    | My Way   |
-		 | bc    | Your Way |
-    
-		When I route I should get
-		 | from | to | route           |
-		 | a    | c  | My Way,Your Way |
-	
-	@unnamed
-	Scenario: Bike - Use way type to describe unnamed ways
-		Given the node map
-		 | a | b | c | d |
+    Background:
+        Given the profile "bicycle"
 
-		And the ways
-		 | nodes | highway  | name |
-		 | ab    | cycleway |      |
-		 | bcd   | track    |      |
+    Scenario: Bike - A named street
+        Given the node map
+            | a | b |
+            |   | c |
 
-		When I route I should get
-		 | from | to | route                              |
-		 | a    | d  | {highway:cycleway},{highway:track} |
+        And the ways
+            | nodes | name     |
+            | ab    | My Way   |
+            | bc    | Your Way |
 
-  	@area @names @todo
-  	Scenario: Bike - name on streets overlapping an area
-  		Given the node map
-  		 | x | a | b | y |
-  		 |   | d | c |   |
+        When I route I should get
+            | from | to | route           |
+            | a    | c  | My Way,Your Way |
 
-  		And the ways
-  		 | nodes | highway     | area |
-  		 | xaby  | residential |      |
-  		 | abcda | residential | yes  |
+    @unnamed
+    Scenario: Bike - Use way type to describe unnamed ways
+        Given the node map
+            | a | b | c | d |
 
-  		When I route I should get
-  		 | from | to | route |
-  		 | x    | y  | xaby  |
-  		 | y    | x  | xaby  |
+        And the ways
+            | nodes | highway  | name |
+            | ab    | cycleway |      |
+            | bcd   | track    |      |
+
+        When I route I should get
+            | from | to | route                              |
+            | a    | d  | {highway:cycleway},{highway:track} |
diff --git a/features/bicycle/oneway.feature b/features/bicycle/oneway.feature
index ee0d713..4dd9e1f 100644
--- a/features/bicycle/oneway.feature
+++ b/features/bicycle/oneway.feature
@@ -1,128 +1,128 @@
 @routing @bicycle @oneway
 Feature: Bike - Oneway streets
-Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing
-Usually we can push bikes against oneways, but we use foot=no to prevent this in these tests
-
-	Background:
-		Given the profile "bicycle"
-	
-	Scenario: Bike - Simple oneway
-		Then routability should be
-		 | highway | foot | oneway | forw | backw |
-		 | primary | no   | yes    | x    |       |
-
-	Scenario: Simple reverse oneway
-		Then routability should be
-		 | highway | foot | oneway | forw | backw |
-		 | primary | no   | -1     |      | x     |
-
-	Scenario: Bike - Around the Block
-		Given the node map
-		 | a | b |
-		 | d | c |
-	
-		And the ways
-		 | nodes | oneway | foot |
-		 | ab    | yes    | no   |
-		 | bc    |        | no   |
-		 | cd    |        | no   |
-		 | da    |        | no   |
-    
-		When I route I should get
-		 | from | to | route    |
-		 | a    | b  | ab       |
-		 | b    | a  | bc,cd,da |
-	
-	Scenario: Bike - Handle various oneway tag values
-	 	Then routability should be
-		 | foot | oneway   | forw | backw |
-		 | no   |          | x    | x     |
-		 | no   | nonsense | x    | x     |
-		 | no   | no       | x    | x     |
-		 | no   | false    | x    | x     |
-		 | no   | 0        | x    | x     |
-		 | no   | yes      | x    |       |
-		 | no   | true     | x    |       |
-		 | no   | 1        | x    |       |
-		 | no   | -1       |      | x     |
-	
-	Scenario: Bike - Implied oneways
-	 	Then routability should be
-		 | highway       | foot | bicycle | junction   | forw | backw |
-		 |               | no   |         |            | x    | x     |
-		 |               | no   |         | roundabout | x    |       |
-		 | motorway      | no   | yes     |            | x    |       |
-		 | motorway_link | no   | yes     |            | x    |       |
-		 | motorway      | no   | yes     | roundabout | x    |       |
-		 | motorway_link | no   | yes     | roundabout | x    |       |
-
-	Scenario: Bike - Overriding implied oneways
-	 	Then routability should be
-		 | highway       | foot | junction   | oneway | forw | backw |
-		 | primary       | no   | roundabout | no     | x    | x     |
-		 | primary       | no   | roundabout | yes    | x    |       |
-		 | motorway_link | no   |            | -1     |      |       |
-		 | trunk_link    | no   |            | -1     |      |       |
-		 | primary       | no   | roundabout | -1     |      | x     |
-	
-	Scenario: Bike - Oneway:bicycle should override normal oneways tags
-	 	Then routability should be
-		 | foot | oneway:bicycle | oneway | junction   | forw | backw |
-		 | no   | yes            |        |            | x    |       |
-		 | no   | yes            | yes    |            | x    |       |
-		 | no   | yes            | no     |            | x    |       |
-		 | no   | yes            | -1     |            | x    |       |
-		 | no   | yes            |        | roundabout | x    |       |
-		 | no   | no             |        |            | x    | x     |
-		 | no   | no             | yes    |            | x    | x     |
-		 | no   | no             | no     |            | x    | x     |
-		 | no   | no             | -1     |            | x    | x     |
-		 | no   | no             |        | roundabout | x    | x     |
-		 | no   | -1             |        |            |      | x     |
-		 | no   | -1             | yes    |            |      | x     |
-		 | no   | -1             | no     |            |      | x     |
-		 | no   | -1             | -1     |            |      | x     |
-		 | no   | -1             |        | roundabout |      | x     |
-	
-	Scenario: Bike - Contra flow
-	 	Then routability should be
-		 | foot | oneway | cycleway       | forw | backw |
-		 | no   | yes    | opposite       | x    | x     |
-		 | no   | yes    | opposite_track | x    | x     |
-		 | no   | yes    | opposite_lane  | x    | x     |
-		 | no   | -1     | opposite       | x    | x     |
-		 | no   | -1     | opposite_track | x    | x     |
-		 | no   | -1     | opposite_lane  | x    | x     |
-		 | no   | no     | opposite       | x    | x     |
-		 | no   | no     | opposite_track | x    | x     |
-		 | no   | no     | opposite_lane  | x    | x     |
-
-	Scenario: Bike - Should not be affected by car tags
-		Then routability should be
-		 | foot | junction   | oneway | oneway:car | forw | backw |
-		 | no   |            | yes    | yes        | x    |       |
-		 | no   |            | yes    | no         | x    |       |
-		 | no   |            | yes    | -1         | x    |       |
-		 | no   |            | no     | yes        | x    | x     |
-		 | no   |            | no     | no         | x    | x     |
-		 | no   |            | no     | -1         | x    | x     |
-		 | no   |            | -1     | yes        |      | x     |
-		 | no   |            | -1     | no         |      | x     |
-		 | no   |            | -1     | -1         |      | x     |
-		 | no   | roundabout |        | yes        | x    |       |
-		 | no   | roundabout |        | no         | x    |       |
-		 | no   | roundabout |        | -1         | x    |       |
-
-   	Scenario: Bike - Two consecutive oneways
-   		Given the node map
-   		 | a | b | c |
-
-   		And the ways
-   		 | nodes | oneway |
-   		 | ab    | yes    |
-   		 | bc    | yes    |
-
-
-   		When I route I should get
-   		 | from | to | route |
-   		 | a    | c  | ab,bc |
\ No newline at end of file
+# Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing
+# Usually we can push bikes against oneways, but we use foot=no to prevent this in these tests
+
+    Background:
+        Given the profile "bicycle"
+
+    Scenario: Bike - Simple oneway
+        Then routability should be
+            | highway | foot | oneway | forw | backw |
+            | primary | no   | yes    | x    |       |
+
+    Scenario: Simple reverse oneway
+        Then routability should be
+            | highway | foot | oneway | forw | backw |
+            | primary | no   | -1     |      | x     |
+
+    Scenario: Bike - Around the Block
+        Given the node map
+            | a | b |
+            | d | c |
+
+        And the ways
+            | nodes | oneway | foot |
+            | ab    | yes    | no   |
+            | bc    |        | no   |
+            | cd    |        | no   |
+            | da    |        | no   |
+
+        When I route I should get
+            | from | to | route    |
+            | a    | b  | ab       |
+            | b    | a  | bc,cd,da |
+
+    Scenario: Bike - Handle various oneway tag values
+        Then routability should be
+            | foot | oneway   | forw | backw |
+            | no   |          | x    | x     |
+            | no   | nonsense | x    | x     |
+            | no   | no       | x    | x     |
+            | no   | false    | x    | x     |
+            | no   | 0        | x    | x     |
+            | no   | yes      | x    |       |
+            | no   | true     | x    |       |
+            | no   | 1        | x    |       |
+            | no   | -1       |      | x     |
+
+    Scenario: Bike - Implied oneways
+        Then routability should be
+            | highway       | foot | bicycle | junction   | forw | backw |
+            |               | no   |         |            | x    | x     |
+            |               | no   |         | roundabout | x    |       |
+            | motorway      | no   | yes     |            | x    |       |
+            | motorway_link | no   | yes     |            | x    |       |
+            | motorway      | no   | yes     | roundabout | x    |       |
+            | motorway_link | no   | yes     | roundabout | x    |       |
+
+    Scenario: Bike - Overriding implied oneways
+        Then routability should be
+            | highway       | foot | junction   | oneway | forw | backw |
+            | primary       | no   | roundabout | no     | x    | x     |
+            | primary       | no   | roundabout | yes    | x    |       |
+            | motorway_link | no   |            | -1     |      |       |
+            | trunk_link    | no   |            | -1     |      |       |
+            | primary       | no   | roundabout | -1     |      | x     |
+
+    Scenario: Bike - Oneway:bicycle should override normal oneways tags
+        Then routability should be
+            | foot | oneway:bicycle | oneway | junction   | forw | backw |
+            | no   | yes            |        |            | x    |       |
+            | no   | yes            | yes    |            | x    |       |
+            | no   | yes            | no     |            | x    |       |
+            | no   | yes            | -1     |            | x    |       |
+            | no   | yes            |        | roundabout | x    |       |
+            | no   | no             |        |            | x    | x     |
+            | no   | no             | yes    |            | x    | x     |
+            | no   | no             | no     |            | x    | x     |
+            | no   | no             | -1     |            | x    | x     |
+            | no   | no             |        | roundabout | x    | x     |
+            | no   | -1             |        |            |      | x     |
+            | no   | -1             | yes    |            |      | x     |
+            | no   | -1             | no     |            |      | x     |
+            | no   | -1             | -1     |            |      | x     |
+            | no   | -1             |        | roundabout |      | x     |
+
+    Scenario: Bike - Contra flow
+        Then routability should be
+            | foot | oneway | cycleway       | forw | backw |
+            | no   | yes    | opposite       | x    | x     |
+            | no   | yes    | opposite_track | x    | x     |
+            | no   | yes    | opposite_lane  | x    | x     |
+            | no   | -1     | opposite       | x    | x     |
+            | no   | -1     | opposite_track | x    | x     |
+            | no   | -1     | opposite_lane  | x    | x     |
+            | no   | no     | opposite       | x    | x     |
+            | no   | no     | opposite_track | x    | x     |
+            | no   | no     | opposite_lane  | x    | x     |
+
+    Scenario: Bike - Should not be affected by car tags
+        Then routability should be
+            | foot | junction   | oneway | oneway:car | forw | backw |
+            | no   |            | yes    | yes        | x    |       |
+            | no   |            | yes    | no         | x    |       |
+            | no   |            | yes    | -1         | x    |       |
+            | no   |            | no     | yes        | x    | x     |
+            | no   |            | no     | no         | x    | x     |
+            | no   |            | no     | -1         | x    | x     |
+            | no   |            | -1     | yes        |      | x     |
+            | no   |            | -1     | no         |      | x     |
+            | no   |            | -1     | -1         |      | x     |
+            | no   | roundabout |        | yes        | x    |       |
+            | no   | roundabout |        | no         | x    |       |
+            | no   | roundabout |        | -1         | x    |       |
+
+    Scenario: Bike - Two consecutive oneways
+        Given the node map
+            | a | b | c |
+
+        And the ways
+            | nodes | oneway |
+            | ab    | yes    |
+            | bc    | yes    |
+
+
+        When I route I should get
+            | from | to | route |
+            | a    | c  | ab,bc |
diff --git a/features/bicycle/pushing.feature b/features/bicycle/pushing.feature
index 13590d0..2b23829 100644
--- a/features/bicycle/pushing.feature
+++ b/features/bicycle/pushing.feature
@@ -1,124 +1,124 @@
 @routing @bicycle @pushing
 Feature: Bike - Accessability of different way types
 
-	Background:
-		Given the profile "bicycle"
+    Background:
+        Given the profile "bicycle"
         Given the shortcuts
-		 | key  | value     |
-		 | bike | 49s ~20%  |
-		 | foot | 121s ~20% |
+            | key  | value     |
+            | bike | 49s ~20%  |
+            | foot | 121s ~20% |
 
-	Scenario: Bike - Pushing bikes on pedestrian-only ways
-	 	Then routability should be
-		 | highway    | oneway | forw | backw |
-		 | (nil)      |        |      |       |
-		 | cycleway   |        | bike | bike  |
-		 | primary    |        | bike | bike  |
-		 | pedestrian |        | foot | foot  |
-		 | footway    |        | foot | foot  |
-		 | primary    | yes    | bike | foot  |
+    Scenario: Bike - Pushing bikes on pedestrian-only ways
+        Then routability should be
+            | highway    | oneway | forw | backw |
+            | (nil)      |        |      |       |
+            | cycleway   |        | bike | bike  |
+            | primary    |        | bike | bike  |
+            | pedestrian |        | foot | foot  |
+            | footway    |        | foot | foot  |
+            | primary    | yes    | bike | foot  |
 
- 	Scenario: Bike - Pushing bikes against normal oneways
- 	 	Then routability should be
- 		 | highway    | oneway | forw | backw |
- 		 | (nil)      |        |      |       |
- 		 | primary    | yes    | bike | foot  |
- 		 | pedestrian | yes    | foot | foot  |
+    Scenario: Bike - Pushing bikes against normal oneways
+        Then routability should be
+            | highway    | oneway | forw | backw |
+            | (nil)      |        |      |       |
+            | primary    | yes    | bike | foot  |
+            | pedestrian | yes    | foot | foot  |
 
-  	Scenario: Bike - Pushing bikes against reverse oneways
-  	 	Then routability should be
-  		 | highway    | oneway | forw | backw |
-  		 | (nil)      |        |      |       |
-  		 | primary    | -1     | foot | bike  |
-  		 | pedestrian | -1     | foot | foot  |
+    Scenario: Bike - Pushing bikes against reverse oneways
+        Then routability should be
+            | highway    | oneway | forw | backw |
+            | (nil)      |        |      |       |
+            | primary    | -1     | foot | bike  |
+            | pedestrian | -1     | foot | foot  |
 
- 	@square	
- 	Scenario: Bike - Push bikes on pedestrian areas
- 		Given the node map
- 		 | x |   |
- 		 | a | b |
- 		 | d | c |
+    @square    
+    Scenario: Bike - Push bikes on pedestrian areas
+        Given the node map
+            | x |   |
+            | a | b |
+            | d | c |
 
- 		And the ways
- 		 | nodes | area | highway    |
- 		 | xa    |      | primary    |
- 		 | abcda | yes  | pedestrian |
+        And the ways
+            | nodes | area | highway    |
+            | xa    |      | primary    |
+            | abcda | yes  | pedestrian |
 
- 		When I route I should get
- 		 | from | to | route |
- 		 | a    | b  | abcda |
- 		 | a    | d  | abcda |
- 		 | b    | c  | abcda |
- 		 | c    | b  | abcda |
- 		 | c    | d  | abcda |
- 		 | d    | c  | abcda |
- 		 | d    | a  | abcda |
- 		 | a    | d  | abcda |
+        When I route I should get
+            | from | to | route |
+            | a    | b  | abcda |
+            | a    | d  | abcda |
+            | b    | c  | abcda |
+            | c    | b  | abcda |
+            | c    | d  | abcda |
+            | d    | c  | abcda |
+            | d    | a  | abcda |
+            | a    | d  | abcda |
 
- 	Scenario: Bike - Pushing bikes on ways with foot=yes
- 	 	Then routability should be
- 		 | highway  | foot | bothw |
- 		 | motorway |      |       |
- 		 | motorway | yes  | foot  |
- 		 | runway   |      |       |
- 		 | runway   | yes  | foot  |
+    Scenario: Bike - Pushing bikes on ways with foot=yes
+        Then routability should be
+            | highway  | foot | forw | backw |
+            | motorway |      |      |       |
+            | motorway | yes  | foot |       |
+            | runway   |      |      |       |
+            | runway   | yes  | foot | foot  |
     
     @todo
-  	Scenario: Bike - Pushing bikes on ways with foot=yes in one direction
-  	 	Then routability should be
-  		 | highway  | foot:forward | foot:backward | forw | backw |
-  		 | motorway |              |               |      |       |
-  		 | motorway | yes          |               | foot |       |
-  		 | motorway |              | yes           |      | foot  |
+    Scenario: Bike - Pushing bikes on ways with foot=yes in one direction
+        Then routability should be
+            | highway  | foot:forward | foot:backward | forw | backw |
+            | motorway |              |               |      |       |
+            | motorway | yes          |               | foot |       |
+            | motorway |              | yes           |      | foot  |
 
     @construction
- 	Scenario: Bike - Don't allow routing on ways still under construction 
- 	 	Then routability should be
- 		 | highway      | foot | bicycle | bothw |
- 		 | primary      |      |         | x     |
- 		 | construction |      |         |       |
- 		 | construction | yes  |         |       |
- 		 | construction |      | yes     |       |
+    Scenario: Bike - Don't allow routing on ways still under construction 
+        Then routability should be
+            | highway      | foot | bicycle | bothw |
+            | primary      |      |         | x     |
+            | construction |      |         |       |
+            | construction | yes  |         |       |
+            | construction |      | yes     |       |
         
     @roundabout
-  	Scenario: Bike - Don't push bikes against oneway flow on roundabouts
-  	 	Then routability should be
-  		 | junction   | forw | backw |
-  		 | roundabout | x    |       |
+    Scenario: Bike - Don't push bikes against oneway flow on roundabouts
+        Then routability should be
+            | junction   | forw | backw |
+            | roundabout | x    |       |
  
-  	Scenario: Bike - Instructions when pushing bike on oneways
-  		Given the node map
-  		 | a | b |   |
-  		 |   | c | d |
+    Scenario: Bike - Instructions when pushing bike on oneways
+        Given the node map
+            | a | b |   |
+            |   | c | d |
 
-  		And the ways
-  		 | nodes | highway | oneway |
-  		 | ab    | primary |        |
-  		 | bc    | primary | yes    |
-  		 | cd    | primary |        |
+        And the ways
+            | nodes | highway | oneway |
+            | ab    | primary |        |
+            | bc    | primary | yes    |
+            | cd    | primary |        |
 
-  		When I route I should get
-  		 | from | to | route    | turns                                              |
-  		 | a    | d  | ab,bc,cd | head,right,left,destination                        |
-  		 | d    | a  | cd,bc,ab | head,enter_contraflow,leave_contraflow,destination |
-  		 | c    | a  | bc,ab    | head,leave_contraflow,destination                  |
-  		 | d    | b  | cd,bc    | head,enter_contraflow,destination                  |
+        When I route I should get
+            | from | to | route    | turns                                              |
+            | a    | d  | ab,bc,cd | head,right,left,destination                        |
+            | d    | a  | cd,bc,ab | head,enter_contraflow,leave_contraflow,destination |
+            | c    | a  | bc,ab    | head,leave_contraflow,destination                  |
+            | d    | b  | cd,bc    | head,enter_contraflow,destination                  |
 
-  	@todo
+    @todo
     Scenario: Bike - Instructions when pushing bike on footway/pedestrian, etc.
-   		Given the node map
-   		 | a | b |   |
-   		 |   | c | d |
+        Given the node map
+            | a | b |   |
+            |   | c | d |
 
-   		And the ways
-   		 | nodes | highway |
-   		 | ab    | primary |
-   		 | bc    | footway |
-   		 | cd    | primary |
+        And the ways
+            | nodes | highway |
+            | ab    | primary |
+            | bc    | footway |
+            | cd    | primary |
 
-   		When I route I should get
-   		 | from | to | route    | turns                                              |
-   		 | a    | d  | ab,bc,cd | head,right,left,destination                        |
-   		 | d    | a  | cd,bc,ab | head,enter_contraflow,leave_contraflow,destination |
-   		 | c    | a  | bc,ab    | head,leave_contraflow,destination                  |
-   		 | d    | b  | cd,bc    | head,enter_contraflow,destination                  |
\ No newline at end of file
+        When I route I should get
+            | from | to | route    | turns                                              |
+            | a    | d  | ab,bc,cd | head,right,left,destination                        |
+            | d    | a  | cd,bc,ab | head,enter_contraflow,leave_contraflow,destination |
+            | c    | a  | bc,ab    | head,leave_contraflow,destination                  |
+            | d    | b  | cd,bc    | head,enter_contraflow,destination                  |
diff --git a/features/bicycle/ref.feature b/features/bicycle/ref.feature
index da15859..3afde77 100644
--- a/features/bicycle/ref.feature
+++ b/features/bicycle/ref.feature
@@ -1,41 +1,41 @@
 @routing @bicycle @ref @name
 Feature: Bike - Way ref
 
-	Background:
-		Given the profile "bicycle"
-	
-	Scenario: Bike - Way with both name and ref
-		Given the node map
-		 | a | b |
-	
-		And the ways
-		 | nodes | name         | ref |
-		 | ab    | Utopia Drive | E7  |
-    
-		When I route I should get
-		 | from | to | route             |
-		 | a    | b  | Utopia Drive / E7 |
-
- 	Scenario: Bike - Way with only ref
- 		Given the node map
- 		 | a | b |
-
- 		And the ways
- 		 | nodes | name | ref |
- 		 | ab    |      | E7  |
-
- 		When I route I should get
- 		 | from | to | route |
- 		 | a    | b  | E7    |
-
-  	Scenario: Bike - Way with only name
-  		Given the node map
-  		 | a | b |
-
-  		And the ways
-  		 | nodes | name         |
-  		 | ab    | Utopia Drive |
-
-  		When I route I should get
-  		 | from | to | route        |
-  		 | a    | b  | Utopia Drive |
+    Background:
+        Given the profile "bicycle"
+
+    Scenario: Bike - Way with both name and ref
+        Given the node map
+            | a | b |
+
+        And the ways
+            | nodes | name         | ref |
+            | ab    | Utopia Drive | E7  |
+
+        When I route I should get
+            | from | to | route             |
+            | a    | b  | Utopia Drive / E7 |
+
+    Scenario: Bike - Way with only ref
+        Given the node map
+            | a | b |
+
+        And the ways
+            | nodes | name | ref |
+            | ab    |      | E7  |
+
+        When I route I should get
+            | from | to | route |
+            | a    | b  | E7    |
+
+    Scenario: Bike - Way with only name
+        Given the node map
+            | a | b |
+
+        And the ways
+            | nodes | name         |
+            | ab    | Utopia Drive |
+
+        When I route I should get
+            | from | to | route        |
+            | a    | b  | Utopia Drive |
diff --git a/features/bicycle/restrictions.feature b/features/bicycle/restrictions.feature
index 2d5fa40..6218d81 100644
--- a/features/bicycle/restrictions.feature
+++ b/features/bicycle/restrictions.feature
@@ -1,289 +1,289 @@
 @routing @bicycle @restrictions
 Feature: Bike - Turn restrictions
-	Ignore turn restrictions on bicycle, since you always become a temporary pedestrian.
-	Note that if u-turns are allowed, turn restrictions can lead to suprising, but correct, routes.
-	
-	Background:
-		Given the profile "bicycle"
-	
-	@no_turning
-	Scenario: Bike - No left turn
-		Given the node map
-		 |   | n |   |
-		 | w | j | e |
-		 |   | s |   |
-
-		And the ways
-		 | nodes | oneway | foot |
-		 | sj    | yes    | no   |
-		 | nj    | -1     | no   |
-		 | wj    | -1     | no   |
-		 | ej    | -1     | no   |
-
-		And the relations
-		 | type        | way:from | way:to | node:via | restriction  |
-		 | restriction | sj       | wj     | j        | no_left_turn |
-
-		When I route I should get
-		 | from | to | route |
-		 | s    | w  | sj,wj |
-		 | s    | n  | sj,nj |
-		 | s    | e  | sj,ej |
-
-	@no_turning
-	Scenario: Bike - No right turn
-		Given the node map
-		 |   | n |   |
-		 | w | j | e |
-		 |   | s |   |
-
-		And the ways
-		 | nodes | oneway | foot |
-		 | sj    | yes    | no   |
-		 | nj    | -1     | no   |
-		 | wj    | -1     | no   |
-		 | ej    | -1     | no   |
-
-		And the relations
-		 | type        | way:from | way:to | node:via | restriction   |
-		 | restriction | sj       | ej     | j        | no_right_turn |
-
-		When I route I should get
-		 | from | to | route |
-		 | s    | w  | sj,wj |
-		 | s    | n  | sj,nj |
-		 | s    | e  | sj,ej |
-
-	@no_turning
-	Scenario: Bike - No u-turn
-		Given the node map
-		 |   | n |   |
-		 | w | j | e |
-		 |   | s |   |
-
-		And the ways
-		 | nodes | oneway | foot |
-		 | sj    | yes    | no   |
-		 | nj    | -1     | no   |
-		 | wj    | -1     | no   |
-		 | ej    | -1     | no   |
-
-		And the relations
-		 | type        | way:from | way:to | node:via | restriction |
-		 | restriction | sj       | wj     | j        | no_u_turn   |
-
-		When I route I should get
-		 | from | to | route |
-		 | s    | w  | sj,wj |
-		 | s    | n  | sj,nj |
-		 | s    | e  | sj,ej |
-
-	@no_turning
-	Scenario: Bike - Handle any no_* relation
-		Given the node map
-		 |   | n |   |
-		 | w | j | e |
-		 |   | s |   |
-
-		And the ways
-		 | nodes | oneway | foot |
-		 | sj    | yes    | no   |
-		 | nj    | -1     | no   |
-		 | wj    | -1     | no   |
-		 | ej    | -1     | no   |
-
-		And the relations
-		 | type        | way:from | way:to | node:via | restriction      |
-		 | restriction | sj       | wj     | j        | no_weird_zigzags |
-
-		When I route I should get
-		 | from | to | route |
-		 | s    | w  | sj,wj |
-		 | s    | n  | sj,nj |
-		 | s    | e  | sj,ej |
-
-	@only_turning
-	Scenario: Bike - Only left turn
-		Given the node map
-		 |   | n |   |
-		 | w | j | e |
-		 |   | s |   |
-
-		And the ways
-		 | nodes | oneway | foot |
-		 | sj    | yes    | no   |
-		 | nj    | -1     | no   |
-		 | wj    | -1     | no   |
-		 | ej    | -1     | no   |
-
-		And the relations
-		 | type        | way:from | way:to | node:via | restriction    |
-		 | restriction | sj       | wj     | j        | only_left_turn |
-
-		When I route I should get
-		 | from | to | route |
-		 | s    | w  | sj,wj |
-		 | s    | n  | sj,nj |
-		 | s    | e  | sj,ej |
-
-	@only_turning
-	Scenario: Bike - Only right turn
-		Given the node map
-		 |   | n |   |
-		 | w | j | e |
-		 |   | s |   |
-
-		And the ways
-		 | nodes | oneway | foot |
-		 | sj    | yes    | no   |
-		 | nj    | -1     | no   |
-		 | wj    | -1     | no   |
-		 | ej    | -1     | no   |
-
-		And the relations
-		 | type        | way:from | way:to | node:via | restriction     |
-		 | restriction | sj       | ej     | j        | only_right_turn |
-
-		When I route I should get
-		 | from | to | route |
-		 | s    | w  | sj,wj |
-		 | s    | n  | sj,nj |
-		 | s    | e  | sj,ej |
-	
-	@only_turning
-	Scenario: Bike - Only straight on
-		Given the node map
-		 |   | n |   |
-		 | w | j | e |
-		 |   | s |   |
-
-		And the ways
-		 | nodes | oneway | foot |
-		 | sj    | yes    | no   |
-		 | nj    | -1     | no   |
-		 | wj    | -1     | no   |
-		 | ej    | -1     | no   |
-
-		And the relations
-		 | type        | way:from | way:to | node:via | restriction      |
-		 | restriction | sj       | nj     | j        | only_straight_on |
-
-		When I route I should get
-		 | from | to | route |
-		 | s    | w  | sj,wj |
-		 | s    | n  | sj,nj |
-		 | s    | e  | sj,ej |
-
-	@no_turning
-	Scenario: Bike - Handle any only_* restriction
-		Given the node map
-		 |   | n |   |
-		 | w | j | e |
-		 |   | s |   |
-
-		And the ways
-		 | nodes | oneway | foot |
-		 | sj    | yes    | no   |
-		 | nj    | -1     | no   |
-		 | wj    | -1     | no   |
-		 | ej    | -1     | no   |
-
-		And the relations
-		 | type        | way:from | way:to | node:via | restriction        |
-		 | restriction | sj       | nj     | j        | only_weird_zigzags |
-
-		When I route I should get
-		 | from | to | route |
-		 | s    | w  | sj,wj |
-		 | s    | n  | sj,nj |
-		 | s    | e  | sj,ej |
-
- 	@except
- 	Scenario: Bike - Except tag and on no_ restrictions
- 		Given the node map
- 		 | b | x | c |
- 		 | a | j | d |
- 		 |   | s |   |
-
- 		And the ways
- 		 | nodes | oneway | foot |
- 		 | sj    | no     | no   |
- 		 | xj    | -1     | no   |
- 		 | aj    | -1     | no   |
- 		 | bj    | no     | no   |
- 		 | cj    | -1     | no   |
- 		 | dj    | -1     | no   |
-
- 		And the relations
- 		 | type        | way:from | way:to | node:via | restriction   | except  |
- 		 | restriction | sj       | aj     | j        | no_left_turn  | bicycle |
- 		 | restriction | sj       | bj     | j        | no_left_turn  |         |
- 		 | restriction | sj       | cj     | j        | no_right_turn |         |
- 		 | restriction | sj       | dj     | j        | no_right_turn | bicycle |
-
- 		When I route I should get
- 		 | from | to | route |
- 		 | s    | a  | sj,aj |
- 		 | s    | b  | sj,bj |
- 		 | s    | c  | sj,cj |
- 		 | s    | d  | sj,dj |
-
-  	@except
-  	Scenario: Bike - Except tag and on only_ restrictions
-  		Given the node map
-  		 | a |   | b |
-  		 |   | j |   |
-  		 |   | s |   |
-
-  		And the ways
-  		 | nodes | oneway | foot |
-  		 | sj    | yes    | no   |
-  		 | aj    | no     | no   |
-  		 | bj    | no     | no   |
-
-  		And the relations
-  		 | type        | way:from | way:to | node:via | restriction      | except  |
-  		 | restriction | sj       | aj     | j        | only_straight_on | bicycle |
-
-  		When I route I should get
-  		 | from | to | route |
-  		 | s    | a  | sj,aj |
-  		 | s    | b  | sj,bj |
-
-  	@except
-  	Scenario: Bike - Multiple except tag values
-  		Given the node map
-  		 | s | j | a |
-  		 |   |   | b |
-  		 |   |   | c |
-  		 |   |   | d |
-  		 |   |   | e |
-  		 |   |   | f |
-
-  		And the ways
-  		 | nodes | oneway | foot |
-  		 | sj    | yes    | no   |
-  		 | ja    | yes    | no   |
-  		 | jb    | yes    | no   |
-  		 | jc    | yes    | no   |
-  		 | jd    | yes    | no   |
-  		 | je    | yes    | no   |
-  		 | jf    | yes    | no   |
-
-  		And the relations
-  		 | type        | way:from | way:to | node:via | restriction    | except           |
-  		 | restriction | sj       | ja     | j        | no_straight_on |                  |
-  		 | restriction | sj       | jb     | j        | no_straight_on | bicycle          |
-  		 | restriction | sj       | jc     | j        | no_straight_on | bus; bicycle     |
-  		 | restriction | sj       | jd     | j        | no_straight_on | bicycle; motocar |
-  		 | restriction | sj       | je     | j        | no_straight_on | bus, bicycle     |
-  		 | restriction | sj       | jf     | j        | no_straight_on | bicycle, bus     |
-
-  		When I route I should get
-  		 | from | to | route |
-  		 | s    | a  | sj,ja |
-  		 | s    | b  | sj,jb |
-  		 | s    | c  | sj,jc |
-  		 | s    | d  | sj,jd |
-  		 | s    | e  | sj,je |
-  		 | s    | f  | sj,jf |
+# Ignore turn restrictions on bicycle, since you always become a temporary pedestrian.
+# Note that if u-turns are allowed, turn restrictions can lead to suprising, but correct, routes.
+
+    Background:
+        Given the profile "bicycle"
+
+    @no_turning
+    Scenario: Bike - No left turn
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway | foot |
+            | sj    | yes    | no   |
+            | nj    | -1     | no   |
+            | wj    | -1     | no   |
+            | ej    | -1     | no   |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction  |
+            | restriction | sj       | wj     | j        | no_left_turn |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @no_turning
+    Scenario: Bike - No right turn
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway | foot |
+            | sj    | yes    | no   |
+            | nj    | -1     | no   |
+            | wj    | -1     | no   |
+            | ej    | -1     | no   |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction   |
+            | restriction | sj       | ej     | j        | no_right_turn |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @no_turning
+    Scenario: Bike - No u-turn
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway | foot |
+            | sj    | yes    | no   |
+            | nj    | -1     | no   |
+            | wj    | -1     | no   |
+            | ej    | -1     | no   |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction |
+            | restriction | sj       | wj     | j        | no_u_turn   |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @no_turning
+    Scenario: Bike - Handle any no_* relation
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway | foot |
+            | sj    | yes    | no   |
+            | nj    | -1     | no   |
+            | wj    | -1     | no   |
+            | ej    | -1     | no   |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction      |
+            | restriction | sj       | wj     | j        | no_weird_zigzags |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @only_turning
+    Scenario: Bike - Only left turn
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway | foot |
+            | sj    | yes    | no   |
+            | nj    | -1     | no   |
+            | wj    | -1     | no   |
+            | ej    | -1     | no   |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction    |
+            | restriction | sj       | wj     | j        | only_left_turn |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @only_turning
+    Scenario: Bike - Only right turn
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway | foot |
+            | sj    | yes    | no   |
+            | nj    | -1     | no   |
+            | wj    | -1     | no   |
+            | ej    | -1     | no   |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction     |
+            | restriction | sj       | ej     | j        | only_right_turn |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @only_turning
+    Scenario: Bike - Only straight on
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway | foot |
+            | sj    | yes    | no   |
+            | nj    | -1     | no   |
+            | wj    | -1     | no   |
+            | ej    | -1     | no   |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction      |
+            | restriction | sj       | nj     | j        | only_straight_on |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @no_turning
+    Scenario: Bike - Handle any only_* restriction
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway | foot |
+            | sj    | yes    | no   |
+            | nj    | -1     | no   |
+            | wj    | -1     | no   |
+            | ej    | -1     | no   |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction        |
+            | restriction | sj       | nj     | j        | only_weird_zigzags |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @except
+    Scenario: Bike - Except tag and on no_ restrictions
+        Given the node map
+            | b | x | c |
+            | a | j | d |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway | foot |
+            | sj    | no     | no   |
+            | xj    | -1     | no   |
+            | aj    | -1     | no   |
+            | bj    | no     | no   |
+            | cj    | -1     | no   |
+            | dj    | -1     | no   |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction   | except  |
+            | restriction | sj       | aj     | j        | no_left_turn  | bicycle |
+            | restriction | sj       | bj     | j        | no_left_turn  |         |
+            | restriction | sj       | cj     | j        | no_right_turn |         |
+            | restriction | sj       | dj     | j        | no_right_turn | bicycle |
+
+        When I route I should get
+            | from | to | route |
+            | s    | a  | sj,aj |
+            | s    | b  | sj,bj |
+            | s    | c  | sj,cj |
+            | s    | d  | sj,dj |
+
+    @except
+    Scenario: Bike - Except tag and on only_ restrictions
+        Given the node map
+            | a |   | b |
+            |   | j |   |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway | foot |
+            | sj    | yes    | no   |
+            | aj    | no     | no   |
+            | bj    | no     | no   |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction      | except  |
+            | restriction | sj       | aj     | j        | only_straight_on | bicycle |
+
+        When I route I should get
+            | from | to | route |
+            | s    | a  | sj,aj |
+            | s    | b  | sj,bj |
+
+    @except
+    Scenario: Bike - Multiple except tag values
+        Given the node map
+            | s | j | a |
+            |   |   | b |
+            |   |   | c |
+            |   |   | d |
+            |   |   | e |
+            |   |   | f |
+
+        And the ways
+            | nodes | oneway | foot |
+            | sj    | yes    | no   |
+            | ja    | yes    | no   |
+            | jb    | yes    | no   |
+            | jc    | yes    | no   |
+            | jd    | yes    | no   |
+            | je    | yes    | no   |
+            | jf    | yes    | no   |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction    | except           |
+            | restriction | sj       | ja     | j        | no_straight_on |                  |
+            | restriction | sj       | jb     | j        | no_straight_on | bicycle          |
+            | restriction | sj       | jc     | j        | no_straight_on | bus; bicycle     |
+            | restriction | sj       | jd     | j        | no_straight_on | bicycle; motocar |
+            | restriction | sj       | je     | j        | no_straight_on | bus, bicycle     |
+            | restriction | sj       | jf     | j        | no_straight_on | bicycle, bus     |
+
+        When I route I should get
+            | from | to | route |
+            | s    | a  | sj,ja |
+            | s    | b  | sj,jb |
+            | s    | c  | sj,jc |
+            | s    | d  | sj,jd |
+            | s    | e  | sj,je |
+            | s    | f  | sj,jf |
diff --git a/features/bicycle/roundabout.feature b/features/bicycle/roundabout.feature
new file mode 100644
index 0000000..6123280
--- /dev/null
+++ b/features/bicycle/roundabout.feature
@@ -0,0 +1,30 @@
+ at routing @bicycle @roundabout @instruction
+Feature: Roundabout Instructions
+
+    Background:
+        Given the profile "bicycle"
+
+    Scenario: Bicycle - Roundabout instructions
+        Given the node map
+            |   |   | v |   |   |
+            |   |   | d |   |   |
+            | s | a |   | c | u |
+            |   |   | b |   |   |
+            |   |   | t |   |   |
+
+        And the ways
+            | nodes | junction   |
+            | sa    |            |
+            | tb    |            |
+            | uc    |            |
+            | vd    |            |
+            | abcda | roundabout |
+
+        When I route I should get
+            | from | to | route | turns                               |
+            | s    | t  | sa,tb | head,enter_roundabout-1,destination |
+            | s    | u  | sa,uc | head,enter_roundabout-2,destination |
+            | s    | v  | sa,vd | head,enter_roundabout-3,destination |
+            | u    | v  | uc,vd | head,enter_roundabout-1,destination |
+            | u    | s  | uc,sa | head,enter_roundabout-2,destination |
+            | u    | t  | uc,tb | head,enter_roundabout-3,destination |
diff --git a/features/bicycle/stop_area.feature b/features/bicycle/stop_area.feature
index 7113808..5f6c3bc 100644
--- a/features/bicycle/stop_area.feature
+++ b/features/bicycle/stop_area.feature
@@ -1,37 +1,37 @@
 @routing @bicycle @stop_area @todo
 Feature: Bike - Stop areas for public transport
-Platforms and railway/bus lines are connected using a relation rather that a way, as specified in:
-http://wiki.openstreetmap.org/wiki/Tag:public_transport%3Dstop_area
+# Platforms and railway/bus lines are connected using a relation rather that a way, as specified in:
+# http://wiki.openstreetmap.org/wiki/Tag:public_transport%3Dstop_area
 
-	Background:
-		Given the profile "bicycle"
-	
-	Scenario: Bike - Platforms tagged using public_transport
-	 	Then routability should be
-		 | highway | public_transport | bicycle | bothw |
-		 | primary |                  |         | x     |
-		 | (nil)   | platform         |         | x     |
+    Background:
+        Given the profile "bicycle"
 
-	Scenario: Bike - railway platforms
-		Given the node map
-		 | a | b | c | d |
-		 |   | s | t |   |
+    Scenario: Bike - Platforms tagged using public_transport
+        Then routability should be
+            | highway | public_transport | bicycle | bothw |
+            | primary |                  |         | x     |
+            | (nil)   | platform         |         | x     |
+
+    Scenario: Bike - railway platforms
+        Given the node map
+            | a | b | c | d |
+            |   | s | t |   |
 
         And the nodes
-     	 | node | public_transport |
-     	 | c    | stop_position    |
-     	 
-		And the ways
-		 | nodes | highway | railway | bicycle | public_transport |
-		 | abcd  | (nil)   | train   | yes     |                  |
-		 | st    | (nil)   | (nil)   |         | platform         |
+            | node | public_transport |
+            | c    | stop_position    |
+
+        And the ways
+            | nodes | highway | railway | bicycle | public_transport |
+            | abcd  | (nil)   | train   | yes     |                  |
+            | st    | (nil)   | (nil)   |         | platform         |
 
-  		And the relations
-  		 | type             | public_transport | node:stop | way:platform |
-  		 | public_transport | stop_area        | c         | st           |
+        And the relations
+            | type             | public_transport | node:stop | way:platform |
+            | public_transport | stop_area        | c         | st           |
 
-		When I route I should get
-		 | from | to | route        |
-		 | a    | d  | abcd         |
-		 | s    | t  | st           |
-		 | s    | d  | /st,.+,abcd/ |
+        When I route I should get
+            | from | to | route        |
+            | a    | d  | abcd         |
+            | s    | t  | st           |
+            | s    | d  | /st,.+,abcd/ |
diff --git a/features/bicycle/surface.feature b/features/bicycle/surface.feature
new file mode 100644
index 0000000..216307b
--- /dev/null
+++ b/features/bicycle/surface.feature
@@ -0,0 +1,40 @@
+ at routing @surface @bicycle
+Feature: Bike - Surfaces
+
+    Background:
+        Given the profile "bicycle"
+
+    Scenario: Bicycle - Slow surfaces
+        Then routability should be
+            | highway  | surface               | bothw |
+            | cycleway |                       | 48s   |
+            | cycleway | asphalt               | 48s   |
+            | cycleway | cobblestone:flattened | 72s   |
+            | cycleway | paving_stones         | 72s   |
+            | cycleway | compacted             | 72s   |
+            | cycleway | cobblestone           | 120s  |
+            | cycleway | unpaved               | 120s  |
+            | cycleway | fine_gravel           | 120s  |
+            | cycleway | gravel                | 120s  |
+            | cycleway | pebbelstone           | 120s  |
+            | cycleway | dirt                  | 120s  |
+            | cycleway | earth                 | 120s  |
+            | cycleway | grass                 | 120s  |
+            | cycleway | mud                   | 240s  |
+            | cycleway | sand                  | 240s  |
+
+    Scenario: Bicycle - Good surfaces on small paths
+        Then routability should be
+        | highway  | surface | bothw |
+        | cycleway |         | 48s   |
+        | path     |         | 60s   |
+        | track    |         | 60s   |
+        | track    | asphalt | 48s   |
+        | path     | asphalt | 48s   |
+
+    Scenario: Bicycle - Surfaces should not make unknown ways routable
+        Then routability should be
+        | highway  | surface | bothw |
+        | cycleway |         | 48s   |
+        | nosense  |         |       |
+        | nosense  | asphalt |       |
diff --git a/features/bicycle/train.feature b/features/bicycle/train.feature
index a4af362..aafa203 100644
--- a/features/bicycle/train.feature
+++ b/features/bicycle/train.feature
@@ -1,39 +1,39 @@
 @routing @bicycle @train
 Feature: Bike - Handle ferry routes
-Bringing bikes on trains and subways
+# Bringing bikes on trains and subways
 
-	Background:
-		Given the profile "bicycle"
-	
-	Scenario: Bike - Bringing bikes on trains
-	 	Then routability should be
-		 | highway | railway    | bicycle | bothw |
-		 | primary |            |         | x     |
-		 | (nil)   | train      |         |       |
-		 | (nil)   | train      | no      |       |
-		 | (nil)   | train      | yes     | x     |
-		 | (nil)   | railway    |         |       |
-		 | (nil)   | railway    | no      |       |
-		 | (nil)   | railway    | yes     | x     |
-		 | (nil)   | subway     |         |       |
-		 | (nil)   | subway     | no      |       |
-		 | (nil)   | subway     | yes     | x     |
-		 | (nil)   | tram       |         |       |
-		 | (nil)   | tram       | no      |       |
-		 | (nil)   | tram       | yes     | x     |
-		 | (nil)   | light_rail |         |       |
-		 | (nil)   | light_rail | no      |       |
-		 | (nil)   | light_rail | yes     | x     |
-		 | (nil)   | monorail   |         |       |
-		 | (nil)   | monorail   | no      |       |
-		 | (nil)   | monorail   | yes     | x     |
-		 | (nil)   | some_tag   |         |       |
-		 | (nil)   | some_tag   | no      |       |
-		 | (nil)   | some_tag   | yes     | x     |
+    Background:
+        Given the profile "bicycle"
 
-	@construction
- 	Scenario: Bike - Don't route on railways under construction
- 	 	Then routability should be
- 		 | highway | railway      | bicycle | bothw |
- 		 | primary |              |         | x     |
- 		 | (nil)   | construction | yes     |       |
+    Scenario: Bike - Bringing bikes on trains
+        Then routability should be
+            | highway | railway    | bicycle | bothw |
+            | primary |            |         | x     |
+            | (nil)   | train      |         |       |
+            | (nil)   | train      | no      |       |
+            | (nil)   | train      | yes     | x     |
+            | (nil)   | railway    |         |       |
+            | (nil)   | railway    | no      |       |
+            | (nil)   | railway    | yes     | x     |
+            | (nil)   | subway     |         |       |
+            | (nil)   | subway     | no      |       |
+            | (nil)   | subway     | yes     | x     |
+            | (nil)   | tram       |         |       |
+            | (nil)   | tram       | no      |       |
+            | (nil)   | tram       | yes     | x     |
+            | (nil)   | light_rail |         |       |
+            | (nil)   | light_rail | no      |       |
+            | (nil)   | light_rail | yes     | x     |
+            | (nil)   | monorail   |         |       |
+            | (nil)   | monorail   | no      |       |
+            | (nil)   | monorail   | yes     | x     |
+            | (nil)   | some_tag   |         |       |
+            | (nil)   | some_tag   | no      |       |
+            | (nil)   | some_tag   | yes     | x     |
+
+    @construction
+    Scenario: Bike - Don't route on railways under construction
+        Then routability should be
+            | highway | railway      | bicycle | bothw |
+            | primary |              |         | x     |
+            | (nil)   | construction | yes     |       |
diff --git a/features/bicycle/turn_penalty.feature b/features/bicycle/turn_penalty.feature
index 157cbf2..d8c46b8 100644
--- a/features/bicycle/turn_penalty.feature
+++ b/features/bicycle/turn_penalty.feature
@@ -2,32 +2,32 @@
 Feature: Turn Penalties
 
     Background:
-        Given the profile "turnbot"     
+        Given the profile "turnbot"
 
     Scenario: Bike - turns should incur a delay that depend on the angle
 
         Given the node map
-         | c | d | e |
-         | b | j | f |
-         | a | s | g |
+            | c | d | e |
+            | b | j | f |
+            | a | s | g |
 
         And the ways
-         | nodes |
-         | sj    |
-         | ja    |
-         | jb    |
-         | jc    |
-         | jd    |
-         | je    |
-         | jf    |
-         | jg    |
+            | nodes |
+            | sj    |
+            | ja    |
+            | jb    |
+            | jc    |
+            | jd    |
+            | je    |
+            | jf    |
+            | jg    |
 
         When I route I should get
-         | from | to | route | time    | distance |
-         | s    | a  | sj,ja | 39s +-1 | 242m +-1 |
-         | s    | b  | sj,jb | 30s +-1 | 200m +-1 |
-         | s    | c  | sj,jc | 29s +-1 | 242m +-1 |
-         | s    | d  | sj,jd | 20s +-1 | 200m +-1 |
-         | s    | e  | sj,je | 29s +-1 | 242m +-1 |
-         | s    | f  | sj,jf | 30s +-1 | 200m +-1 |
-         | s    | g  | sj,jg | 39s +-1 | 242m +-1 |
\ No newline at end of file
+            | from | to | route | time    | distance |
+            | s    | a  | sj,ja | 39s +-1 | 242m +-1 |
+            | s    | b  | sj,jb | 30s +-1 | 200m +-1 |
+            | s    | c  | sj,jc | 29s +-1 | 242m +-1 |
+            | s    | d  | sj,jd | 20s +-1 | 200m +-1 |
+            | s    | e  | sj,je | 29s +-1 | 242m +-1 |
+            | s    | f  | sj,jf | 30s +-1 | 200m +-1 |
+            | s    | g  | sj,jg | 39s +-1 | 242m +-1 |
\ No newline at end of file
diff --git a/features/bicycle/way.feature b/features/bicycle/way.feature
index f5ad5bb..b9beb5f 100644
--- a/features/bicycle/way.feature
+++ b/features/bicycle/way.feature
@@ -1,41 +1,42 @@
 @routing @bicycle @way
 Feature: Bike - Accessability of different way types
 
-	Background:
-		Given the profile "bicycle"
+    Background:
+        Given the profile "bicycle"
 
-	Scenario: Bike - Routability of way types
-	Bikes are allowed on footways etc because you can pull your bike at a lower speed.
-	Pier is not allowed, since it's tagged using man_made=pier.
-	 	Then routability should be
-		 | highway        | bothw |
-		 | (nil)          |       |
-		 | motorway       |       |
-		 | motorway_link  |       |
-		 | trunk          |       |
-		 | trunk_link     |       |
-		 | primary        | x     |
-		 | primary_link   | x     |
-		 | secondary      | x     |
-		 | secondary_link | x     |
-		 | tertiary       | x     |
-		 | tertiary_link  | x     |
-		 | residential    | x     |
-		 | service        | x     |
-		 | unclassified   | x     |
-		 | living_street  | x     |
-		 | road           | x     |
-		 | track          | x     |
-		 | path           | x     |
-		 | footway        | x     |
-		 | pedestrian     | x     |
-		 | steps          | x     |
-		 | cycleway       | x     |
-		 | bridleway      |       |
-		 | pier           |       |
+    Scenario: Bike - Routability of way types
+    # Bikes are allowed on footways etc because you can pull your bike at a lower speed.
+    # Pier is not allowed, since it's tagged using man_made=pier.
 
- 	Scenario: Bike - Routability of man_made structures
- 	 	Then routability should be
- 		 | highway | man_made | bothw |
- 		 | (nil)   | (nil)    |       |
- 		 | (nil)   | pier     | x     |
+        Then routability should be
+            | highway        | bothw |
+            | (nil)          |       |
+            | motorway       |       |
+            | motorway_link  |       |
+            | trunk          |       |
+            | trunk_link     |       |
+            | primary        | x     |
+            | primary_link   | x     |
+            | secondary      | x     |
+            | secondary_link | x     |
+            | tertiary       | x     |
+            | tertiary_link  | x     |
+            | residential    | x     |
+            | service        | x     |
+            | unclassified   | x     |
+            | living_street  | x     |
+            | road           | x     |
+            | track          | x     |
+            | path           | x     |
+            | footway        | x     |
+            | pedestrian     | x     |
+            | steps          | x     |
+            | cycleway       | x     |
+            | bridleway      |       |
+            | pier           |       |
+
+    Scenario: Bike - Routability of man_made structures
+        Then routability should be
+            | highway | man_made | bothw |
+            | (nil)   | (nil)    |       |
+            | (nil)   | pier     | x     |
diff --git a/features/car/access.feature b/features/car/access.feature
index 97e61c5..37dfed4 100644
--- a/features/car/access.feature
+++ b/features/car/access.feature
@@ -1,144 +1,144 @@
 @routing @car @access
 Feature: Car - Restricted access
-Reference: http://wiki.openstreetmap.org/wiki/Key:access
+# Reference: http://wiki.openstreetmap.org/wiki/Key:access
 
-	Background:
-		Given the profile "car"
-		
-	Scenario: Car - Access tag hierachy	on ways	
-		Then routability should be
-		 | access | vehicle | motor_vehicle | motorcar | bothw |
-		 |        |         |               |          | x     |
-		 | yes    |         |               |          | x     |
-		 | no     |         |               |          |       |
-		 |        | yes     |               |          | x     |
-		 |        | no      |               |          |       |
-		 | no     | yes     |               |          | x     |
-		 | yes    | no      |               |          |       |
-		 |        |         | yes           |          | x     |
-		 |        |         | no            |          |       |
-		 | no     |         | yes           |          | x     |
-		 | yes    |         | no            |          |       |
-		 |        | no      | yes           |          | x     |
-		 |        | yes     | no            |          |       |
-		 |        |         |               | yes      | x     |
-		 |        |         |               | no       |       |
-		 | no     |         |               | yes      | x     |
-		 | yes    |         |               | no       |       |
-		 |        | no      |               | yes      | x     |
-		 |        | yes     |               | no       |       |
-		 |        |         | no            | yes      | x     |
-		 |        |         | yes           | no       |       |
+    Background:
+        Given the profile "car"
 
-	Scenario: Car - Access tag hierachy on nodes
-		Then routability should be
-		 | node/access | node/vehicle | node/motor_vehicle | node/motorcar | bothw |
-		 |             |              |                    |               | x     |
-		 | yes         |              |                    |               | x     |
-		 | no          |              |                    |               |       |
-		 |             | yes          |                    |               | x     |
-		 |             | no           |                    |               |       |
-		 | no          | yes          |                    |               | x     |
-		 | yes         | no           |                    |               |       |
-		 |             |              | yes                |               | x     |
-		 |             |              | no                 |               |       |
-		 | no          |              | yes                |               | x     |
-		 | yes         |              | no                 |               |       |
-		 |             | no           | yes                |               | x     |
-		 |             | yes          | no                 |               |       |
-		 |             |              |                    | yes           | x     |
-		 |             |              |                    | no            |       |
-		 | no          |              |                    | yes           | x     |
-		 | yes         |              |                    | no            |       |
-		 |             | no           |                    | yes           | x     |
-		 |             | yes          |                    | no            |       |
-		 |             |              | no                 | yes           | x     |
-		 |             |              | yes                | no            |       |
+    Scenario: Car - Access tag hierachy    on ways
+        Then routability should be
+            | access | vehicle | motor_vehicle | motorcar | bothw |
+            |        |         |               |          | x     |
+            | yes    |         |               |          | x     |
+            | no     |         |               |          |       |
+            |        | yes     |               |          | x     |
+            |        | no      |               |          |       |
+            | no     | yes     |               |          | x     |
+            | yes    | no      |               |          |       |
+            |        |         | yes           |          | x     |
+            |        |         | no            |          |       |
+            | no     |         | yes           |          | x     |
+            | yes    |         | no            |          |       |
+            |        | no      | yes           |          | x     |
+            |        | yes     | no            |          |       |
+            |        |         |               | yes      | x     |
+            |        |         |               | no       |       |
+            | no     |         |               | yes      | x     |
+            | yes    |         |               | no       |       |
+            |        | no      |               | yes      | x     |
+            |        | yes     |               | no       |       |
+            |        |         | no            | yes      | x     |
+            |        |         | yes           | no       |       |
 
-	Scenario: Car - Overwriting implied acccess on ways
-		Then routability should be
-		 | highway | access | vehicle | motor_vehicle | motorcar | bothw |
-		 | primary |        |         |               |          | x     |
-		 | runway  |        |         |               |          |       |
-		 | primary | no     |         |               |          |       |
-		 | primary |        | no      |               |          |       |
-		 | primary |        |         | no            |          |       |
-		 | primary |        |         |               | no       |       |
-		 | runway  | yes    |         |               |          | x     |
-		 | runway  |        | yes     |               |          | x     |
-		 | runway  |        |         | yes           |          | x     |
-		 | runway  |        |         |               | yes      | x     |
+    Scenario: Car - Access tag hierachy on nodes
+        Then routability should be
+            | node/access | node/vehicle | node/motor_vehicle | node/motorcar | bothw |
+            |             |              |                    |               | x     |
+            | yes         |              |                    |               | x     |
+            | no          |              |                    |               |       |
+            |             | yes          |                    |               | x     |
+            |             | no           |                    |               |       |
+            | no          | yes          |                    |               | x     |
+            | yes         | no           |                    |               |       |
+            |             |              | yes                |               | x     |
+            |             |              | no                 |               |       |
+            | no          |              | yes                |               | x     |
+            | yes         |              | no                 |               |       |
+            |             | no           | yes                |               | x     |
+            |             | yes          | no                 |               |       |
+            |             |              |                    | yes           | x     |
+            |             |              |                    | no            |       |
+            | no          |              |                    | yes           | x     |
+            | yes         |              |                    | no            |       |
+            |             | no           |                    | yes           | x     |
+            |             | yes          |                    | no            |       |
+            |             |              | no                 | yes           | x     |
+            |             |              | yes                | no            |       |
 
-	Scenario: Car - Overwriting implied acccess on nodes
-		Then routability should be
-		 | highway | node/access | node/vehicle | node/motor_vehicle | node/motorcar | bothw |
-		 | primary |             |              |                    |               | x     |
-		 | runway  |             |              |                    |               |       |
-		 | primary | no          |              |                    |               |       |
-		 | primary |             | no           |                    |               |       |
-		 | primary |             |              | no                 |               |       |
-		 | primary |             |              |                    | no            |       |
-		 | runway  | yes         |              |                    |               |       |
-		 | runway  |             | yes          |                    |               |       |
-		 | runway  |             |              | yes                |               |       |
-		 | runway  |             |              |                    | yes           |       |
-	
-	Scenario: Car - Access tags on ways
-	 	Then routability should be
-		 | access       | bothw |
-		 | yes          | x     |
-		 | permissive   | x     |
-		 | designated   | x     |
-		 | no           |       |
-		 | private      |       |
-		 | agricultural |       |
-		 | forestry     |       |
-		 | some_tag     | x     |
+    Scenario: Car - Overwriting implied acccess on ways
+        Then routability should be
+            | highway | access | vehicle | motor_vehicle | motorcar | bothw |
+            | primary |        |         |               |          | x     |
+            | runway  |        |         |               |          |       |
+            | primary | no     |         |               |          |       |
+            | primary |        | no      |               |          |       |
+            | primary |        |         | no            |          |       |
+            | primary |        |         |               | no       |       |
+            | runway  | yes    |         |               |          | x     |
+            | runway  |        | yes     |               |          | x     |
+            | runway  |        |         | yes           |          | x     |
+            | runway  |        |         |               | yes      | x     |
 
+    Scenario: Car - Overwriting implied acccess on nodes
+        Then routability should be
+            | highway | node/access | node/vehicle | node/motor_vehicle | node/motorcar | bothw |
+            | primary |             |              |                    |               | x     |
+            | runway  |             |              |                    |               |       |
+            | primary | no          |              |                    |               |       |
+            | primary |             | no           |                    |               |       |
+            | primary |             |              | no                 |               |       |
+            | primary |             |              |                    | no            |       |
+            | runway  | yes         |              |                    |               |       |
+            | runway  |             | yes          |                    |               |       |
+            | runway  |             |              | yes                |               |       |
+            | runway  |             |              |                    | yes           |       |
 
-	Scenario: Car - Access tags on nodes
-	 	Then routability should be
-		 | node/access  | bothw |
-		 | yes          | x     |
-		 | permissive   | x     |
-		 | designated   | x     |
-		 | no           |       |
-		 | private      |       |
-		 | agricultural |       |
-		 | forestry     |       |
-		 | some_tag     | x     |
+    Scenario: Car - Access tags on ways
+        Then routability should be
+            | access       | bothw |
+            | yes          | x     |
+            | permissive   | x     |
+            | designated   | x     |
+            | no           |       |
+            | private      |       |
+            | agricultural |       |
+            | forestry     |       |
+            | some_tag     | x     |
 
-	Scenario: Car - Access tags on both node and way
-	 	Then routability should be
-		 | access   | node/access | bothw |
-		 | yes      | yes         | x     |
-		 | yes      | no          |       |
-		 | yes      | some_tag    | x     |
-		 | no       | yes         |       |
-		 | no       | no          |       |
-		 | no       | some_tag    |       |
-		 | some_tag | yes         | x     |
-		 | some_tag | no          |       |
-		 | some_tag | some_tag    | x     |
 
-	Scenario: Car - Access combinations
-	 	Then routability should be
-		 | highway     | accesss      | vehicle    | motor_vehicle | motorcar   | bothw |
-		 | runway      | private      |            |               | permissive | x     |
-		 | primary     | forestry     |            | yes           |            | x     |
-		 | cycleway    |              |            | designated    |            | x     |
-		 | residential |              | yes        | no            |            |       |
-		 | motorway    | yes          | permissive |               | private    |       |
-		 | trunk       | agricultural | designated | permissive    | no         |       |
+    Scenario: Car - Access tags on nodes
+        Then routability should be
+            | node/access  | bothw |
+            | yes          | x     |
+            | permissive   | x     |
+            | designated   | x     |
+            | no           |       |
+            | private      |       |
+            | agricultural |       |
+            | forestry     |       |
+            | some_tag     | x     |
 
-	Scenario: Car - Ignore access tags for other modes
-	 	Then routability should be
-		 | highway | foot | bicycle | psv | motorhome | bothw |
-		 | runway  | yes  |         |     |           |       |
-		 | primary | no   |         |     |           | x     |
-		 | runway  |      | yes     |     |           |       |
-		 | primary |      | no      |     |           | x     |
-		 | runway  |      |         | yes |           |       |
-		 | primary |      |         | no  |           | x     |
-		 | runway  |      |         |     | yes       |       |
-		 | primary |      |         |     | no        | x     |
+    Scenario: Car - Access tags on both node and way
+        Then routability should be
+            | access   | node/access | bothw |
+            | yes      | yes         | x     |
+            | yes      | no          |       |
+            | yes      | some_tag    | x     |
+            | no       | yes         |       |
+            | no       | no          |       |
+            | no       | some_tag    |       |
+            | some_tag | yes         | x     |
+            | some_tag | no          |       |
+            | some_tag | some_tag    | x     |
+
+    Scenario: Car - Access combinations
+        Then routability should be
+            | highway     | accesss      | vehicle    | motor_vehicle | motorcar   | bothw |
+            | runway      | private      |            |               | permissive | x     |
+            | primary     | forestry     |            | yes           |            | x     |
+            | cycleway    |              |            | designated    |            | x     |
+            | residential |              | yes        | no            |            |       |
+            | motorway    | yes          | permissive |               | private    |       |
+            | trunk       | agricultural | designated | permissive    | no         |       |
+
+    Scenario: Car - Ignore access tags for other modes
+        Then routability should be
+            | highway | foot | bicycle | psv | motorhome | bothw |
+            | runway  | yes  |         |     |           |       |
+            | primary | no   |         |     |           | x     |
+            | runway  |      | yes     |     |           |       |
+            | primary |      | no      |     |           | x     |
+            | runway  |      |         | yes |           |       |
+            | primary |      |         | no  |           | x     |
+            | runway  |      |         |     | yes       |       |
+            | primary |      |         |     | no        | x     |
diff --git a/features/car/barrier.feature b/features/car/barrier.feature
index 9d37d35..e637049 100644
--- a/features/car/barrier.feature
+++ b/features/car/barrier.feature
@@ -1,38 +1,38 @@
 @routing @car @barrier
 Feature: Car - Barriers
 
-	Background:
-		Given the profile "car"
+    Background:
+        Given the profile "car"
 
-	Scenario: Car - Barriers 
-		Then routability should be
-		 | node/barrier   | bothw |
-		 |                | x     |
-		 | bollard        |       |
-		 | gate           | x     |
-		 | cattle_grid    | x     |
-		 | border_control | x     |
-		 | toll_booth     | x     |
-		 | sally_port     | x     |
-		 | entrance       |       |
-		 | wall           |       |
-		 | fence          |       |
-		 | some_tag       |       |
+    Scenario: Car - Barriers
+        Then routability should be
+            | node/barrier   | bothw |
+            |                | x     |
+            | bollard        |       |
+            | gate           | x     |
+            | cattle_grid    | x     |
+            | border_control | x     |
+            | toll_booth     | x     |
+            | sally_port     | x     |
+            | entrance       | x     |
+            | wall           |       |
+            | fence          |       |
+            | some_tag       |       |
 
-	Scenario: Car - Access tag trumphs barriers
-		Then routability should be
-		 | node/barrier | node/access   | bothw |
-		 | gate         |               | x     |
-		 | gate         | yes           | x     |
-		 | gate         | permissive    | x     |
-		 | gate         | designated    | x     |
-		 | gate         | no            |       |
-		 | gate         | private       |       |
-		 | gate         | agricultural  |       |
-		 | wall         |               |       |
-		 | wall         | yes           | x     |
-		 | wall         | permissive    | x     |
-		 | wall         | designated    | x     |
-		 | wall         | no            |       |
-		 | wall         | private       |       |
-		 | wall         | agricultural  |       |
+    Scenario: Car - Access tag trumphs barriers
+        Then routability should be
+            | node/barrier | node/access   | bothw |
+            | gate         |               | x     |
+            | gate         | yes           | x     |
+            | gate         | permissive    | x     |
+            | gate         | designated    | x     |
+            | gate         | no            |       |
+            | gate         | private       |       |
+            | gate         | agricultural  |       |
+            | wall         |               |       |
+            | wall         | yes           | x     |
+            | wall         | permissive    | x     |
+            | wall         | designated    | x     |
+            | wall         | no            |       |
+            | wall         | private       |       |
+            | wall         | agricultural  |       |
diff --git a/features/car/destination.feature b/features/car/destination.feature
index 43059e1..506aa21 100644
--- a/features/car/destination.feature
+++ b/features/car/destination.feature
@@ -1,77 +1,77 @@
 @routing @car @destination @todo
 Feature: Car - Destination only, no passing through
 
-	Background:
-		Given the profile "car"
-		
-	Scenario: Car - Destination only street
-		Given the node map
-		 | a |   |   |   | e |
-		 |   | b | c | d |   |
-		 |   |   |   |   |   |
-		 | x |   |   |   | y |
+    Background:
+        Given the profile "car"
 
-		And the ways
-		 | nodes | access      |
-		 | ab    |             |
-		 | bcd   | destination |
-		 | de    |             |
-		 | axye  |             |
+    Scenario: Car - Destination only street
+        Given the node map
+            | a |   |   |   | e |
+            |   | b | c | d |   |
+            |   |   |   |   |   |
+            | x |   |   |   | y |
 
-		When I route I should get
-		 | from | to | route     |
-		 | a    | b  | ab        |
-		 | a    | c  | ab,bcd    |
-		 | a    | d  | ab,bcd    |
-		 | a    | e  | axye      |
-		 | e    | d  | de        |
-		 | e    | c  | de,bcd    |
-		 | e    | b  | de,bcd    |
-		 | e    | a  | axye      |
-		
-	Scenario: Car - Destination only street
-		Given the node map
-		 | a |   |   |   | e |
-		 |   | b | c | d |   |
-		 |   |   |   |   |   |
-		 | x |   |   |   | y |
+        And the ways
+            | nodes | access      |
+            | ab    |             |
+            | bcd   | destination |
+            | de    |             |
+            | axye  |             |
 
-		And the ways
-		 | nodes | access      |
-		 | ab    |             |
-		 | bc    | destination |
-		 | cd    | destination |
-		 | de    |             |
-		 | axye  |             |
+        When I route I should get
+            | from | to | route  |
+            | a    | b  | ab     |
+            | a    | c  | ab,bcd |
+            | a    | d  | ab,bcd |
+            | a    | e  | axye   |
+            | e    | d  | de     |
+            | e    | c  | de,bcd |
+            | e    | b  | de,bcd |
+            | e    | a  | axye   |
 
-		When I route I should get
-		 | from | to | route    |
-		 | a    | b  | ab       |
-		 | a    | c  | ab,bc    |
-		 | a    | d  | ab,bc,cd |
-		 | a    | e  | axye     |
-		 | e    | d  | de       |
-		 | e    | c  | de,dc    |
-		 | e    | b  | de,dc,bc |
-		 | e    | a  | axye     |
+    Scenario: Car - Destination only street
+        Given the node map
+            | a |   |   |   | e |
+            |   | b | c | d |   |
+            |   |   |   |   |   |
+            | x |   |   |   | y |
 
-	Scenario: Car - Routing inside a destination only area
-		Given the node map
-		 | a |   | c |   | e |
-		 |   | b |   | d |   |
-		 | x |   |   |   | y |
+        And the ways
+            | nodes | access      |
+            | ab    |             |
+            | bc    | destination |
+            | cd    | destination |
+            | de    |             |
+            | axye  |             |
 
-		And the ways
-		 | nodes | access      |
-		 | ab    | destination |
-		 | bc    | destination |
-		 | cd    | destination |
-		 | de    | destination |
-		 | axye  |             |
+        When I route I should get
+            | from | to | route    |
+            | a    | b  | ab       |
+            | a    | c  | ab,bc    |
+            | a    | d  | ab,bc,cd |
+            | a    | e  | axye     |
+            | e    | d  | de       |
+            | e    | c  | de,dc    |
+            | e    | b  | de,dc,bc |
+            | e    | a  | axye     |
 
-		When I route I should get
-		 | from | to | route       |
-		 | a    | e  | ab,bc,cd,de |
-		 | e    | a  | de,cd,bc,ab |
-		 | b    | d  | bc,cd       |
-		 | d    | b  | cd,bc       |
\ No newline at end of file
+    Scenario: Car - Routing inside a destination only area
+        Given the node map
+            | a |   | c |   | e |
+            |   | b |   | d |   |
+            | x |   |   |   | y |
+
+        And the ways
+            | nodes | access      |
+            | ab    | destination |
+            | bc    | destination |
+            | cd    | destination |
+            | de    | destination |
+            | axye  |             |
+
+        When I route I should get
+            | from | to | route       |
+            | a    | e  | ab,bc,cd,de |
+            | e    | a  | de,cd,bc,ab |
+            | b    | d  | bc,cd       |
+            | d    | b  | cd,bc       |
diff --git a/features/car/ferry.feature b/features/car/ferry.feature
index 3182c75..3e90cf0 100644
--- a/features/car/ferry.feature
+++ b/features/car/ferry.feature
@@ -1,30 +1,28 @@
 @routing @car @ferry
 Feature: Car - Handle ferry routes
 
-	Background:
-		Given the profile "car"
-	
-	Scenario: Car - Use a ferry route
-		Given the node map
-		 | a | b | c |   |   |
-		 |   |   | d |   |   |
-		 |   |   | e | f | g |
-	
-		And the ways
-		 | nodes | highway | route | bicycle |
-		 | abc   | primary |       |         |
-		 | cde   |         | ferry | yes     |
-		 | efg   | primary |       |         |
-   
-		When I route I should get
-		 | from | to | route       |
-		 | a    | g  | abc,cde,efg |
-		 | b    | f  | abc,cde,efg |
-		 | e    | c  | cde         |
-		 | e    | b  | cde,abc     |
-		 | e    | a  | cde,abc     |
-		 | c    | e  | cde         |
-		 | c    | f  | cde,efg     |
-		 | c    | g  | cde,efg     |
+    Background:
+        Given the profile "car"
 
+    Scenario: Car - Use a ferry route
+        Given the node map
+            | a | b | c |   |   |
+            |   |   | d |   |   |
+            |   |   | e | f | g |
 
+        And the ways
+            | nodes | highway | route | bicycle |
+            | abc   | primary |       |         |
+            | cde   |         | ferry | yes     |
+            | efg   | primary |       |         |
+
+        When I route I should get
+            | from | to | route       |
+            | a    | g  | abc,cde,efg |
+            | b    | f  | abc,cde,efg |
+            | e    | c  | cde         |
+            | e    | b  | cde,abc     |
+            | e    | a  | cde,abc     |
+            | c    | e  | cde         |
+            | c    | f  | cde,efg     |
+            | c    | g  | cde,efg     |
diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature
index 3e09a0a..9e77cde 100644
--- a/features/car/maxspeed.feature
+++ b/features/car/maxspeed.feature
@@ -1,54 +1,65 @@
 @routing @maxspeed @car
 Feature: Car - Max speed restrictions
+OSRM will use 4/5 of the projected free-flow speed.
 
-	Background: Use specific speeds
-		Given the profile "car"
-		Given a grid size of 1000 meters
-	
-	Scenario: Car - Respect maxspeeds when lower that way type speed
-		Given the node map
-		 | a | b | c |
-
-		And the ways
-		 | nodes | highway | maxspeed |
-		 | ab    | trunk   |          |
-		 | bc    | trunk   | 10       |
-
-		When I route I should get
-		 | from | to | route | time      |
-		 | a    | b  | ab    | 42s ~10%  |
-		 | b    | c  | bc    | 360s ~10% |
-
-	Scenario: Car - Do not ignore maxspeed when higher than way speed
-		Given the node map
-		 | a | b | c |
-
-		And the ways
-		 | nodes | highway     | maxspeed |
-		 | ab    | residential |          |
-		 | bc    | residential | 85       |
-
-		When I route I should get
-		 | from | to | route | time      |
-		 | a    | b  | ab    | 144s ~10% |
-		 | b    | c  | bc    | 42s ~10%  |
-
-     Scenario: Car - Forward/backward maxspeed
-        Given the shortcuts
- 		 | key   | value     |
- 		 | car   | 12s ~10%  |
- 		 | run   | 73s ~10%  |
- 		 | walk  | 146s ~10% |
- 		 | snail | 720s ~10% |
-  		
-  		And a grid size of 100 meters
-
-  	 	Then routability should be
-     	 | maxspeed | maxspeed:forward | maxspeed:backward | forw  | backw |
-     	 |          |                  |                   | car   | car   |
-     	 | 10       |                  |                   | run   | run   |
-     	 |          | 10               |                   | run   | car   |
-     	 |          |                  | 10                | car   | run   |
-     	 | 1        | 10               |                   | run   | snail |
-     	 | 1        |                  | 10                | snail | run   |
-     	 | 1        | 5                | 10                | walk  | run   |
+    Background: Use specific speeds
+        Given the profile "car"
+        Given a grid size of 1000 meters
+
+    Scenario: Car - Respect maxspeeds when lower that way type speed
+        Given the node map
+            | a | b | c |
+
+        And the ways
+            | nodes | highway | maxspeed |
+            | ab    | trunk   |          |
+            | bc    | trunk   | 60       |
+
+        When I route I should get
+            | from | to | route | speed        |
+            | a    | b  | ab    | 67 km/h      |
+            | b    | c  | bc    | 48 km/h +- 1 |
+
+    Scenario: Car - Do not ignore maxspeed when higher than way speed
+        Given the node map
+            | a | b | c |
+
+        And the ways
+            | nodes | highway     | maxspeed |
+            | ab    | residential |          |
+            | bc    | residential | 90       |
+
+        When I route I should get
+            | from | to | route | speed        |
+            | a    | b  | ab    | 20 km/h      |
+            | b    | c  | bc    | 72 km/h +- 1 |
+
+    Scenario: Car - Forward/backward maxspeed
+        Given a grid size of 100 meters
+
+        Then routability should be
+            | highway | maxspeed | maxspeed:forward | maxspeed:backward | forw        | backw        |
+            | primary |          |                  |                   | 51 km/h     | 51 km/h      |
+            | primary | 60       |                  |                   | 48 km/h     | 48 km/h      |
+            | primary |          | 60               |                   | 48 km/h     | 65 km/h      |
+            | primary |          |                  | 60                | 51 km/h     | 48 km/h      |
+            | primary | 15       | 60               |                   | 48 km/h     | 15 km/h +- 1 |
+            | primary | 15       |                  | 60                | 12 km/h +- 1| 48 km/h      |
+            | primary | 15       | 30               | 60                | 24 km/h     | 48 km/h      |
+
+    Scenario: Car - Maxspeed should not allow routing on unroutable ways
+        Then routability should be
+            | highway   | railway | access | maxspeed | maxspeed:forward | maxspeed:backward | bothw |
+            | primary   |         |        |          |                  |                   | x     |
+            | secondary |         | no     |          |                  |                   |       |
+            | secondary |         | no     | 100      |                  |                   |       |
+            | secondary |         | no     |          | 100              |                   |       |
+            | secondary |         | no     |          |                  | 100               |       |
+            | (nil)     | train   |        |          |                  |                   |       |
+            | (nil)     | train   |        | 100      |                  |                   |       |
+            | (nil)     | train   |        |          | 100              |                   |       |
+            | (nil)     | train   |        |          |                  | 100               |       |
+            | runway    |         |        |          |                  |                   |       |
+            | runway    |         |        | 100      |                  |                   |       |
+            | runway    |         |        |          | 100              |                   |       |
+            | runway    |         |        |          |                  | 100               |       |
diff --git a/features/car/names.feature b/features/car/names.feature
index d7d98b7..ac4bfc8 100644
--- a/features/car/names.feature
+++ b/features/car/names.feature
@@ -1,33 +1,33 @@
 @routing @car @names
 Feature: Car - Street names in instructions
 
-	Background:
-		Given the profile "car"
-	
-	Scenario: Car - A named street
-		Given the node map
-		 | a | b |
-		 |   | c |
-	
-		And the ways
-		 | nodes | name     |
-		 | ab    | My Way   |
-		 | bc    | Your Way |
-    
-		When I route I should get
-		 | from | to | route           |
-		 | a    | c  | My Way,Your Way |
-	
-	@todo
-	Scenario: Car - Use way type to describe unnamed ways
-		Given the node map
-		 | a | b | c | d |
+    Background:
+        Given the profile "car"
 
-		And the ways
-		 | nodes | highway     | name |
-		 | ab    | tertiary    |      |
-		 | bcd   | residential |      |
+    Scenario: Car - A named street
+        Given the node map
+            | a | b |
+            |   | c |
 
-		When I route I should get
-		 | from | to | route                |
-		 | a    | c  | tertiary,residential |
+        And the ways
+            | nodes | name     |
+            | ab    | My Way   |
+            | bc    | Your Way |
+
+        When I route I should get
+            | from | to | route           |
+            | a    | c  | My Way,Your Way |
+
+    @todo
+    Scenario: Car - Use way type to describe unnamed ways
+        Given the node map
+            | a | b | c | d |
+
+        And the ways
+            | nodes | highway     | name |
+            | ab    | tertiary    |      |
+            | bcd   | residential |      |
+
+        When I route I should get
+            | from | to | route                |
+            | a    | c  | tertiary,residential |
diff --git a/features/car/oneway.feature b/features/car/oneway.feature
index b181085..b47c3c6 100644
--- a/features/car/oneway.feature
+++ b/features/car/oneway.feature
@@ -1,73 +1,79 @@
 @routing @car @oneway
 Feature: Car - Oneway streets
-Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing
+# Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing
 
-	Background:
-		Given the profile "car"
-	
-	Scenario: Car - Simple oneway
-		Then routability should be
-		 | highway | oneway | forw | backw |
-		 | primary | yes    | x    |       |
+    Background:
+        Given the profile "car"
 
-	Scenario: Car - Simple reverse oneway
-		Then routability should be
-		 | highway | oneway | forw | backw |
-		 | primary | -1     |      | x     |
+    Scenario: Car - Simple oneway
+        Then routability should be
+            | highway | oneway | forw | backw |
+            | primary | yes    | x    |       |
 
-	Scenario: Car - Implied onewatys
-		Then routability should be
-		 | highway       | junction   | forw | backw |
-		 | motorway      |            | x    |       |
-		 | motorway_link |            | x    |       |
-		 | primary       |            | x    | x     |
-		 | motorway      | roundabout | x    |       |
-		 | motorway_link | roundabout | x    |       |
-		 | primary       | roundabout | x    |       |
+    Scenario: Car - Simple reverse oneway
+        Then routability should be
+            | highway | oneway | forw | backw |
+            | primary | -1     |      | x     |
 
-	Scenario: Car - Around the Block
-		Given the node map
-		 | a | b |
-		 | d | c |		
-	
-		And the ways
-		 | nodes | oneway |
-		 | ab    | yes    |
-		 | bc    |        |
-		 | cd    |        |
-		 | da    |        |
-    
-		When I route I should get
-		 | from | to | route    |
-		 | a    | b  | ab       |
-		 | b    | a  | bc,cd,da |
-	
-	Scenario: Car - Cars should not be affected by bicycle tags
-		Then routability should be
-		 | highway | junction   | oneway | oneway:bicycle | forw | backw |
-		 | primary |            | yes    | yes            | x    |       |
-		 | primary |            | yes    | no             | x    |       |
-		 | primary |            | yes    | -1             | x    |       |
-		 | primary |            | no     | yes            | x    | x     |
-		 | primary |            | no     | no             | x    | x     |
-		 | primary |            | no     | -1             | x    | x     |
-		 | primary |            | -1     | yes            |      | x     |
-		 | primary |            | -1     | no             |      | x     |
-		 | primary |            | -1     | -1             |      | x     |
-		 | primary | roundabout |        | yes            | x    |       |
-		 | primary | roundabout |        | no             | x    |       |
-		 | primary | roundabout |        | -1             | x    |       |
+    Scenario: Car - Implied oneways
+        Then routability should be
+            | highway       | junction   | forw | backw |
+            | motorway      |            | x    |       |
+            | motorway_link |            | x    |       |
+            | primary       |            | x    | x     |
+            | motorway      | roundabout | x    |       |
+            | motorway_link | roundabout | x    |       |
+            | primary       | roundabout | x    |       |
 
-  	Scenario: Car - Two consecutive oneways
-  		Given the node map
-  		 | a | b | c |
+    Scenario: Car - Overrule implied oneway
+        Then routability should be
+            | highway       | oneway | forw | backw |
+            | motorway      | no     | x    | x     |
+            | motorway_link | no     | x    | x     |
 
-  		And the ways
-  		 | nodes | oneway |
-  		 | ab    | yes    |
-  		 | bc    | yes    |
+    Scenario: Car - Around the Block
+        Given the node map
+            | a | b |
+            | d | c |
 
+        And the ways
+            | nodes | oneway |
+            | ab    | yes    |
+            | bc    |        |
+            | cd    |        |
+            | da    |        |
 
-  		When I route I should get
-  		 | from | to | route |
-  		 | a    | c  | ab,bc |
\ No newline at end of file
+        When I route I should get
+            | from | to | route    |
+            | a    | b  | ab       |
+            | b    | a  | bc,cd,da |
+
+    Scenario: Car - Cars should not be affected by bicycle tags
+        Then routability should be
+            | highway | junction   | oneway | oneway:bicycle | forw | backw |
+            | primary |            | yes    | yes            | x    |       |
+            | primary |            | yes    | no             | x    |       |
+            | primary |            | yes    | -1             | x    |       |
+            | primary |            | no     | yes            | x    | x     |
+            | primary |            | no     | no             | x    | x     |
+            | primary |            | no     | -1             | x    | x     |
+            | primary |            | -1     | yes            |      | x     |
+            | primary |            | -1     | no             |      | x     |
+            | primary |            | -1     | -1             |      | x     |
+            | primary | roundabout |        | yes            | x    |       |
+            | primary | roundabout |        | no             | x    |       |
+            | primary | roundabout |        | -1             | x    |       |
+
+    Scenario: Car - Two consecutive oneways
+        Given the node map
+            | a | b | c |
+
+        And the ways
+            | nodes | oneway |
+            | ab    | yes    |
+            | bc    | yes    |
+
+
+        When I route I should get
+            | from | to | route |
+            | a    | c  | ab,bc |
diff --git a/features/car/restrictions.feature b/features/car/restrictions.feature
index 91ba298..b4ccdbe 100644
--- a/features/car/restrictions.feature
+++ b/features/car/restrictions.feature
@@ -1,251 +1,314 @@
 @routing @car @restrictions
 Feature: Car - Turn restrictions
-	Handle turn restrictions as defined by http://wiki.openstreetmap.org/wiki/Relation:restriction
-	Note that if u-turns are allowed, turn restrictions can lead to suprising, but correct, routes.
-	
-	Background: Use car routing
-		Given the profile "car"
-	
-	@no_turning
-	Scenario: Car - No left turn
-		Given the node map
-		 |   | n |   |
-		 | w | j | e |
-		 |   | s |   |
-
-		And the ways
-		 | nodes | oneway |
-		 | sj    | yes    |
-		 | nj    | -1     |
-		 | wj    | -1     |
-		 | ej    | -1     |
-
-		And the relations
-		 | type        | way:from | way:to | node:via | restriction  |
-		 | restriction | sj       | wj     | j        | no_left_turn |
-
-		When I route I should get
-		 | from | to | route |
-		 | s    | w  |       |
-		 | s    | n  | sj,nj |
-		 | s    | e  | sj,ej |
-
-	@no_turning
-	Scenario: Car - No right turn
-		Given the node map
-		 |   | n |   |
-		 | w | j | e |
-		 |   | s |   |
-
-		And the ways
-		 | nodes | oneway |
-		 | sj    | yes    |
-		 | nj    | -1     |
-		 | wj    | -1     |
-		 | ej    | -1     |
-
-		And the relations
-		 | type        | way:from | way:to | node:via | restriction   |
-		 | restriction | sj       | ej     | j        | no_right_turn |
-
-		When I route I should get
-		 | from | to | route |
-		 | s    | w  | sj,wj |
-		 | s    | n  | sj,nj |
-		 | s    | e  |       |
-
-	@no_turning
-	Scenario: Car - No u-turn
-		Given the node map
-		 |   | n |   |
-		 | w | j | e |
-		 |   | s |   |
-
-		And the ways
-		 | nodes | oneway |
-		 | sj    | yes    |
-		 | nj    | -1     |
-		 | wj    | -1     |
-		 | ej    | -1     |
-
-		And the relations
-		 | type        | way:from | way:to | node:via | restriction |
-		 | restriction | sj       | wj     | j        | no_u_turn   |
-
-		When I route I should get
-		 | from | to | route |
-		 | s    | w  |       |
-		 | s    | n  | sj,nj |
-		 | s    | e  | sj,ej |
-
-	@no_turning
-	Scenario: Car - Handle any no_* relation
-		Given the node map
-		 |   | n |   |
-		 | w | j | e |
-		 |   | s |   |
-
-		And the ways
-		 | nodes | oneway |
-		 | sj    | yes    |
-		 | nj    | -1     |
-		 | wj    | -1     |
-		 | ej    | -1     |
-
-		And the relations
-		 | type        | way:from | way:to | node:via | restriction      |
-		 | restriction | sj       | wj     | j        | no_weird_zigzags |
-
-		When I route I should get
-		 | from | to | route |
-		 | s    | w  |       |
-		 | s    | n  | sj,nj |
-		 | s    | e  | sj,ej |
-
-	@only_turning
-	Scenario: Car - Only left turn
-		Given the node map
-		 |   | n |   |
-		 | w | j | e |
-		 |   | s |   |
-
-		And the ways
-		 | nodes | oneway |
-		 | sj    | yes    |
-		 | nj    | -1     |
-		 | wj    | -1     |
-		 | ej    | -1     |
-
-		And the relations
-		 | type        | way:from | way:to | node:via | restriction    |
-		 | restriction | sj       | wj     | j        | only_left_turn |
-
-		When I route I should get
-		 | from | to | route |
-		 | s    | w  | sj,wj |
-		 | s    | n  |       |
-		 | s    | e  |       |
-
-	@only_turning
-	Scenario: Car - Only right turn
-		Given the node map
-		 |   | n |   |
-		 | w | j | e |
-		 |   | s |   |
-
-		And the ways
-		 | nodes | oneway |
-		 | sj    | yes    |
-		 | nj    | -1     |
-		 | wj    | -1     |
-		 | ej    | -1     |
-
-		And the relations
-		 | type        | way:from | way:to | node:via | restriction     |
-		 | restriction | sj       | ej     | j        | only_right_turn |
-
-		When I route I should get
-		 | from | to | route |
-		 | s    | w  |       |
-		 | s    | n  |       |
-		 | s    | e  | sj,ej |
-	
-	@only_turning
-	Scenario: Car - Only straight on
-		Given the node map
-		 |   | n |   |
-		 | w | j | e |
-		 |   | s |   |
-
-		And the ways
-		 | nodes | oneway |
-		 | sj    | yes    |
-		 | nj    | -1     |
-		 | wj    | -1     |
-		 | ej    | -1     |
-
-		And the relations
-		 | type        | way:from | way:to | node:via | restriction      |
-		 | restriction | sj       | nj     | j        | only_straight_on |
-
-		When I route I should get
-		 | from | to | route |
-		 | s    | w  |       |
-		 | s    | n  | sj,nj |
-		 | s    | e  |       |
-
-	@no_turning
-	Scenario: Car - Handle any only_* restriction
-		Given the node map
-		 |   | n |   |
-		 | w | j | e |
-		 |   | s |   |
-
-		And the ways
-		 | nodes | oneway |
-		 | sj    | yes    |
-		 | nj    | -1     |
-		 | wj    | -1     |
-		 | ej    | -1     |
-
-		And the relations
-		 | type        | way:from | way:to | node:via | restriction        |
-		 | restriction | sj       | nj     | j        | only_weird_zigzags |
-
-		When I route I should get
-		 | from | to | route |
-		 | s    | w  |       |
-		 | s    | n  | sj,nj |
-		 | s    | e  |       |
-
-  	@except
-  	Scenario: Car - Except tag and on no_ restrictions
-  		Given the node map
-  		 | b | x | c |
-  		 | a | j | d |
-  		 |   | s |   |
-
-  		And the ways
-  		 | nodes | oneway |
-  		 | sj    | no     |
-  		 | xj    | -1     |
-  		 | aj    | -1     |
-  		 | bj    | no     |
-  		 | cj    | no     |
-  		 | dj    | -1     |
-
-  		And the relations
-  		 | type        | way:from | way:to | node:via | restriction   | except   |
-  		 | restriction | sj       | aj     | j        | no_left_turn  | motorcar |
-  		 | restriction | sj       | bj     | j        | no_left_turn  |          |
-  		 | restriction | sj       | cj     | j        | no_right_turn |          |
-  		 | restriction | sj       | dj     | j        | no_right_turn | motorcar |
-
-  		When I route I should get
-  		 | from | to | route |
-  		 | s    | a  | sj,aj |
-  		 | s    | b  |       |
-  		 | s    | c  |       |
-  		 | s    | d  | sj,dj |
-
-   	@except
-   	Scenario: Car - Except tag and on only_ restrictions
-   		Given the node map
-   		 | a |   | b |
-   		 |   | j |   |
-   		 |   | s |   |
-
-   		And the ways
-   		 | nodes | oneway |
-   		 | sj    | yes    |
-   		 | aj    | no     |
-   		 | bj    | no     |
-
-   		And the relations
-   		 | type        | way:from | way:to | node:via | restriction      | except   |
-   		 | restriction | sj       | aj     | j        | only_straight_on | motorcar |
-
-   		When I route I should get
-   		 | from | to | route |
-   		 | s    | a  | sj,aj |
-   		 | s    | b  | sj,bj |
+# Handle turn restrictions as defined by http://wiki.openstreetmap.org/wiki/Relation:restriction
+# Note that if u-turns are allowed, turn restrictions can lead to suprising, but correct, routes.
+
+    Background: Use car routing
+        Given the profile "car"
+
+    @no_turning
+    Scenario: Car - No left turn
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | nj    | -1     |
+            | wj    | -1     |
+            | ej    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction  |
+            | restriction | sj       | wj     | j        | no_left_turn |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  |       |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @no_turning
+    Scenario: Car - No straight on
+        Given the node map
+            | a | b | j | d | e |
+            | v |   |   |   | z |
+            |   | w | x | y |   |
+
+        And the ways
+            | nodes | oneway |
+            | ab    | no     |
+            | bj    | no     |
+            | jd    | no     |
+            | de    | no     |
+            | av    | yes    |
+            | vw    | yes    |
+            | wx    | yes    |
+            | xy    | yes    |
+            | yz    | yes    |
+            | ze    | yes    |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction    |
+            | restriction | bj       | jd     | j        | no_straight_on |
+
+        When I route I should get
+            | from | to | route             |
+            | a    | e  | av,vw,wx,xy,yz,ze |
+
+    @no_turning
+    Scenario: Car - No right turn
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | nj    | -1     |
+            | wj    | -1     |
+            | ej    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction   |
+            | restriction | sj       | ej     | j        | no_right_turn |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  | sj,nj |
+            | s    | e  |       |
+
+    @no_turning
+    Scenario: Car - No u-turn
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | nj    | -1     |
+            | wj    | -1     |
+            | ej    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction |
+            | restriction | sj       | wj     | j        | no_u_turn   |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  |       |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @no_turning
+    Scenario: Car - Handle any no_* relation
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | nj    | -1     |
+            | wj    | -1     |
+            | ej    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction      |
+            | restriction | sj       | wj     | j        | no_weird_zigzags |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  |       |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @only_turning
+    Scenario: Car - Only left turn
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | nj    | -1     |
+            | wj    | -1     |
+            | ej    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction    |
+            | restriction | sj       | wj     | j        | only_left_turn |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  |       |
+            | s    | e  |       |
+
+    @only_turning
+    Scenario: Car - Only right turn
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | nj    | -1     |
+            | wj    | -1     |
+            | ej    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction     |
+            | restriction | sj       | ej     | j        | only_right_turn |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  |       |
+            | s    | n  |       |
+            | s    | e  | sj,ej |
+
+    @only_turning
+    Scenario: Car - Only straight on
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | nj    | -1     |
+            | wj    | -1     |
+            | ej    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction      |
+            | restriction | sj       | nj     | j        | only_straight_on |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  |       |
+            | s    | n  | sj,nj |
+            | s    | e  |       |
+
+    @no_turning
+    Scenario: Car - Handle any only_* restriction
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | nj    | -1     |
+            | wj    | -1     |
+            | ej    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction        |
+            | restriction | sj       | nj     | j        | only_weird_zigzags |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  |       |
+            | s    | n  | sj,nj |
+            | s    | e  |       |
+
+    @except
+    Scenario: Car - Except tag and on no_ restrictions
+        Given the node map
+            | b | x | c |
+            | a | j | d |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | no     |
+            | xj    | -1     |
+            | aj    | -1     |
+            | bj    | no     |
+            | cj    | no     |
+            | dj    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction   | except   |
+            | restriction | sj       | aj     | j        | no_left_turn  | motorcar |
+            | restriction | sj       | bj     | j        | no_left_turn  |          |
+            | restriction | sj       | cj     | j        | no_right_turn |          |
+            | restriction | sj       | dj     | j        | no_right_turn | motorcar |
+
+        When I route I should get
+            | from | to | route |
+            | s    | a  | sj,aj |
+            | s    | b  |       |
+            | s    | c  |       |
+            | s    | d  | sj,dj |
+
+    @except
+    Scenario: Car - Except tag and on only_ restrictions
+        Given the node map
+            | a |   | b |
+            |   | j |   |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | aj    | no     |
+            | bj    | no     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction      | except   |
+            | restriction | sj       | aj     | j        | only_straight_on | motorcar |
+
+        When I route I should get
+            | from | to | route |
+            | s    | a  | sj,aj |
+            | s    | b  | sj,bj |
+
+    @except
+    Scenario: Car - Several only_ restrictions at the same segment
+        Given the node map
+            |   |   |   |   | y |   |   |   |   |
+            | i | j | f | b | x | a | e | g | h |
+            |   |   |   |   |   |   |   |   |   |
+            |   |   |   | c |   | d |   |   |   |
+
+        And the ways
+            | nodes | oneway |
+            | fb    | no     |
+            | bx    | -1     |
+            | xa    | no     |
+            | ae    | no     |
+            | cb    | no     |
+            | dc    | -1     |
+            | da    | no     |
+            | fj    | no     |
+            | jf    | no     |
+            | ge    | no     |
+            | hg    | no     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction      |
+            | restriction | ae       | xa     | a        | only_straight_on |
+            | restriction | xb       | fb     | b        | only_straight_on |
+            | restriction | cb       | bx     | b        | only_right_turn  |
+            | restriction | da       | ae     | a        | only_right_turn  |
+
+        When I route I should get
+            | from | to | route                            |
+            | e    | f  | ae,xa,bx,fb                      |
+            | c    | f  | dc,da,ae,ge,hg,hg,ge,ae,xa,bx,fb |
+            | d    | f  | da,ae,ge,hg,hg,ge,ae,xa,bx,fb    |
diff --git a/features/car/roundabout.feature b/features/car/roundabout.feature
new file mode 100644
index 0000000..2965479
--- /dev/null
+++ b/features/car/roundabout.feature
@@ -0,0 +1,30 @@
+ at routing @car @roundabout @instruction
+Feature: Roundabout Instructions
+
+    Background:
+        Given the profile "car"
+
+    Scenario: Car - Roundabout instructions
+        Given the node map
+            |   |   | v |   |   |
+            |   |   | d |   |   |
+            | s | a |   | c | u |
+            |   |   | b |   |   |
+            |   |   | t |   |   |
+
+        And the ways
+            | nodes | junction   |
+            | sa    |            |
+            | tb    |            |
+            | uc    |            |
+            | vd    |            |
+            | abcda | roundabout |
+
+        When I route I should get
+            | from | to | route | turns                               |
+            | s    | t  | sa,tb | head,enter_roundabout-1,destination |
+            | s    | u  | sa,uc | head,enter_roundabout-2,destination |
+            | s    | v  | sa,vd | head,enter_roundabout-3,destination |
+            | u    | v  | uc,vd | head,enter_roundabout-1,destination |
+            | u    | s  | uc,sa | head,enter_roundabout-2,destination |
+            | u    | t  | uc,tb | head,enter_roundabout-3,destination |
diff --git a/features/car/shuttle_train.feature b/features/car/shuttle_train.feature
index e58ffa2..97f32e5 100644
--- a/features/car/shuttle_train.feature
+++ b/features/car/shuttle_train.feature
@@ -1,33 +1,31 @@
 @routing @car @shuttle_train
 Feature: Car - Handle ferryshuttle train routes
 
-	Background:
-		Given the profile "car"
+    Background:
+        Given the profile "car"
 
-	Scenario: Car - Use a ferry route
-		Given the node map
-		 | a | b | c |   |   |   |
-		 |   |   | d |   |   |   |
-		 |   |   | e | f | g | h |
-
-		And the ways
-		 | nodes | highway | route         | bicycle |
-		 | abc   | primary |               |         |
-		 | cde   |         | shuttle_train | yes     |
-		 | ef    | primary |               |         |
-		 | fg    |         | ferry_man     |         |
-		 | gh	 | primary |               | no      |
-
-		When I route I should get
-		 | from | to | route      |
-		 | a    | f  | abc,cde,ef |
-		 | b    | f  | abc,cde,ef |
-		 | e    | c  | cde        |
-		 | e    | b  | cde,abc    |
-		 | e    | a  | cde,abc    |
-		 | c    | e  | cde        |
-		 | c    | f  | cde,ef     |
-		 | f    | g  |            |
-		 | g    | h  | gh		  |
+    Scenario: Car - Use a ferry route
+        Given the node map
+            | a | b | c |   |   |   |
+            |   |   | d |   |   |   |
+            |   |   | e | f | g | h |
 
+        And the ways
+            | nodes | highway | route         | bicycle |
+            | abc   | primary |               |         |
+            | cde   |         | shuttle_train | yes     |
+            | ef    | primary |               |         |
+            | fg    |         | ferry_man     |         |
+            | gh    | primary |               | no      |
 
+        When I route I should get
+            | from | to | route      |
+            | a    | f  | abc,cde,ef |
+            | b    | f  | abc,cde,ef |
+            | e    | c  | cde        |
+            | e    | b  | cde,abc    |
+            | e    | a  | cde,abc    |
+            | c    | e  | cde        |
+            | c    | f  | cde,ef     |
+            | f    | g  |            |
+            | g    | h  | gh         |
diff --git a/features/car/speed.feature b/features/car/speed.feature
new file mode 100644
index 0000000..4f54a33
--- /dev/null
+++ b/features/car/speed.feature
@@ -0,0 +1,24 @@
+ at routing @car @speed
+Feature: Car - speeds
+
+    Background:
+        Given the profile "car"
+        And a grid size of 1000 meters
+
+    Scenario: Car - speed of various way types
+        Then routability should be
+            | highway        | oneway | bothw        |
+            | motorway       | no     | 72 km/h      |
+            | motorway_link  | no     | 60 km/h      |
+            | trunk          | no     | 67 km/h +- 1 |
+            | trunk_link     | no     | 55 km/h +- 1 |
+            | primary        | no     | 52 km/h +- 1 |
+            | primary_link   | no     | 48 km/h      |
+            | secondary      | no     | 43 km/h +- 1 |
+            | secondary_link | no     | 40 km/h      |
+            | tertiary       | no     | 32 km/h      |
+            | tertiary_link  | no     | 24 km/h      |
+            | unclassified   | no     | 20 km/h      |
+            | residential    | no     | 20 km/h      |
+            | living_street  | no     |  8 km/h      |
+            | service        | no     | 12 km/h      |
diff --git a/features/car/way.feature b/features/car/way.feature
index 8ca62a5..d6d324c 100644
--- a/features/car/way.feature
+++ b/features/car/way.feature
@@ -1,33 +1,33 @@
 @routing @car @way
 Feature: Car - Accessability of different way types
 
-	Background:
-		Given the profile "car"
+    Background:
+        Given the profile "car"
 
-	Scenario: Car - Basic access
-	 	Then routability should be
-		 | highway        | forw |
-		 | (nil)          |      |
-		 | motorway       | x    |
-		 | motorway_link  | x    |
-		 | trunk          | x    |
-		 | trunk_link     | x    |
-		 | primary        | x    |
-		 | primary_link   | x    |
-		 | secondary      | x    |
-		 | secondary_link | x    |
-		 | tertiary       | x    |
-		 | tertiary_link  | x    |
-		 | residential    | x    |
-		 | service        | x    |
-		 | unclassified   | x    |
-		 | living_street  | x    |
-		 | road           |      |
-		 | track          |      |
-		 | path           |      |
-		 | footway        |      |
-		 | pedestrian     |      |
-		 | steps          |      |
-		 | pier           |      |
-		 | cycleway       |      |
-		 | bridleway      |      |
\ No newline at end of file
+    Scenario: Car - Basic access
+        Then routability should be
+            | highway        | forw |
+            | (nil)          |      |
+            | motorway       | x    |
+            | motorway_link  | x    |
+            | trunk          | x    |
+            | trunk_link     | x    |
+            | primary        | x    |
+            | primary_link   | x    |
+            | secondary      | x    |
+            | secondary_link | x    |
+            | tertiary       | x    |
+            | tertiary_link  | x    |
+            | residential    | x    |
+            | service        | x    |
+            | unclassified   | x    |
+            | living_street  | x    |
+            | road           |      |
+            | track          |      |
+            | path           |      |
+            | footway        |      |
+            | pedestrian     |      |
+            | steps          |      |
+            | pier           |      |
+            | cycleway       |      |
+            | bridleway      |      |
diff --git a/features/foot/access.feature b/features/foot/access.feature
new file mode 100644
index 0000000..4d81d0e
--- /dev/null
+++ b/features/foot/access.feature
@@ -0,0 +1,95 @@
+ at routing @foot @access
+Feature: Foot - Access tags on ways
+# Reference: http://wiki.openstreetmap.org/wiki/Key:access
+
+    Background:
+        Given the profile "foot"
+
+    Scenario: Foot - Access tag hierachy on ways
+        Then routability should be
+            | highway  | access | foot | bothw |
+            | footway  |        |      | x     |
+            | footway  |        | yes  | x     |
+            | footway  |        | no   |       |
+            | footway  | yes    |      | x     |
+            | footway  | yes    | yes  | x     |
+            | footway  | yes    | no   |       |
+            | footway  | no     |      |       |
+            | footway  | no     | yes  | x     |
+            | footway  | no     | no   |       |
+            | motorway |        |      |       |
+            | motorway |        | yes  | x     |
+            | motorway |        | no   |       |
+            | motorway | yes    |      | x     |
+            | motorway | yes    | yes  | x     |
+            | motorway | yes    | no   |       |
+            | motorway | no     |      |       |
+            | motorway | no     | yes  | x     |
+            | motorway | no     | no   |       |
+
+
+    Scenario: Foot - Overwriting implied acccess on ways
+        Then routability should be
+            | highway  | access | foot | bothw |
+            | footway  |        |      | x     |
+            | motorway |        |      |       |
+            | footway  | no     |      |       |
+            | footway  |        |      | x     |
+            | footway  |        | no   |       |
+            | motorway | yes    |      | x     |
+            | motorway |        |      |       |
+            | motorway |        | yes  | x     |
+
+    Scenario: Foot - Access tags on ways
+        Then routability should be
+            | access       | foot         | bothw |
+            |              |              | x     |
+            | yes          |              | x     |
+            | permissive   |              | x     |
+            | designated   |              | x     |
+            | some_tag     |              | x     |
+            | no           |              |       |
+            | private      |              |       |
+            | agricultural |              |       |
+            | forestery    |              |       |
+            |              | yes          | x     |
+            |              | permissive   | x     |
+            |              | designated   | x     |
+            |              | some_tag     | x     |
+            |              | no           |       |
+            |              | private      |       |
+            |              | agricultural |       |
+            |              | forestery    |       |
+
+    Scenario: Foot - Access tags on both node and way
+        Then routability should be
+            | access   | node/access | bothw |
+            | yes      | yes         | x     |
+            | yes      | no          |       |
+            | yes      | some_tag    | x     |
+            | no       | yes         |       |
+            | no       | no          |       |
+            | no       | some_tag    |       |
+            | some_tag | yes         | x     |
+            | some_tag | no          |       |
+            | some_tag | some_tag    | x     |
+
+    Scenario: Foot - Access combinations
+        Then routability should be
+            | highway     | access     | foot       | bothw |
+            | motorway    | private    | yes        | x     |
+            | footway     |            | permissive | x     |
+            | track       | forestry   | permissive | x     |
+            | footway     | yes        | no         |       |
+            | primary     |            | private    |       |
+            | residential | permissive | no         |       |
+
+    Scenario: Foot - Ignore access tags for other modes
+        Then routability should be
+            | highway  | boat | motor_vehicle | moped | bothw |
+            | river    | yes  |               |       |       |
+            | footway  | no   |               |       | x     |
+            | motorway |      | yes           |       |       |
+            | footway  |      | no            |       | x     |
+            | motorway |      |               | yes   |       |
+            | footway  |      |               | no    | x     |
diff --git a/features/foot/access_node.feature b/features/foot/access_node.feature
new file mode 100644
index 0000000..5a4a131
--- /dev/null
+++ b/features/foot/access_node.feature
@@ -0,0 +1,50 @@
+ at routing @foot @access
+Feature: Foot - Access tags on nodes
+# Reference: http://wiki.openstreetmap.org/wiki/Key:access
+
+    Background:
+        Given the profile "foot"
+
+    Scenario: Foot - Access tag hierachy on nodes
+        Then routability should be
+            | node/access | node/foot | bothw |
+            |             |           | x     |
+            |             | yes       | x     |
+            |             | no        |       |
+            | yes         |           | x     |
+            | yes         | yes       | x     |
+            | yes         | no        |       |
+            | no          |           |       |
+            | no          | yes       | x     |
+            | no          | no        |       |
+
+    Scenario: Foot - Overwriting implied acccess on nodes doesn't overwrite way
+        Then routability should be
+            | highway  | node/access | node/foot | bothw |
+            | footway  |             |           | x     |
+            | footway  | no          |           |       |
+            | footway  |             | no        |       |
+            | motorway |             |           |       |
+            | motorway | yes         |           |       |
+            | motorway |             | yes       |       |
+
+    Scenario: Foot - Access tags on nodes
+        Then routability should be
+            | node/access  | node/foot    | bothw |
+            |              |              | x     |
+            | yes          |              | x     |
+            | permissive   |              | x     |
+            | designated   |              | x     |
+            | some_tag     |              | x     |
+            | no           |              |       |
+            | private      |              |       |
+            | agricultural |              |       |
+            | forestery    |              |       |
+            | no           | yes          | x     |
+            | no           | permissive   | x     |
+            | no           | designated   | x     |
+            | no           | some_tag     | x     |
+            | yes          | no           |       |
+            | yes          | private      |       |
+            | yes          | agricultural |       |
+            | yes          | forestery    |       |
diff --git a/features/foot/area.feature b/features/foot/area.feature
new file mode 100644
index 0000000..6edd585
--- /dev/null
+++ b/features/foot/area.feature
@@ -0,0 +1,103 @@
+ at routing @foot @area
+Feature: Foot - Squares and other areas
+
+    Background:
+        Given the profile "foot"
+
+    @square
+    Scenario: Foot - Route along edge of a squares
+        Given the node map
+            | x |   |
+            | a | b |
+            | d | c |
+
+        And the ways
+            | nodes | area | highway     |
+            | xa    |      | primary     |
+            | abcda | yes  | residential |
+
+        When I route I should get
+            | from | to | route |
+            | a    | b  | abcda |
+            | a    | d  | abcda |
+            | b    | c  | abcda |
+            | c    | b  | abcda |
+            | c    | d  | abcda |
+            | d    | c  | abcda |
+            | d    | a  | abcda |
+            | a    | d  | abcda |
+
+    @building
+    Scenario: Foot - Don't route on buildings
+        Given the node map
+            | x |   |
+            | a | b |
+            | d | c |
+
+        And the ways
+            | nodes | highway | area | building | access |
+            | xa    | primary |      |          |        |
+            | abcda | (nil)   | yes  | yes      | yes    |
+
+        When I route I should get
+            | from | to | route |
+            | a    | b  | xa    |
+            | a    | d  | xa    |
+            | b    | c  | xa    |
+            | c    | b  | xa    |
+            | c    | d  | xa    |
+            | d    | c  | xa    |
+            | d    | a  | xa    |
+            | a    | d  | xa    |
+
+    @parking
+    Scenario: Foot - parking areas
+        Given the node map
+            | e |   |   | f |
+            | x | a | b | y |
+            |   | d | c |   |
+
+        And the ways
+            | nodes | highway | amenity |
+            | xa    | primary |         |
+            | by    | primary |         |
+            | xefy  | primary |         |
+            | abcda | (nil)   | parking |
+
+        When I route I should get
+            | from | to | route       |
+            | x    | y  | xa,abcda,by |
+            | y    | x  | by,abcda,xa |
+            | a    | b  | abcda       |
+            | a    | d  | abcda       |
+            | b    | c  | abcda       |
+            | c    | b  | abcda       |
+            | c    | d  | abcda       |
+            | d    | c  | abcda       |
+            | d    | a  | abcda       |
+            | a    | d  | abcda       |
+
+    @train @platform
+    Scenario: Foot - railway platforms
+        Given the node map
+            | x | a | b | y |
+            |   | d | c |   |
+
+        And the ways
+            | nodes | highway | railway  |
+            | xa    | primary |          |
+            | by    | primary |          |
+            | abcda | (nil)   | platform |
+
+        When I route I should get
+            | from | to | route       |
+            | x    | y  | xa,abcda,by |
+            | y    | x  | by,abcda,xa |
+            | a    | b  | abcda       |
+            | a    | d  | abcda       |
+            | b    | c  | abcda       |
+            | c    | b  | abcda       |
+            | c    | d  | abcda       |
+            | d    | c  | abcda       |
+            | d    | a  | abcda       |
+            | a    | d  | abcda       |
diff --git a/features/foot/barrier.feature b/features/foot/barrier.feature
new file mode 100644
index 0000000..18fa4de
--- /dev/null
+++ b/features/foot/barrier.feature
@@ -0,0 +1,39 @@
+ at routing @foot @barrier
+Feature: Barriers
+
+    Background:
+        Given the profile "foot"
+
+    Scenario: Foot - Barriers
+        Then routability should be
+            | node/barrier   | bothw |
+            |                | x     |
+            | bollard        | x     |
+            | gate           | x     |
+            | cycle_barrier  | x     |
+            | cattle_grid    | x     |
+            | border_control | x     |
+            | toll_booth     | x     |
+            | sally_port     | x     |
+            | entrance       | x     |
+            | wall           |       |
+            | fence          |       |
+            | some_tag       |       |
+
+    Scenario: Foot - Access tag trumphs barriers
+        Then routability should be
+            | node/barrier | node/access  | bothw |
+            | bollard      |              | x     |
+            | bollard      | yes          | x     |
+            | bollard      | permissive   | x     |
+            | bollard      | designated   | x     |
+            | bollard      | no           |       |
+            | bollard      | private      |       |
+            | bollard      | agricultural |       |
+            | wall         |              |       |
+            | wall         | yes          | x     |
+            | wall         | permissive   | x     |
+            | wall         | designated   | x     |
+            | gate         | no           |       |
+            | gate         | private      |       |
+            | gate         | agricultural |       |
diff --git a/features/foot/ferry.feature b/features/foot/ferry.feature
new file mode 100644
index 0000000..4308756
--- /dev/null
+++ b/features/foot/ferry.feature
@@ -0,0 +1,63 @@
+ at routing @foot @ferry
+Feature: Foot - Handle ferry routes
+
+    Background:
+        Given the profile "foot"
+
+    Scenario: Foot - Ferry route
+        Given the node map
+            | a | b | c |   |   |
+            |   |   | d |   |   |
+            |   |   | e | f | g |
+
+        And the ways
+            | nodes | highway | route | foot |
+            | abc   | primary |       |      |
+            | cde   |         | ferry | yes  |
+            | efg   | primary |       |      |
+
+        When I route I should get
+            | from | to | route       |
+            | a    | g  | abc,cde,efg |
+            | b    | f  | abc,cde,efg |
+            | e    | c  | cde         |
+            | e    | b  | cde,abc     |
+            | e    | a  | cde,abc     |
+            | c    | e  | cde         |
+            | c    | f  | cde,efg     |
+            | c    | g  | cde,efg     |
+
+    Scenario: Foot - Ferry duration, single node
+        Given the node map
+            | a | b | c | d |
+            |   |   | e | f |
+            |   |   | g | h |
+            |   |   | i | j |
+
+        And the ways
+            | nodes | highway | route | foot | duration |
+            | ab    | primary |       |      |          |
+            | cd    | primary |       |      |          |
+            | ef    | primary |       |      |          |
+            | gh    | primary |       |      |          |
+            | ij    | primary |       |      |          |
+            | bc    |         | ferry | yes  | 0:01     |
+            | be    |         | ferry | yes  | 0:10     |
+            | bg    |         | ferry | yes  | 1:00     |
+            | bi    |         | ferry | yes  | 10:00    |
+
+    Scenario: Foot - Ferry duration, multiple nodes
+        Given the node map
+            | x |   |   |   |   | y |
+            |   | a | b | c | d |   |
+
+        And the ways
+            | nodes | highway | route | foot | duration |
+            | xa    | primary |       |      |          |
+            | yd    | primary |       |      |          |
+            | abcd  |         | ferry | yes  | 1:00     |
+
+        When I route I should get
+            | from | to | route | time       |
+            | a    | d  | abcd  | 3600s +-10 |
+            | d    | a  | abcd  | 3600s +-10 |
diff --git a/features/foot/maxspeed.feature b/features/foot/maxspeed.feature
index 8a3571a..d4e3583 100644
--- a/features/foot/maxspeed.feature
+++ b/features/foot/maxspeed.feature
@@ -1,20 +1,19 @@
- at routing @maxspeed @foot
+ at routing @foot @maxspeed
 Feature: Foot - Ignore max speed restrictions
 
 Background: Use specific speeds
-	Given the profile "foot"
+    Given the profile "foot"
 
- at todo
-Scenario: Foot - Ignore maxspeed
-	Then routability should be
-	 | highway     | maxspeed  | bothw     |
-	 | residential |           | 145s ~10% |
-	 | residential | 1         | 145s ~10% |
-	 | residential | 100       | 145s ~10% |
-	 | residential | 1         | 145s ~10% |
-	 | residential | 1mph      | 145s ~10% |
-	 | residential | 1 mph     | 145s ~10% |
-	 | residential | 1unknown  | 145s ~10% |
-	 | residential | 1 unknown | 145s ~10% |
-	 | residential | none      | 145s ~10% |
-	 | residential | signals   | 145s ~10% |
+    Scenario: Foot - Ignore maxspeed
+        Then routability should be
+            | highway     | maxspeed  | bothw     |
+            | residential |           | 145s ~10% |
+            | residential | 1         | 145s ~10% |
+            | residential | 100       | 145s ~10% |
+            | residential | 1         | 145s ~10% |
+            | residential | 1mph      | 145s ~10% |
+            | residential | 1 mph     | 145s ~10% |
+            | residential | 1unknown  | 145s ~10% |
+            | residential | 1 unknown | 145s ~10% |
+            | residential | none      | 145s ~10% |
+            | residential | signals   | 145s ~10% |
diff --git a/features/foot/names.feature b/features/foot/names.feature
new file mode 100644
index 0000000..d5fdcc7
--- /dev/null
+++ b/features/foot/names.feature
@@ -0,0 +1,33 @@
+ at routing @foot @names
+Feature: Foot - Street names in instructions
+
+    Background:
+        Given the profile "foot"
+
+    Scenario: Foot - A named street
+        Given the node map
+            | a | b |
+            |   | c |
+
+        And the ways
+            | nodes | name     |
+            | ab    | My Way   |
+            | bc    | Your Way |
+
+        When I route I should get
+            | from | to | route           |
+            | a    | c  | My Way,Your Way |
+
+    @unnamed
+    Scenario: Foot - Use way type to describe unnamed ways
+        Given the node map
+            | a | b | c | d |
+
+        And the ways
+            | nodes | highway | name |
+            | ab    | footway |      |
+            | bcd   | track   |      |
+
+        When I route I should get
+            | from | to | route                             |
+            | a    | d  | {highway:footway},{highway:track} |
diff --git a/features/foot/oneway.feature b/features/foot/oneway.feature
index e1c96e3..77562e5 100644
--- a/features/foot/oneway.feature
+++ b/features/foot/oneway.feature
@@ -1,60 +1,60 @@
 @routing @foot @oneway
 Feature: Foot - Oneway streets
-Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing
+# Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing
 
-	Background:
-		Given the profile "foot"
-	
-	Scenario: Foot - Walking should not be affected by oneways
-	 	Then routability should be
-		 | oneway   | bothw |
-		 |          | x     |
-		 | nonsense | x     |
-		 | no       | x     |
-		 | false    | x     |
-		 | 0        | x     |
-		 | yes      | x     |
-		 | true     | x     |
-		 | 1        | x     |
-		 | -1       | x     |
+    Background:
+        Given the profile "foot"
 
-	Scenario: Foot - Walking and roundabouts
-	 	Then routability should be
-		 | junction   | bothw |
-		 | roundarout | x     |
+    Scenario: Foot - Walking should not be affected by oneways
+        Then routability should be
+            | oneway   | bothw |
+            |          | x     |
+            | nonsense | x     |
+            | no       | x     |
+            | false    | x     |
+            | 0        | x     |
+            | yes      | x     |
+            | true     | x     |
+            | 1        | x     |
+            | -1       | x     |
 
-	Scenario: Foot - Oneway:foot tag should not cause walking on big roads
-	 	Then routability should be
-		 | highway       | oneway:foot | bothw |
-		 | footway       |             | x     |
-		 | motorway      | yes         |       |
-		 | motorway_link | yes         |       |
-		 | trunk         | yes         |       |
-		 | trunk_link    | yes         |       |
-		 | motorway      | no          |       |
-		 | motorway_link | no          |       |
-		 | trunk         | no          |       |
-		 | trunk_link    | no          |       |
-		 | motorway      | -1          |       |
-		 | motorway_link | -1          |       |
-		 | trunk         | -1          |       |
-		 | trunk_link    | -1          |       |
-                                               
-	Scenario: Foot - Walking should respect oneway:foot
-	 	Then routability should be
-		 | oneway:foot | oneway | junction   | forw | backw |
-		 | yes         |        |            | x    |       |
-		 | yes         | yes    |            | x    |       |
-		 | yes         | no     |            | x    |       |
-		 | yes         | -1     |            | x    |       |
-		 | yes         |        | roundabout | x    |       |
-		 | no          |        |            | x    | x     |
-		 | no          | yes    |            | x    | x     |
-		 | no          | no     |            | x    | x     |
-		 | no          | -1     |            | x    | x     |
-		 | no          |        | roundabout | x    | x     |
-		 | -1          |        |            |      | x     |
-		 | -1          | yes    |            |      | x     |
-		 | -1          | no     |            |      | x     |
-		 | -1          | -1     |            |      | x     |
-		 | -1          |        | roundabout |      | x     |
\ No newline at end of file
+    Scenario: Foot - Walking and roundabouts
+        Then routability should be
+            | junction   | bothw |
+            | roundarout | x     |
+
+    Scenario: Foot - Oneway:foot tag should not cause walking on big roads
+        Then routability should be
+            | highway       | oneway:foot | bothw |
+            | footway       |             | x     |
+            | motorway      | yes         |       |
+            | motorway_link | yes         |       |
+            | trunk         | yes         |       |
+            | trunk_link    | yes         |       |
+            | motorway      | no          |       |
+            | motorway_link | no          |       |
+            | trunk         | no          |       |
+            | trunk_link    | no          |       |
+            | motorway      | -1          |       |
+            | motorway_link | -1          |       |
+            | trunk         | -1          |       |
+            | trunk_link    | -1          |       |
+
+    Scenario: Foot - Walking should respect oneway:foot
+        Then routability should be
+            | oneway:foot | oneway | junction   | forw | backw |
+            | yes         |        |            | x    |       |
+            | yes         | yes    |            | x    |       |
+            | yes         | no     |            | x    |       |
+            | yes         | -1     |            | x    |       |
+            | yes         |        | roundabout | x    |       |
+            | no          |        |            | x    | x     |
+            | no          | yes    |            | x    | x     |
+            | no          | no     |            | x    | x     |
+            | no          | -1     |            | x    | x     |
+            | no          |        | roundabout | x    | x     |
+            | -1          |        |            |      | x     |
+            | -1          | yes    |            |      | x     |
+            | -1          | no     |            |      | x     |
+            | -1          | -1     |            |      | x     |
+            | -1          |        | roundabout |      | x     |
diff --git a/features/foot/ref.feature b/features/foot/ref.feature
new file mode 100644
index 0000000..bc0c77e
--- /dev/null
+++ b/features/foot/ref.feature
@@ -0,0 +1,41 @@
+ at routing @foot @ref @name
+Feature: Foot - Way ref
+
+    Background:
+        Given the profile "foot"
+
+    Scenario: Foot - Way with both name and ref
+        Given the node map
+            | a | b |
+
+        And the ways
+            | nodes | name         | ref |
+            | ab    | Utopia Drive | E7  |
+
+        When I route I should get
+            | from | to | route             |
+            | a    | b  | Utopia Drive / E7 |
+
+    Scenario: Foot - Way with only ref
+        Given the node map
+            | a | b |
+
+        And the ways
+            | nodes | name | ref |
+            | ab    |      | E7  |
+
+        When I route I should get
+            | from | to | route |
+            | a    | b  | E7    |
+
+    Scenario: Foot - Way with only name
+        Given the node map
+            | a | b |
+
+        And the ways
+            | nodes | name         |
+            | ab    | Utopia Drive |
+
+        When I route I should get
+            | from | to | route        |
+            | a    | b  | Utopia Drive |
diff --git a/features/foot/restrictions.feature b/features/foot/restrictions.feature
new file mode 100644
index 0000000..8d6a029
--- /dev/null
+++ b/features/foot/restrictions.feature
@@ -0,0 +1,288 @@
+ at routing @foot @restrictions
+Feature: Foot - Turn restrictions
+# Ignore turn restrictions on foot.
+
+    Background:
+        Given the profile "foot"
+
+    @no_turning
+    Scenario: Foot - No left turn
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | nj    | -1     |
+            | wj    | -1     |
+            | ej    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction  |
+            | restriction | sj       | wj     | j        | no_left_turn |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @no_turning
+    Scenario: Foot - No right turn
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | nj    | -1     |
+            | wj    | -1     |
+            | ej    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction   |
+            | restriction | sj       | ej     | j        | no_right_turn |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @no_turning
+    Scenario: Foot - No u-turn
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | nj    | -1     |
+            | wj    | -1     |
+            | ej    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction |
+            | restriction | sj       | wj     | j        | no_u_turn   |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @no_turning
+    Scenario: Foot - Handle any no_* relation
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | nj    | -1     |
+            | wj    | -1     |
+            | ej    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction      |
+            | restriction | sj       | wj     | j        | no_weird_zigzags |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @only_turning
+    Scenario: Foot - Only left turn
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | nj    | -1     |
+            | wj    | -1     |
+            | ej    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction    |
+            | restriction | sj       | wj     | j        | only_left_turn |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @only_turning
+    Scenario: Foot - Only right turn
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | nj    | -1     |
+            | wj    | -1     |
+            | ej    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction     |
+            | restriction | sj       | ej     | j        | only_right_turn |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @only_turning
+    Scenario: Foot - Only straight on
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | nj    | -1     |
+            | wj    | -1     |
+            | ej    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction      |
+            | restriction | sj       | nj     | j        | only_straight_on |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @no_turning
+    Scenario: Foot - Handle any only_* restriction
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | nj    | -1     |
+            | wj    | -1     |
+            | ej    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction        |
+            | restriction | sj       | nj     | j        | only_weird_zigzags |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  | sj,wj |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+    @except
+    Scenario: Foot - Except tag and on no_ restrictions
+        Given the node map
+            | b | x | c |
+            | a | j | d |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | no     |
+            | xj    | -1     |
+            | aj    | -1     |
+            | bj    | no     |
+            | cj    | -1     |
+            | dj    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction   | except |
+            | restriction | sj       | aj     | j        | no_left_turn  | foot   |
+            | restriction | sj       | bj     | j        | no_left_turn  |        |
+            | restriction | sj       | cj     | j        | no_right_turn |        |
+            | restriction | sj       | dj     | j        | no_right_turn | foot   |
+
+        When I route I should get
+            | from | to | route |
+            | s    | a  | sj,aj |
+            | s    | b  | sj,bj |
+            | s    | c  | sj,cj |
+            | s    | d  | sj,dj |
+
+    @except
+    Scenario: Foot - Except tag and on only_ restrictions
+        Given the node map
+            | a |   | b |
+            |   | j |   |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | aj    | no     |
+            | bj    | no     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction      | except |
+            | restriction | sj       | aj     | j        | only_straight_on | foot   |
+
+        When I route I should get
+            | from | to | route |
+            | s    | a  | sj,aj |
+            | s    | b  | sj,bj |
+
+    @except
+    Scenario: Foot - Multiple except tag values
+        Given the node map
+            | s | j | a |
+            |   |   | b |
+            |   |   | c |
+            |   |   | d |
+            |   |   | e |
+            |   |   | f |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | ja    | yes    |
+            | jb    | yes    |
+            | jc    | yes    |
+            | jd    | yes    |
+            | je    | yes    |
+            | jf    | yes    |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction    | except        |
+            | restriction | sj       | ja     | j        | no_straight_on |               |
+            | restriction | sj       | jb     | j        | no_straight_on | foot          |
+            | restriction | sj       | jc     | j        | no_straight_on | bus; foot     |
+            | restriction | sj       | jd     | j        | no_straight_on | foot; motocar |
+            | restriction | sj       | je     | j        | no_straight_on | bus, foot     |
+            | restriction | sj       | jf     | j        | no_straight_on | foot, bus     |
+
+        When I route I should get
+            | from | to | route |
+            | s    | a  | sj,ja |
+            | s    | b  | sj,jb |
+            | s    | c  | sj,jc |
+            | s    | d  | sj,jd |
+            | s    | e  | sj,je |
+            | s    | f  | sj,jf |
diff --git a/features/foot/roundabout.feature b/features/foot/roundabout.feature
new file mode 100644
index 0000000..5aa9860
--- /dev/null
+++ b/features/foot/roundabout.feature
@@ -0,0 +1,34 @@
+ at routing @foot @roundabout @instruction
+Feature: Roundabout Instructions
+
+    Background:
+        Given the profile "foot"
+    
+    @todo
+    Scenario: Foot - Roundabout instructions
+    # You can walk in both directions on a roundabout, bu the normal roundabout instructions don't
+    # make sense when you're going the opposite way around the roundabout.
+    
+        Given the node map
+            |   |   | v |   |   |
+            |   |   | d |   |   |
+            | s | a |   | c | u |
+            |   |   | b |   |   |
+            |   |   | t |   |   |
+
+        And the ways
+            | nodes | junction   |
+            | sa    |            |
+            | tb    |            |
+            | uc    |            |
+            | vd    |            |
+            | abcda | roundabout |
+
+        When I route I should get
+            | from | to | route | turns                               |
+            | s    | t  | sa,tb | head,enter_roundabout-1,destination |
+            | s    | u  | sa,uc | head,enter_roundabout-2,destination |
+            | s    | v  | sa,vd | head,enter_roundabout-3,destination |
+            | u    | v  | uc,vd | head,enter_roundabout-1,destination |
+            | u    | s  | uc,sa | head,enter_roundabout-2,destination |
+            | u    | t  | uc,tb | head,enter_roundabout-3,destination |
diff --git a/features/foot/surface.feature b/features/foot/surface.feature
new file mode 100644
index 0000000..556c3d8
--- /dev/null
+++ b/features/foot/surface.feature
@@ -0,0 +1,15 @@
+ at routing @foot @surface
+Feature: Foot - Surfaces
+
+    Background:
+        Given the profile "foot"
+
+    Scenario: Foot - Slow surfaces
+        Then routability should be
+            | highway | surface     | bothw     |
+            | footway |             | 145s ~10% |
+            | footway | fine_gravel | 193s ~10% |
+            | footway | gravel      | 193s ~10% |
+            | footway | pebbelstone | 193s ~10% |
+            | footway | mud         | 289s ~10% |
+            | footway | sand        | 289s ~10% |
diff --git a/features/foot/way.feature b/features/foot/way.feature
index e18d9f8..653c773 100644
--- a/features/foot/way.feature
+++ b/features/foot/way.feature
@@ -1,32 +1,32 @@
 @routing @foot @way
 Feature: Foot - Accessability of different way types
 
-	Background:
-		Given the profile "foot"
+    Background:
+        Given the profile "foot"
 
-	Scenario: Foot - Basic access
-	 	Then routability should be
-		 | highway        | forw |
-		 | motorway       |      |
-		 | motorway_link  |      |
-		 | trunk          |      |
-		 | trunk_link     |      |
-		 | primary        | x    |
-		 | primary_link   | x    |
-		 | secondary      | x    |
-		 | secondary_link | x    |
-		 | tertiary       | x    |
-		 | tertiary_link  | x    |
-		 | residential    | x    |
-		 | service        | x    |
-		 | unclassified   | x    |
-		 | living_street  | x    |
-		 | road           | x    |
-		 | track          | x    |
-		 | path           | x    |
-		 | footway        | x    |
-		 | pedestrian     | x    |
-		 | steps          | x    |
-		 | pier           | x    |
-		 | cycleway       |      |
-		 | bridleway      |      |
\ No newline at end of file
+    Scenario: Foot - Basic access
+        Then routability should be
+            | highway        | forw |
+            | motorway       |      |
+            | motorway_link  |      |
+            | trunk          |      |
+            | trunk_link     |      |
+            | primary        | x    |
+            | primary_link   | x    |
+            | secondary      | x    |
+            | secondary_link | x    |
+            | tertiary       | x    |
+            | tertiary_link  | x    |
+            | residential    | x    |
+            | service        | x    |
+            | unclassified   | x    |
+            | living_street  | x    |
+            | road           | x    |
+            | track          | x    |
+            | path           | x    |
+            | footway        | x    |
+            | pedestrian     | x    |
+            | steps          | x    |
+            | pier           | x    |
+            | cycleway       |      |
+            | bridleway      |      |
diff --git a/features/investigate/weird.feature b/features/investigate/weird.feature
deleted file mode 100644
index f84a075..0000000
--- a/features/investigate/weird.feature
+++ /dev/null
@@ -1,42 +0,0 @@
- at routing @weird
-Feature: Weird routings discovered
-	
-	Background:
-		Given the profile "testbot"
-	
-	Scenario: Routing on a oneway roundabout
-		Given the node map
-		 |   | d | c |   |
-		 | e |   |   | b |
-		 | f |   |   | a |
-		 |   | g | h |   |
-
-		And the ways
-		 | nodes | oneway |
-		 | ab    | yes    |
-		 | bc    | yes    |
-		 | cd    | yes    |
-		 | de    | yes    |
-		 | ef    | yes    |
-		 | fg    | yes    |
-		 | gh    | yes    |
-		 | ha    | yes    |
-
-		When I route I should get
-		 | from | to | route                |
-		 | a    | b  | ab                   |
-		 | b    | c  | bc                   |
-		 | c    | d  | cd                   |
-		 | d    | e  | de                   |
-		 | e    | f  | ef                   |
-		 | f    | g  | fg                   |
-		 | g    | h  | gh                   |
-		 | h    | a  | ha                   |
-		 | b    | a  | bc,cd,de,ef,fg,gh,ha |
-		 | c    | b  | cd,de,ef,fg,gh,ha,ab |
-		 | d    | c  | de,ef,fg,gh,ha,ab,bc |
-		 | e    | d  | ef,fg,gh,ha,ab,bc,cd |
-		 | f    | e  | fg,gh,ha,ab,bc,cd,de |
-		 | g    | f  | gh,ha,ab,bc,cd,de,ef |
-		 | h    | g  | ha,ab,bc,cd,de,ef,fg |
-		 | a    | h  | ab,bc,cd,de,ef,fg,gh |
\ No newline at end of file
diff --git a/features/locate/locate.feature b/features/locate/locate.feature
new file mode 100644
index 0000000..838bcd5
--- /dev/null
+++ b/features/locate/locate.feature
@@ -0,0 +1,197 @@
+ at locate
+Feature: Locate - return nearest node
+
+    Background:
+        Given the profile "testbot"
+
+    Scenario: Locate - two ways crossing
+        Given the node map
+            |   |  | 0 | c | 1 |  |   |
+            |   |  |   |   |   |  |   |
+            | 7 |  |   | n |   |  | 2 |
+            | a |  | k | x | m |  | b |
+            | 6 |  |   | l |   |  | 3 |
+            |   |  |   |   |   |  |   |
+            |   |  | 5 | d | 4 |  |   |
+
+        And the ways
+            | nodes |
+            | axb   |
+            | cxd   |
+
+        When I request locate I should get
+            | in | out |
+            | 0  | c   |
+            | 1  | c   |
+            | 2  | b   |
+            | 3  | b   |
+            | 4  | d   |
+            | 5  | d   |
+            | 6  | a   |
+            | 7  | a   |
+            | a  | a   |
+            | b  | b   |
+            | c  | c   |
+            | d  | d   |
+            | k  | x   |
+            | l  | x   |
+            | m  | x   |
+            | n  | x   |
+
+    Scenario: Locate - inside a triangle
+        Given the node map
+            |   |  |   |   |   | c |   |   |   |  |   |
+            |   |  |   |   |   | 7 |   |   |   |  |   |
+            |   |  |   | y |   |   |   | z |   |  |   |
+            |   |  | 5 |   | 0 |   | 1 |   | 8 |  |   |
+            | 6 |  |   | 2 |   | 3 |   | 4 |   |  | 9 |
+            | a |  |   | x |   | u |   | w |   |  | b |
+
+        And the ways
+            | nodes |
+            | ab    |
+            | bc    |
+            | ca    |
+
+        When I request locate I should get
+            | in | out |
+            | 0  | c   |
+            | 1  | c   |
+            | 2  | a   |
+            | 3  | c   |
+            | 4  | b   |
+            | 5  | a   |
+            | 6  | a   |
+            | 7  | c   |
+            | 8  | b   |
+            | 9  | b   |
+            | x  | a   |
+            | y  | c   |
+            | z  | c   |
+            | w  | b   |
+
+    Scenario: Nearest - easy-west way
+        Given the node map
+            | 3 | 4 |   | 5 | 6 |
+            | 2 | a | x | b | 7 |
+            | 1 | 0 |   | 9 | 8 |
+
+        And the ways
+            | nodes |
+            | ab    |
+
+        When I request locate I should get
+            | in | out |
+            | 0  | a   |
+            | 1  | a   |
+            | 2  | a   |
+            | 3  | a   |
+            | 4  | a   |
+            | 5  | b   |
+            | 6  | b   |
+            | 7  | b   |
+            | 8  | b   |
+            | 9  | b   |
+
+    Scenario: Nearest - north-south way
+        Given the node map
+            | 1 | 2 | 3 |
+            | 0 | a | 4 |
+            |   | x |   |
+            | 9 | b | 5 |
+            | 8 | 7 | 6 |
+
+        And the ways
+            | nodes |
+            | ab    |
+
+        When I request locate I should get
+            | in | out |
+            | 0  | a   |
+            | 1  | a   |
+            | 2  | a   |
+            | 3  | a   |
+            | 4  | a   |
+            | 5  | b   |
+            | 6  | b   |
+            | 7  | b   |
+            | 8  | b   |
+            | 9  | b   |
+
+    Scenario: Nearest - diagonal 1
+        Given the node map
+            | 2 |   | 3 |   |   |   |
+            |   | a |   | 4 |   |   |
+            | 1 |   | x |   | 5 |   |
+            |   | 0 |   | y |   | 6 |
+            |   |   | 9 |   | b |   |
+            |   |   |   | 8 |   | 7 |
+
+        And the ways
+            | nodes |
+            | axyb  |
+
+        When I request locate I should get
+            | in | out |
+            | 0  | x   |
+            | 1  | a   |
+            | 2  | a   |
+            | 3  | a   |
+            | 4  | x   |
+            | 5  | y   |
+            | 6  | b   |
+            | 7  | b   |
+            | 8  | b   |
+            | 9  | y   |
+            | a  | a   |
+            | b  | b   |
+            | x  | x   |
+            | y  | y   |
+
+    Scenario: Nearest - diagonal 2
+        Given the node map
+            |   |   |   | 6 |   | 7 |
+            |   |   | 5 |   | b |   |
+            |   | 4 |   | y |   | 8 |
+            | 3 |   | x |   | 9 |   |
+            |   | a |   | 0 |   |   |
+            | 2 |   | 1 |   |   |   |
+
+        And the ways
+        | nodes |
+        | ab    |
+
+        When I request nearest I should get
+            | in | out |
+            | 0  | x   |
+            | 1  | a   |
+            | 2  | a   |
+            | 3  | a   |
+            | 4  | x   |
+            | 5  | y   |
+            | 6  | b   |
+            | 7  | b   |
+            | 8  | b   |
+            | 9  | y   |
+            | a  | a   |
+            | b  | b   |
+            | x  | x   |
+            | y  | y   |
+
+        Scenario: Locate - High lat/lon
+           Given the node locations
+            | node | lat | lon  |
+            | a    | -85 | -180 |
+            | b    | 0   | 0    |
+            | c    | 85  | 180  |
+            | x    | -84 | -180 |
+            | y    | 84  | 180  |
+
+           And the ways
+            | nodes |
+            | abc   |
+
+           When I request locate I should get
+            | in | out |
+            | x  | a   |
+            | y  | c   |
diff --git a/features/nearest/pick.feature b/features/nearest/pick.feature
index f3bd76d..08e6652 100644
--- a/features/nearest/pick.feature
+++ b/features/nearest/pick.feature
@@ -1,56 +1,78 @@
 @nearest
 Feature: Locating Nearest node on a Way - pick closest way
 
-	Background:
-		Given the profile "testbot"
-	
-	Scenario: Nearest - two ways crossing
-		Given the node map
-		 |   | 0 | c | 1 |   |
-		 | 7 |   | n |   | 2 |
-		 | a | k | x | m | b |
-		 | 6 |   | l |   | 3 |
-		 |   | 5 | d | 4 |   |
-
-		And the ways
-		 | nodes |
-		 | axb   |
-		 | cxd   |
-
-		When I request nearest I should get
-		 | in | out |
-		 | 0  | c   |
-		 | 1  | c   |
-		 | 2  | b   |
-		 | 3  | b   |
-		 | 4  | d   |
-		 | 5  | d   |
-		 | 6  | a   |
-		 | 7  | a   |
-		 | k  | k   |
-		 | l  | l   |
-		 | m  | m   |
-		 | n  | n   |
-
- 	Scenario: Nearest - inside a triangle
- 		Given the node map
-		 |   |  |  |   |   | c |   |   |  |  |   |
-		 |   |  |  |   |   |   |   |   |  |  |   |
-		 |   |  |  | y |   |   |   | z |  |  |   |
-		 |   |  |  |   | 0 |   | 1 |   |  |  |   |
-		 |   |  |  | 2 |   | 3 |   | 4 |  |  |   |
-		 | a |  |  | x |   | u |   | w |  |  | b |
-
- 		And the ways
- 		 | nodes |
- 		 | ab    |
- 		 | bc    |
- 		 | ca    |
-
- 		When I request nearest I should get
- 		 | in | out |
- 		 | 0  | y   |
- 		 | 1  | z   |
- 		 | 2  | x   |
- 		 | 3  | u   |
- 		 | 4  | w   |
\ No newline at end of file
+    Background:
+        Given the profile "testbot"
+
+    Scenario: Nearest - two ways crossing
+        Given the node map
+            |   | 0 | c | 1 |   |
+            | 7 |   | n |   | 2 |
+            | a | k | x | m | b |
+            | 6 |   | l |   | 3 |
+            |   | 5 | d | 4 |   |
+
+        And the ways
+            | nodes |
+            | axb   |
+            | cxd   |
+
+        When I request nearest I should get
+            | in | out |
+            | 0  | c   |
+            | 1  | c   |
+            | 2  | b   |
+            | 3  | b   |
+            | 4  | d   |
+            | 5  | d   |
+            | 6  | a   |
+            | 7  | a   |
+            | k  | k   |
+            | l  | l   |
+            | m  | m   |
+            | n  | n   |
+
+    Scenario: Nearest - inside a triangle
+        Given the node map
+            |   |  |  |   |   | c |   |   |  |  |   |
+            |   |  |  |   |   |   |   |   |  |  |   |
+            |   |  |  | y |   |   |   | z |  |  |   |
+            |   |  |  |   | 0 |   | 1 |   |  |  |   |
+            |   |  |  | 2 |   | 3 |   | 4 |  |  |   |
+            | a |  |  | x |   | u |   | w |  |  | b |
+
+        And the ways
+            | nodes |
+            | ab    |
+            | bc    |
+            | ca    |
+
+        When I request nearest I should get
+            | in | out |
+            | 0  | y   |
+            | 1  | z   |
+            | 2  | x   |
+            | 3  | u   |
+            | 4  | w   |
+
+    Scenario: Nearest - High lat/lon
+        Given the node locations
+            | node | lat | lon  |
+            | a    | -85 | -180 |
+            | b    | -85 | -160 |
+            | c    | -85 | -140 |
+            | x    |  75 | -180 |
+            | y    |  75 | -180 |
+            | v    |   1 |    1 |
+            | w    |  -1 |   -1 |
+
+        And the ways
+            | nodes |
+            | abc   |
+
+        When I request nearest I should get
+            | in | out |
+            | x  | a   |
+            | y  | a   |
+            | v  | c   |
+            | w  | c   |
diff --git a/features/nearest/projection.feature b/features/nearest/projection.feature
index f33a19f..33a8278 100644
--- a/features/nearest/projection.feature
+++ b/features/nearest/projection.feature
@@ -1,105 +1,105 @@
 @nearest
 Feature: Locating Nearest node on a Way - basic projection onto way
 
-	Background:
-		Given the profile "testbot"
-	
-	Scenario: Nearest - easy-west way
-		Given the node map
-		 | 0 | 1 | 2 | 3 | 4 |
-		 |   | a | x | b |   |
-		 | 5 | 6 | 7 | 8 | 9 |
+    Background:
+        Given the profile "testbot"
 
-		And the ways
-		 | nodes |
-		 | ab    |
+    Scenario: Nearest - easy-west way
+        Given the node map
+            | 0 | 1 | 2 | 3 | 4 |
+            |   | a | x | b |   |
+            | 5 | 6 | 7 | 8 | 9 |
 
-		When I request nearest I should get
-		 | in | out |
-		 | 0  | a   |
-		 | 1  | a   |
-		 | 2  | x   |
-		 | 3  | b   |
-		 | 4  | b   |
-		 | 5  | a   |
-		 | 6  | a   |
-		 | 7  | x   |
-		 | 8  | b   |
-		 | 9  | b   |
+        And the ways
+            | nodes |
+            | ab    |
 
- 	Scenario: Nearest - north-south way
- 		Given the node map
- 		 | 0 |   | 5 |
- 		 | 1 | a | 6 |
- 		 | 2 | x | 7 |
- 		 | 3 | b | 8 |
- 		 | 4 |   | 9 |
-         
- 		And the ways
- 		 | nodes |
- 		 | ab    |
+        When I request nearest I should get
+            | in | out |
+            | 0  | a   |
+            | 1  | a   |
+            | 2  | x   |
+            | 3  | b   |
+            | 4  | b   |
+            | 5  | a   |
+            | 6  | a   |
+            | 7  | x   |
+            | 8  | b   |
+            | 9  | b   |
 
- 		When I request nearest I should get
- 		 | in | out |
- 		 | 0  | a   |
- 		 | 1  | a   |
- 		 | 2  | x   |
- 		 | 3  | b   |
- 		 | 4  | b   |
- 		 | 5  | a   |
- 		 | 6  | a   |
- 		 | 7  | x   |
- 		 | 8  | b   |
- 		 | 9  | b   |
+    Scenario: Nearest - north-south way
+        Given the node map
+            | 0 |   | 5 |
+            | 1 | a | 6 |
+            | 2 | x | 7 |
+            | 3 | b | 8 |
+            | 4 |   | 9 |
 
-  	Scenario: Nearest - diagonal 1
-  		Given the node map
- 		 | 8 |   | 4 |   |   |   |
- 		 |   | a |   | 5 |   |   |
- 		 | 0 |   | x |   | 6 |   |
- 		 |   | 1 |   | y |   | 7 |
- 		 |   |   | 2 |   | b |   |
- 		 |   |   |   | 3 |   | 9 |
+        And the ways
+            | nodes |
+            | ab    |
 
-  		And the ways
-  		 | nodes |
-  		 | ab    |
+        When I request nearest I should get
+            | in | out |
+            | 0  | a   |
+            | 1  | a   |
+            | 2  | x   |
+            | 3  | b   |
+            | 4  | b   |
+            | 5  | a   |
+            | 6  | a   |
+            | 7  | x   |
+            | 8  | b   |
+            | 9  | b   |
 
-  		When I request nearest I should get
-  		 | in | out |
-  		 | 0  | a   |
-  		 | 1  | x   |
-  		 | 2  | y   |
-  		 | 3  | b   |
-  		 | 4  | a   |
-  		 | 5  | x   |
-  		 | 6  | y   |
-  		 | 7  | b   |
-  		 | 8  | a   |
-  		 | 9  | b   |
+    Scenario: Nearest - diagonal 1
+        Given the node map
+            | 8 |   | 4 |   |   |   |
+            |   | a |   | 5 |   |   |
+            | 0 |   | x |   | 6 |   |
+            |   | 1 |   | y |   | 7 |
+            |   |   | 2 |   | b |   |
+            |   |   |   | 3 |   | 9 |
 
-   	Scenario: Nearest - diagonal 2
-   		Given the node map
-  		 |   |   |   | 3 |   | 9 |
-  		 |   |   | 2 |   | b |   |
-  		 |   | 1 |   | y |   | 7 |
-  		 | 0 |   | x |   | 6 |   |
-  		 |   | a |   | 5 |   |   |
-  		 | 8 |   | 4 |   |   |   |
+        And the ways
+            | nodes |
+            | ab    |
 
-   		And the ways
-   		 | nodes |
-   		 | ab    |
+        When I request nearest I should get
+            | in | out |
+            | 0  | a   |
+            | 1  | x   |
+            | 2  | y   |
+            | 3  | b   |
+            | 4  | a   |
+            | 5  | x   |
+            | 6  | y   |
+            | 7  | b   |
+            | 8  | a   |
+            | 9  | b   |
 
-   		When I request nearest I should get
-   		 | in | out |
-   		 | 0  | a   |
-   		 | 1  | x   |
-   		 | 2  | y   |
-   		 | 3  | b   |
-   		 | 4  | a   |
-   		 | 5  | x   |
-   		 | 6  | y   |
-   		 | 7  | b   |
-   		 | 8  | a   |
-   		 | 9  | b   |
+    Scenario: Nearest - diagonal 2
+        Given the node map
+            |   |   |   | 3 |   | 9 |
+            |   |   | 2 |   | b |   |
+            |   | 1 |   | y |   | 7 |
+            | 0 |   | x |   | 6 |   |
+            |   | a |   | 5 |   |   |
+            | 8 |   | 4 |   |   |   |
+
+        And the ways
+            | nodes |
+            | ab    |
+
+        When I request nearest I should get
+            | in | out |
+            | 0  | a   |
+            | 1  | x   |
+            | 2  | y   |
+            | 3  | b   |
+            | 4  | a   |
+            | 5  | x   |
+            | 6  | y   |
+            | 7  | b   |
+            | 8  | a   |
+            | 9  | b   |
diff --git a/features/options/extract/files.feature b/features/options/extract/files.feature
new file mode 100644
index 0000000..3061263
--- /dev/null
+++ b/features/options/extract/files.feature
@@ -0,0 +1,30 @@
+ at extract @options @files
+Feature: osrm-extract command line options: files
+# expansions:
+# {base} => path to current input file
+# {profile} => path to current profile script
+
+    Background:
+        Given the profile "testbot"
+        And the node map
+            | a | b |
+        And the ways
+            | nodes |
+            | ab    |
+        And the data has been saved to disk
+
+    Scenario: osrm-extract - Passing base file
+        When I run "osrm-extract {base}.osm --profile {profile}"
+        Then stderr should be empty
+        And it should exit with code 0
+
+    Scenario: osrm-extract - Order of options should not matter
+        When I run "osrm-extract --profile {profile} {base}.osm"
+        Then stderr should be empty
+        And it should exit with code 0
+
+    Scenario: osrm-extract - Missing input file
+        When I run "osrm-extract over-the-rainbow.osrm --profile {profile}"
+        And stderr should contain "over-the-rainbow.osrm"
+        And stderr should contain "not found"
+        And it should exit with code 1
diff --git a/features/options/extract/help.feature b/features/options/extract/help.feature
new file mode 100644
index 0000000..3215e6a
--- /dev/null
+++ b/features/options/extract/help.feature
@@ -0,0 +1,47 @@
+ at extract @options @help
+Feature: osrm-extract command line options: help
+
+    Background:
+        Given the profile "testbot"
+
+    Scenario: osrm-extract - Help should be shown when no options are passed
+        When I run "osrm-extract"
+        Then stderr should be empty
+        And stdout should contain "osrm-extract <input.osm/.osm.bz2/.osm.pbf> [options]:"
+        And stdout should contain "Options:"
+        And stdout should contain "--version"
+        And stdout should contain "--help"
+        And stdout should contain "--config"
+        And stdout should contain "Configuration:"
+        And stdout should contain "--profile"
+        And stdout should contain "--threads"
+        And stdout should contain 12 lines
+        And it should exit with code 0
+
+    Scenario: osrm-extract - Help, short
+        When I run "osrm-extract -h"
+        Then stderr should be empty
+        And stdout should contain "osrm-extract <input.osm/.osm.bz2/.osm.pbf> [options]:"
+        And stdout should contain "Options:"
+        And stdout should contain "--version"
+        And stdout should contain "--help"
+        And stdout should contain "--config"
+        And stdout should contain "Configuration:"
+        And stdout should contain "--profile"
+        And stdout should contain "--threads"
+        And stdout should contain 12 lines
+        And it should exit with code 0
+
+    Scenario: osrm-extract - Help, long
+        When I run "osrm-extract --help"
+        Then stderr should be empty
+        And stdout should contain "osrm-extract <input.osm/.osm.bz2/.osm.pbf> [options]:"
+        And stdout should contain "Options:"
+        And stdout should contain "--version"
+        And stdout should contain "--help"
+        And stdout should contain "--config"
+        And stdout should contain "Configuration:"
+        And stdout should contain "--profile"
+        And stdout should contain "--threads"
+        And stdout should contain 12 lines
+        And it should exit with code 0
diff --git a/features/options/extract/invalid.feature b/features/options/extract/invalid.feature
new file mode 100644
index 0000000..169e53c
--- /dev/null
+++ b/features/options/extract/invalid.feature
@@ -0,0 +1,12 @@
+ at extract @options @invalid
+Feature: osrm-extract command line options: invalid options
+
+    Background:
+        Given the profile "testbot"
+
+    Scenario: osrm-extract - Non-existing option
+        When I run "osrm-extract --fly-me-to-the-moon"
+        Then stdout should be empty
+        And stderr should contain "option"
+        And stderr should contain "fly-me-to-the-moon"
+        And it should exit with code 1
diff --git a/features/options/extract/version.feature b/features/options/extract/version.feature
new file mode 100644
index 0000000..0dd5f65
--- /dev/null
+++ b/features/options/extract/version.feature
@@ -0,0 +1,22 @@
+ at extract @options @version
+Feature: osrm-extract command line options: version
+# the regex will match these two formats:
+# v0.3.7.0          # this is the normal format when you build from a git clone
+# -128-NOTFOUND     # if you build from a shallow clone (used on Travis)
+
+    Background:
+        Given the profile "testbot"
+    
+    Scenario: osrm-extract - Version, short
+        When I run "osrm-extract --v"
+        Then stderr should be empty
+        And stdout should contain 1 line
+        And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
+        And it should exit with code 0
+
+    Scenario: osrm-extract - Version, long
+        When I run "osrm-extract --version"
+        Then stderr should be empty
+        And stdout should contain 1 line
+        And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
+        And it should exit with code 0
diff --git a/features/options/prepare/files.feature b/features/options/prepare/files.feature
new file mode 100644
index 0000000..de356a8
--- /dev/null
+++ b/features/options/prepare/files.feature
@@ -0,0 +1,30 @@
+ at prepare @options @files
+Feature: osrm-prepare command line options: files
+# expansions:
+# {base} => path to current input file
+# {profile} => path to current profile script
+
+    Background:
+        Given the profile "testbot"
+        And the node map
+            | a | b |
+        And the ways
+            | nodes |
+            | ab    |
+        And the data has been extracted
+
+    Scenario: osrm-prepare - Passing base file
+        When I run "osrm-prepare {base}.osrm --profile {profile}"
+        Then stderr should be empty
+        And it should exit with code 0
+
+    Scenario: osrm-prepare - Order of options should not matter
+        When I run "osrm-prepare --profile {profile} {base}.osrm"
+        Then stderr should be empty
+        And it should exit with code 0
+
+    Scenario: osrm-prepare - Missing input file
+        When I run "osrm-prepare over-the-rainbow.osrm --profile {profile}"
+        And stderr should contain "over-the-rainbow.osrm"
+        And stderr should contain "not found"
+        And it should exit with code 1
diff --git a/features/options/prepare/help.feature b/features/options/prepare/help.feature
new file mode 100644
index 0000000..49497ae
--- /dev/null
+++ b/features/options/prepare/help.feature
@@ -0,0 +1,50 @@
+ at prepare @options @help
+Feature: osrm-prepare command line options: help
+
+    Background:
+        Given the profile "testbot"
+
+    Scenario: osrm-prepare - Help should be shown when no options are passed
+        When I run "osrm-prepare"
+        Then stderr should be empty
+        And stdout should contain "osrm-prepare <input.osrm> [options]:"
+        And stdout should contain "Options:"
+        And stdout should contain "--version"
+        And stdout should contain "--help"
+        And stdout should contain "--config"
+        And stdout should contain "Configuration:"
+        And stdout should contain "--restrictions"
+        And stdout should contain "--profile"
+        And stdout should contain "--threads"
+        And stdout should contain 15 lines
+        And it should exit with code 0
+
+    Scenario: osrm-prepare - Help, short
+        When I run "osrm-prepare -h"
+        Then stderr should be empty
+        And stdout should contain "osrm-prepare <input.osrm> [options]:"
+        And stdout should contain "Options:"
+        And stdout should contain "--version"
+        And stdout should contain "--help"
+        And stdout should contain "--config"
+        And stdout should contain "Configuration:"
+        And stdout should contain "--restrictions"
+        And stdout should contain "--profile"
+        And stdout should contain "--threads"
+        And stdout should contain 15 lines
+        And it should exit with code 0
+
+    Scenario: osrm-prepare - Help, long
+        When I run "osrm-prepare --help"
+        Then stderr should be empty
+        And stdout should contain "osrm-prepare <input.osrm> [options]:"
+        And stdout should contain "Options:"
+        And stdout should contain "--version"
+        And stdout should contain "--help"
+        And stdout should contain "--config"
+        And stdout should contain "Configuration:"
+        And stdout should contain "--restrictions"
+        And stdout should contain "--profile"
+        And stdout should contain "--threads"
+        And stdout should contain 15 lines
+        And it should exit with code 0
diff --git a/features/options/prepare/invalid.feature b/features/options/prepare/invalid.feature
new file mode 100644
index 0000000..7450390
--- /dev/null
+++ b/features/options/prepare/invalid.feature
@@ -0,0 +1,12 @@
+ at prepare @options @invalid
+Feature: osrm-prepare command line options: invalid options
+
+    Background:
+        Given the profile "testbot"
+
+    Scenario: osrm-prepare - Non-existing option
+        When I run "osrm-prepare --fly-me-to-the-moon"
+        Then stdout should be empty
+        And stderr should contain "option"
+        And stderr should contain "fly-me-to-the-moon"
+        And it should exit with code 1
diff --git a/features/options/prepare/version.feature b/features/options/prepare/version.feature
new file mode 100644
index 0000000..7a821c6
--- /dev/null
+++ b/features/options/prepare/version.feature
@@ -0,0 +1,22 @@
+ at prepare @options @version
+Feature: osrm-prepare command line options: version
+# the regex will match these two formats:
+# v0.3.7.0          # this is the normal format when you build from a git clone
+# -128-NOTFOUND     # if you build from a shallow clone (used on Travis)
+
+    Background:
+        Given the profile "testbot"
+    
+    Scenario: osrm-prepare - Version, short
+        When I run "osrm-prepare --v"
+        Then stderr should be empty
+        And stdout should contain 1 line
+        And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
+        And it should exit with code 0
+
+    Scenario: osrm-prepare - Version, long
+        When I run "osrm-prepare --version"
+        Then stderr should be empty
+        And stdout should contain 1 line
+        And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
+        And it should exit with code 0
diff --git a/features/options/routed/files.feature b/features/options/routed/files.feature
new file mode 100644
index 0000000..716b2a4
--- /dev/null
+++ b/features/options/routed/files.feature
@@ -0,0 +1,27 @@
+ at routed @options @files
+Feature: osrm-routed command line options: files
+# Normally when launching osrm-routed, it will keep running as a server until it's shut down.
+# For testing program options, the --trial option is used, which causes osrm-routed to quit
+# immediately after initialization. This makes testing easier and faster.
+# 
+# The {base} part of the options to osrm-routed will be expanded to the actual base path of
+# the preprocessed file.
+
+    Background:
+        Given the profile "testbot"
+        And the node map
+            | a | b |
+        And the ways
+            | nodes |
+            | ab    |
+        And the data has been prepared
+
+    Scenario: osrm-routed - Passing base file
+        When I run "osrm-routed {base}.osrm --trial"
+        Then stdout should contain /^\[info\] starting up engines/
+        And stdout should contain /\d{1,2}\.\d{1,2}\.\d{1,2}/
+        And stdout should contain /compiled at/
+        And stdout should contain /^\[info\] loaded plugin: viaroute/
+        And stdout should contain /^\[info\] trial run/
+        And stdout should contain /^\[info\] shutdown completed/
+        And it should exit with code 0
\ No newline at end of file
diff --git a/features/options/routed/help.feature b/features/options/routed/help.feature
new file mode 100644
index 0000000..9603c40
--- /dev/null
+++ b/features/options/routed/help.feature
@@ -0,0 +1,77 @@
+ at routed @options @help
+Feature: osrm-routed command line options: help
+
+    Background:
+        Given the profile "testbot"
+
+    Scenario: osrm-routed - Help should be shown when no options are passed
+        When I run "osrm-routed"
+        Then stderr should be empty
+        And stdout should contain "osrm-routed <base.osrm> [<options>]:"
+        And stdout should contain "Options:"
+        And stdout should contain "--version"
+        And stdout should contain "--help"
+        And stdout should contain "--config"
+        And stdout should contain "--trial"
+        And stdout should contain "Configuration:"
+        And stdout should contain "--hsgrdata arg"
+        And stdout should contain "--nodesdata arg"
+        And stdout should contain "--edgesdata arg"
+        And stdout should contain "--ramindex arg"
+        And stdout should contain "--fileindex arg"
+        And stdout should contain "--namesdata arg"
+        And stdout should contain "--timestamp arg"
+        And stdout should contain "--ip"
+        And stdout should contain "--port"
+        And stdout should contain "--threads"
+        And stdout should contain "--sharedmemory"
+        And stdout should contain 22 lines
+        And it should exit with code 0
+
+    Scenario: osrm-routed - Help, short
+        When I run "osrm-routed -h"
+        Then stderr should be empty
+        And stdout should contain "osrm-routed <base.osrm> [<options>]:"
+        And stdout should contain "Options:"
+        And stdout should contain "--version"
+        And stdout should contain "--help"
+        And stdout should contain "--config"
+        And stdout should contain "--trial"
+        And stdout should contain "Configuration:"
+        And stdout should contain "--hsgrdata arg"
+        And stdout should contain "--nodesdata arg"
+        And stdout should contain "--edgesdata arg"
+        And stdout should contain "--ramindex arg"
+        And stdout should contain "--fileindex arg"
+        And stdout should contain "--namesdata arg"
+        And stdout should contain "--timestamp arg"
+        And stdout should contain "--ip"
+        And stdout should contain "--port"
+        And stdout should contain "--threads"
+        And stdout should contain "--sharedmemory"
+        And stdout should contain 22 lines
+        And it should exit with code 0
+
+    Scenario: osrm-routed - Help, long
+        When I run "osrm-routed --help"
+        Then stderr should be empty
+        And stdout should contain "osrm-routed <base.osrm> [<options>]:"
+        And stdout should contain "Options:"
+        And stdout should contain "--version"
+        And stdout should contain "--help"
+        And stdout should contain "--config"
+        And stdout should contain "--trial"
+        And stdout should contain "Configuration:"
+        And stdout should contain "--hsgrdata arg"
+        And stdout should contain "--nodesdata arg"
+        And stdout should contain "--edgesdata arg"
+        And stdout should contain "--ramindex arg"
+        And stdout should contain "--fileindex arg"
+        And stdout should contain "--namesdata arg"
+        And stdout should contain "--timestamp arg"
+        And stdout should contain "--ip"
+        And stdout should contain "--port"
+        And stdout should contain "--threads"
+        And stdout should contain "--sharedmemory"
+        And stdout should contain 22 lines
+        And it should exit with code 0
diff --git a/features/options/routed/invalid.feature b/features/options/routed/invalid.feature
new file mode 100644
index 0000000..a6d62d7
--- /dev/null
+++ b/features/options/routed/invalid.feature
@@ -0,0 +1,19 @@
+ at routed @options @invalid
+Feature: osrm-routed command line options: invalid options
+
+    Background:
+        Given the profile "testbot"
+
+    Scenario: osrm-routed - Non-existing option
+        When I run "osrm-routed --fly-me-to-the-moon"
+        Then stdout should be empty
+        And stderr should contain "exception"
+        And stderr should contain "fly-me-to-the-moon"
+        And it should exit with code 1
+
+    Scenario: osrm-routed - Missing file
+        When I run "osrm-routed over-the-rainbow.osrm"
+        Then stdout should contain "over-the-rainbow.osrm"
+        And stderr should contain "exception"
+        And stderr should contain "not found"
+        And it should exit with code 1
diff --git a/features/options/routed/version.feature b/features/options/routed/version.feature
new file mode 100644
index 0000000..b544e36
--- /dev/null
+++ b/features/options/routed/version.feature
@@ -0,0 +1,22 @@
+ at routed @options @version
+Feature: osrm-routed command line options: version
+# the regex will match these two formats:
+# v0.3.7.0          # this is the normal format when you build from a git clone
+# -128-NOTFOUND     # if you build from a shallow clone (used on Travis)
+
+    Background:
+        Given the profile "testbot"
+    
+    Scenario: osrm-routed - Version, short
+        When I run "osrm-routed --v"
+        Then stderr should be empty
+        And stdout should contain 1 line
+        And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
+        And it should exit with code 0
+
+    Scenario: osrm-routed - Version, long
+        When I run "osrm-routed --version"
+        Then stderr should be empty
+        And stdout should contain 1 line
+        And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
+        And it should exit with code 0
diff --git a/features/step_definitions/data.rb b/features/step_definitions/data.rb
index 1e021b6..e0985a4 100644
--- a/features/step_definitions/data.rb
+++ b/features/step_definitions/data.rb
@@ -2,10 +2,18 @@ Given /^the profile "([^"]*)"$/ do |profile|
   set_profile profile
 end
 
+Given(/^the import format "(.*?)"$/) do |format|
+  set_input_format format
+end
+
 Given /^a grid size of (\d+) meters$/ do |meters|
   set_grid_size meters
 end
 
+Given /^the origin ([-+]?[0-9]*\.?[0-9]+),([-+]?[0-9]*\.?[0-9]+)$/ do |lat,lon|
+  set_origin [lon.to_f,lat.to_f]
+end
+
 Given /^the shortcuts$/ do |table|
   table.hashes.each do |row|
     shortcuts_hash[ row['key'] ] = row['value']
@@ -19,11 +27,11 @@ Given /^the node map$/ do |table|
         raise "*** node invalid name '#{name}', must be single characters" unless name.size == 1
         raise "*** invalid node name '#{name}', must me alphanumeric" unless name.match /[a-z0-9]/
         if name.match /[a-z]/
-            raise "*** duplicate node '#{name}'" if name_node_hash[name]
-            add_osm_node name, *table_coord_to_lonlat(ci,ri)
+          raise "*** duplicate node '#{name}'" if name_node_hash[name]
+          add_osm_node name, *table_coord_to_lonlat(ci,ri)
         else
-            raise "*** duplicate node '#{name}'" if location_hash[name]
-            add_location name, *table_coord_to_lonlat(ci,ri)
+          raise "*** duplicate node '#{name}'" if location_hash[name]
+          add_location name, *table_coord_to_lonlat(ci,ri)
         end
       end
     end
@@ -35,9 +43,9 @@ Given /^the node locations$/ do |table|
     name = row['node']
     raise "*** duplicate node '#{name}'" if find_node_by_name name
     if name.match /[a-z]/
-        add_osm_node name, row['lon'].to_f, row['lat'].to_f 
+      add_osm_node name, row['lon'].to_f, row['lat'].to_f
     else
-        add_location name, row['lon'].to_f, row['lat'].to_f 
+      add_location name, row['lon'].to_f, row['lat'].to_f
     end
   end
 end
@@ -52,10 +60,11 @@ Given /^the nodes$/ do |table|
 end
 
 Given /^the ways$/ do |table|
+  raise "*** Map data already defined - did you pass an input file in this scenaria?" if @osm_str
   table.hashes.each do |row|
     way = OSM::Way.new make_osm_id, OSM_USER, OSM_TIMESTAMP
     way.uid = OSM_UID
-    
+
     nodes = row.delete 'nodes'
     raise "*** duplicate way '#{nodes}'" if name_way_hash[nodes]
     nodes.each_char do |c|
@@ -64,14 +73,14 @@ Given /^the ways$/ do |table|
       raise "*** unknown node '#{c}'" unless node
       way << node
     end
-    
+
     defaults = { 'highway' => 'primary' }
     tags = defaults.merge(row)
 
     if row['highway'] == '(nil)'
       tags.delete 'highway'
     end
-    
+
     if row['name'] == nil
       tags['name'] = nodes
     elsif (row['name'] == '""') || (row['name'] == "''")
@@ -81,7 +90,7 @@ Given /^the ways$/ do |table|
     else
       tags['name'] = row['name']
     end
-    
+
     way << tags
     osm_db << way
     name_way_hash[nodes] = way
@@ -89,6 +98,7 @@ Given /^the ways$/ do |table|
 end
 
 Given /^the relations$/ do |table|
+  raise "*** Map data already defined - did you pass an input file in this scenaria?" if @osm_str
   table.hashes.each do |row|
     relation = OSM::Relation.new make_osm_id, OSM_USER, OSM_TIMESTAMP
     row.each_pair do |key,value|
@@ -119,3 +129,32 @@ end
 Given /^the defaults$/ do
 end
 
+Given /^the input file ([^"]*)$/ do |file|
+  raise "*** Input file must in .osm format" unless File.extname(file)=='.osm'
+  @osm_str = File.read file
+end
+
+Given /^the data has been saved to disk$/ do
+  begin
+    write_input_data
+  rescue OSRMError => e
+    @process_error = e
+  end
+end
+
+Given /^the data has been extracted$/ do
+  begin
+    write_input_data
+    extract_data unless extracted?
+  rescue OSRMError => e
+    @process_error = e
+  end
+end
+
+Given /^the data has been prepared$/ do
+  begin
+    reprocess
+  rescue OSRMError => e
+    @process_error = e
+  end
+end
diff --git a/features/step_definitions/nearest.rb b/features/step_definitions/locate.rb
similarity index 72%
copy from features/step_definitions/nearest.rb
copy to features/step_definitions/locate.rb
index 3b65792..9d3d74f 100644
--- a/features/step_definitions/nearest.rb
+++ b/features/step_definitions/locate.rb
@@ -1,7 +1,7 @@
-When /^I request nearest I should get$/ do |table|
+When /^I request locate I should get$/ do |table|
   reprocess
   actual = []
-  OSRMLauncher.new do
+  OSRMBackgroundLauncher.new("#{@osm_file}.osrm") do
     table.hashes.each_with_index do |row,ri|
       in_node = find_node_by_name row['in']
       raise "*** unknown in-node '#{row['in']}" unless in_node
@@ -9,16 +9,16 @@ When /^I request nearest I should get$/ do |table|
       out_node = find_node_by_name row['out']
       raise "*** unknown out-node '#{row['out']}" unless out_node
 
-      response = request_nearest("#{in_node.lat},#{in_node.lon}")
+      response = request_locate("#{in_node.lat},#{in_node.lon}")
       if response.code == "200" && response.body.empty? == false
         json = JSON.parse response.body
         if json['status'] == 0
           coord =  json['mapped_coordinate']
         end
       end
-      
+
       got = {'in' => row['in'], 'out' => coord }
-      
+
       ok = true
       row.keys.each do |key|
         if key=='out'
@@ -30,22 +30,22 @@ When /^I request nearest I should get$/ do |table|
           end
         end
       end
-      
+
       unless ok
-        failed = { :attempt => 'nearest', :query => @query, :response => response }
+        failed = { :attempt => 'locate', :query => @query, :response => response }
         log_fail row,got,[failed]
       end
-      
+
       actual << got
     end
   end
   table.routing_diff! actual
 end
 
-When /^I request nearest (\d+) times I should get$/ do |n,table|
+When /^I request locate (\d+) times I should get$/ do |n,table|
   ok = true
   n.to_i.times do
-    ok = false unless step "I request nearest I should get", table
+    ok = false unless step "I request locate I should get", table
   end
   ok
-end
\ No newline at end of file
+end
diff --git a/features/step_definitions/nearest.rb b/features/step_definitions/nearest.rb
index 3b65792..ae5a79c 100644
--- a/features/step_definitions/nearest.rb
+++ b/features/step_definitions/nearest.rb
@@ -1,7 +1,7 @@
 When /^I request nearest I should get$/ do |table|
   reprocess
   actual = []
-  OSRMLauncher.new do
+  OSRMBackgroundLauncher.new("#{@osm_file}.osrm") do
     table.hashes.each_with_index do |row,ri|
       in_node = find_node_by_name row['in']
       raise "*** unknown in-node '#{row['in']}" unless in_node
@@ -16,9 +16,9 @@ When /^I request nearest I should get$/ do |table|
           coord =  json['mapped_coordinate']
         end
       end
-      
+
       got = {'in' => row['in'], 'out' => coord }
-      
+
       ok = true
       row.keys.each do |key|
         if key=='out'
@@ -30,12 +30,12 @@ When /^I request nearest I should get$/ do |table|
           end
         end
       end
-      
+
       unless ok
         failed = { :attempt => 'nearest', :query => @query, :response => response }
         log_fail row,got,[failed]
       end
-      
+
       actual << got
     end
   end
@@ -48,4 +48,4 @@ When /^I request nearest (\d+) times I should get$/ do |n,table|
     ok = false unless step "I request nearest I should get", table
   end
   ok
-end
\ No newline at end of file
+end
diff --git a/features/step_definitions/options.rb b/features/step_definitions/options.rb
new file mode 100644
index 0000000..ac3bc99
--- /dev/null
+++ b/features/step_definitions/options.rb
@@ -0,0 +1,49 @@
+When(/^I run "osrm\-routed\s?(.*?)"$/) do |options|
+  begin
+    Timeout.timeout(1) { run_bin 'osrm-routed', options }
+  rescue Timeout::Error
+    raise "*** osrm-routed didn't quit. Maybe the --trial option wasn't used?"
+  end
+end
+
+When(/^I run "osrm\-extract\s?(.*?)"$/) do |options|
+  run_bin 'osrm-extract', options
+end
+
+When(/^I run "osrm\-prepare\s?(.*?)"$/) do |options|
+  run_bin 'osrm-prepare', options
+end
+
+Then /^it should exit with code (\d+)$/ do |code|
+  @exit_code.should == code.to_i
+end
+
+Then /^stdout should contain "(.*?)"$/ do |str|
+  @stdout.should include(str)
+end
+
+Then /^stderr should contain "(.*?)"$/ do |str|
+  @stderr.should include(str)
+end
+
+Then(/^stdout should contain \/(.*)\/$/) do |regex_str|
+  regex = Regexp.new regex_str
+  @stdout.should =~ regex
+end
+
+Then(/^stderr should contain \/(.*)\/$/) do |regex_str|
+  regex = Regexp.new regex_str
+  @stderr.should =~ regex
+end
+
+Then /^stdout should be empty$/ do
+  @stdout.should == ""
+end
+
+Then /^stderr should be empty$/ do
+  @stderr.should == ""
+end
+
+Then /^stdout should contain (\d+) lines?$/ do |lines|
+  @stdout.lines.count.should == lines.to_i
+end
diff --git a/features/step_definitions/requests.rb b/features/step_definitions/requests.rb
index d965b1a..519a739 100644
--- a/features/step_definitions/requests.rb
+++ b/features/step_definitions/requests.rb
@@ -1,6 +1,6 @@
 When /^I request \/(.*)$/ do |path|
   reprocess
-  OSRMLauncher.new do
+  OSRMBackgroundLauncher.new("#{@osm_file}.osrm") do
     @response = request_path path
   end
 end
@@ -16,9 +16,17 @@ Then /^response should be valid JSON$/ do
 end
 
 Then /^response should be well-formed$/ do
-  @json['version'].class.should == Float
   @json['status'].class.should == Fixnum
-  @json['transactionId'].class.should == String
+end
+
+Then /^status code should be (\d+)$/ do |code|
+  @json = JSON.parse @response.body
+  @json['status'].should == code.to_i
+end
+
+Then /^status message should be "(.*?)"$/ do |message|
+  @json = JSON.parse @response.body
+  @json['status_message'].should == message
 end
 
 Then /^response should be a well-formed route$/ do
@@ -28,18 +36,11 @@ Then /^response should be a well-formed route$/ do
   @json['route_geometry'].class.should == String
   @json['route_instructions'].class.should == Array
   @json['via_points'].class.should == Array
-end
-
-When /^I preprocess data$/ do
-  begin
-    reprocess
-  rescue OSRMError => e
-    @process_error = e
-  end
+  @json['via_indices'].class.should == Array
 end
 
 Then /^"([^"]*)" should return code (\d+)$/ do |binary, code|
   @process_error.is_a?(OSRMError).should == true
   @process_error.process.should == binary
   @process_error.code.to_i.should == code.to_i
-end
+end
\ No newline at end of file
diff --git a/features/step_definitions/routability.rb b/features/step_definitions/routability.rb
index 078428a..161171f 100644
--- a/features/step_definitions/routability.rb
+++ b/features/step_definitions/routability.rb
@@ -1,3 +1,42 @@
+def test_routability_row i
+  result = {}
+  ['forw','backw'].each do |direction|
+    a = Location.new @origin[0]+(1+WAY_SPACING*i)*@zoom, @origin[1]
+    b = Location.new @origin[0]+(3+WAY_SPACING*i)*@zoom, @origin[1]
+    r = {}
+    r[:response] = request_route direction=='forw' ? [a,b] : [b,a]
+    r[:query] = @query
+    r[:json] = JSON.parse(r[:response].body)
+
+    r[:status] = route_status r[:response]
+    if r[:status].empty? == false
+      r[:route] = way_list r[:json]['route_instructions']
+
+      if r[:route]=="w#{i}"
+        r[:time] = r[:json]['route_summary']['total_time']
+        r[:distance] = r[:json]['route_summary']['total_distance']
+        r[:speed] = r[:time]>0 ? (3.6*r[:distance]/r[:time]).to_i : nil
+      else
+        # if we hit the wrong way segment, we assume it's
+        # because the one we tested was not unroutable
+        r[:status] = nil
+      end
+    end
+    result[direction] = r
+  end
+
+  # check if forw and backw returned the same values
+  result['bothw'] = {}
+  [:status,:time,:distance,:speed].each do |key|
+    if result['forw'][key] == result['backw'][key]
+      result['bothw'][key] = result['forw'][key]
+    else
+      result['bothw'][key] = 'diff'
+    end
+  end
+  result
+end
+
 Then /^routability should be$/ do |table|
   build_ways_from_table table
   reprocess
@@ -5,46 +44,34 @@ Then /^routability should be$/ do |table|
   if table.headers&["forw","backw","bothw"] == []
     raise "*** routability tabel must contain either 'forw', 'backw' or 'bothw' column"
   end
-  OSRMLauncher.new do
+  OSRMBackgroundLauncher.new("#{@osm_file}.osrm") do
     table.hashes.each_with_index do |row,i|
-      got = row.dup
+      output_row = row.dup
       attempts = []
-      ['forw','backw','bothw'].each do |direction|
-        if table.headers.include? direction
-          if direction == 'forw' || direction == 'bothw'
-            a = Location.new ORIGIN[0]+(1+WAY_SPACING*i)*@zoom, ORIGIN[1]
-            b = Location.new ORIGIN[0]+(3+WAY_SPACING*i)*@zoom, ORIGIN[1]
-            response = request_route [a,b]
-          elsif direction == 'backw' || direction == 'bothw'
-            a = Location.new ORIGIN[0]+(3+WAY_SPACING*i)*@zoom, ORIGIN[1]
-            b = Location.new ORIGIN[0]+(1+WAY_SPACING*i)*@zoom, ORIGIN[1]
-            response = request_route [a,b]
-          end
-          want = shortcuts_hash[row[direction]] || row[direction]     #expand shortcuts
-          got[direction] = route_status response
-          json = JSON.parse(response.body)
-          if got[direction].empty? == false
-            route = way_list json['route_instructions']
-            if route != "w#{i}"
-              if row[direction].empty? == true
-                got[direction] = want
-              else
-                got[direction] = "testing w#{i}, but got #{route}!?"
-              end
-            elsif want =~ /^\d+s/
-              time = json['route_summary']['total_time']
-              got[direction] = "#{time}s"
-            end
-          end
-          if FuzzyMatch.match got[direction], want
-            got[direction] = row[direction]
-          else
-            attempts << { :attempt => direction, :query => @query, :response => response }
-          end
+      result = test_routability_row i
+      directions = ['forw','backw','bothw']
+      (directions & table.headers).each do |direction|
+        want = shortcuts_hash[row[direction]] || row[direction]     #expand shortcuts
+        case want
+        when '', 'x'
+          output_row[direction] = result[direction][:status].to_s
+        when /^\d+s/
+          output_row[direction] = "#{result[direction][:time]}s"
+        when /^\d+ km\/h/
+          output_row[direction] = "#{result[direction][:speed]} km/h"
+        else
+          raise "*** Unknown expectation format: #{want}"
         end
+
+        if FuzzyMatch.match output_row[direction], want
+          output_row[direction] = row[direction]
+        end
+      end
+
+      if output_row != row
+        log_fail row,output_row,result
       end
-      log_fail row,got,attempts if got != row
-      actual << got
+      actual << output_row
     end
   end
   table.routing_diff! actual
diff --git a/features/step_definitions/routing.rb b/features/step_definitions/routing.rb
index 13c8b6a..92b69ea 100644
--- a/features/step_definitions/routing.rb
+++ b/features/step_definitions/routing.rb
@@ -1,31 +1,38 @@
 When /^I route I should get$/ do |table|
   reprocess
   actual = []
-  OSRMLauncher.new do
+  OSRMBackgroundLauncher.new("#{@osm_file}.osrm") do
     table.hashes.each_with_index do |row,ri|
-      waypoints = []
-      if row['from'] and row['to']
-        node = find_node_by_name(row['from'])
-        raise "*** unknown from-node '#{row['from']}" unless node
-        waypoints << node
-        
-        node = find_node_by_name(row['to'])
-        raise "*** unknown to-node '#{row['to']}" unless node
-        waypoints << node
-        
-        got = {'from' => row['from'], 'to' => row['to'] }
-      elsif row['waypoints']
-        row['waypoints'].split(',').each do |n|
-          node = find_node_by_name(n.strip)
-          raise "*** unknown waypoint node '#{n.strip}" unless node
+      if row['request']
+        got = {'request' => row['request'] }
+        response = request_url row['request']
+      else
+        params = {}
+        waypoints = []
+        if row['from'] and row['to']
+          node = find_node_by_name(row['from'])
+          raise "*** unknown from-node '#{row['from']}" unless node
+          waypoints << node
+
+          node = find_node_by_name(row['to'])
+          raise "*** unknown to-node '#{row['to']}" unless node
           waypoints << node
+
+          got = {'from' => row['from'], 'to' => row['to'] }
+          response = request_route waypoints, params
+        elsif row['waypoints']
+          row['waypoints'].split(',').each do |n|
+            node = find_node_by_name(n.strip)
+            raise "*** unknown waypoint node '#{n.strip}" unless node
+            waypoints << node
+          end
+          got = {'waypoints' => row['waypoints'] }
+          response = request_route waypoints, params
+        else
+          raise "*** no waypoints"
         end
-        got = {'waypoints' => row['waypoints'] }
-      else
-        raise "*** no waypoints"
       end
-        
-      params = {}
+
       row.each_pair do |k,v|
         if k =~ /param:(.*)/
           if v=='(nil)'
@@ -36,54 +43,87 @@ When /^I route I should get$/ do |table|
           got[k]=v
         end
       end
-            
-      response = request_route(waypoints, params)
-      if response.code == "200" && response.body.empty? == false
+
+      if response.body.empty? == false
         json = JSON.parse response.body
+      end
+
+      if response.body.empty? == false
         if json['status'] == 0
           instructions = way_list json['route_instructions']
           bearings = bearing_list json['route_instructions']
           compasses = compass_list json['route_instructions']
           turns = turn_list json['route_instructions']
           modes = mode_list json['route_instructions']
+          times = time_list json['route_instructions']
+          distances = distance_list json['route_instructions']
         end
       end
-      
-      if table.headers.include? 'start'
-        got['start'] = instructions ? json['route_summary']['start_point'] : nil
+
+      if table.headers.include? 'status'
+        got['status'] = json['status'].to_s
       end
-      if table.headers.include? 'end'
-        got['end'] = instructions ? json['route_summary']['end_point'] : nil
+      if table.headers.include? 'message'
+        got['message'] = json['status_message']
       end
-      if table.headers.include? 'route'
-        got['route'] = (instructions || '').strip
-        if table.headers.include?('distance')
-          if row['distance']!=''
-            raise "*** Distance must be specied in meters. (ex: 250m)" unless row['distance'] =~ /\d+m/
-          end
-          got['distance'] = instructions ? "#{json['route_summary']['total_distance'].to_s}m" : ''
-        end
-        if table.headers.include?('time')
-          raise "*** Time must be specied in seconds. (ex: 60s)" unless row['time'] =~ /\d+s/
-          got['time'] = instructions ? "#{json['route_summary']['total_time'].to_s}s" : ''
-        end
-        if table.headers.include? 'bearing'
-          got['bearing'] = bearings
-        end
-        if table.headers.include? 'compass'
-          got['compass'] = compasses
+      if table.headers.include? '#'   # comment column
+        got['#'] = row['#']           # copy value so it always match
+      end
+
+      if response.code == "200"
+        if table.headers.include? 'start'
+          got['start'] = instructions ? json['route_summary']['start_point'] : nil
         end
-        if table.headers.include? 'turns'
-          got['turns'] = turns
+        if table.headers.include? 'end'
+          got['end'] = instructions ? json['route_summary']['end_point'] : nil
         end
-        if table.headers.include? 'modes'
-          got['modes'] = modes
+        if table.headers.include? 'geometry'
+            got['geometry'] = json['route_geometry']
         end
-        if table.headers.include? '#'   # comment column
-          got['#'] = row['#']           # copy value so it always match
+        if table.headers.include? 'route'
+          got['route'] = (instructions || '').strip
+          if table.headers.include?('distance')
+            if row['distance']!=''
+              raise "*** Distance must be specied in meters. (ex: 250m)" unless row['distance'] =~ /\d+m/
+            end
+            got['distance'] = instructions ? "#{json['route_summary']['total_distance'].to_s}m" : ''
+          end
+          if table.headers.include?('time')
+            raise "*** Time must be specied in seconds. (ex: 60s)" unless row['time'] =~ /\d+s/
+            got['time'] = instructions ? "#{json['route_summary']['total_time'].to_s}s" : ''
+          end
+          if table.headers.include?('speed')
+            if row['speed'] != '' && instructions
+              raise "*** Speed must be specied in km/h. (ex: 50 km/h)" unless row['speed'] =~ /\d+ km\/h/
+                time = json['route_summary']['total_time']
+                distance = json['route_summary']['total_distance']
+                speed = time>0 ? (3.6*distance/time).to_i : nil
+                got['speed'] =  "#{speed} km/h"
+            else
+              got['speed'] = ''
+            end
+          end
+          if table.headers.include? 'bearing'
+            got['bearing'] = bearings
+          end
+          if table.headers.include? 'compass'
+            got['compass'] = compasses
+          end
+          if table.headers.include? 'turns'
+            got['turns'] = turns
+          end
+          if table.headers.include? 'modes'
+            got['modes'] = modes
+          end
+          if table.headers.include? 'times'
+            got['times'] = times
+          end
+          if table.headers.include? 'distances'
+            got['distances'] = distances
+          end
         end
       end
-      
+
       ok = true
       row.keys.each do |key|
         if FuzzyMatch.match got[key], row[key]
@@ -92,12 +132,11 @@ When /^I route I should get$/ do |table|
           ok = false
         end
       end
-      
+
       unless ok
-        failed = { :attempt => 'route', :query => @query, :response => response }
-        log_fail row,got,[failed]
+        log_fail row,got, { 'route' => {:query => @query, :response => response} }
       end
-      
+
       actual << got
     end
   end
diff --git a/features/stress/launch.feature b/features/stress/launch.feature
index 2463782..10c13c8 100644
--- a/features/stress/launch.feature
+++ b/features/stress/launch.feature
@@ -1,58 +1,58 @@
 @stress
 Feature: Stress testing
-	
-	Background:
-		Given the profile "testbot"
-	
-	Scenario: Stress - 10km star, request 1 route
-	#osrm-routed hangs very often
-		Given a grid size of 10000 meters
-		Given the node map
-		 | h | a | b |
-		 | g | x | c |
-		 | f | e | d |
 
-		And the ways
-		 | nodes | highway   |
-		 | xa    | primary   |
-		 | xb    | primary   |
-		 | xc    | primary   |
-		 | xd    | primary   |
-		 | xe    | primary   |
-		 | xf    | primary   |
-		 | xg    | primary   |
-		 | xh    | primary   |
+    Background:
+        Given the profile "testbot"
 
- 		When I route 100 times I should get
- 		 | from | to | route |
- 		 | x    | h  | xh    |
+    Scenario: Stress - 10km star, request 1 route
+    #osrm-routed hangs very often
+        Given a grid size of 10000 meters
+        Given the node map
+            | h | a | b |
+            | g | x | c |
+            | f | e | d |
 
-	Scenario: Stress - 10km star, request 8 routes
-	#osrm-routed hangs sometimes
-		Given a grid size of 10000 meters
-		Given the node map
-		 | h | a | b |
-		 | g | x | c |
-		 | f | e | d |
+        And the ways
+            | nodes | highway |
+            | xa    | primary |
+            | xb    | primary |
+            | xc    | primary |
+            | xd    | primary |
+            | xe    | primary |
+            | xf    | primary |
+            | xg    | primary |
+            | xh    | primary |
 
-		And the ways
-		 | nodes | highway   |
-		 | xa    | primary   |
-		 | xb    | primary   |
-		 | xc    | primary   |
-		 | xd    | primary   |
-		 | xe    | primary   |
-		 | xf    | primary   |
-		 | xg    | primary   |
-		 | xh    | primary   |
+        When I route 100 times I should get
+            | from | to | route |
+            | x    | h  | xh    |
 
- 		When I route 100 times I should get
- 		 | from | to | route |
- 		 | x    | a  | xa    |
- 		 | x    | b  | xb    |
- 		 | x    | c  | xc    |
- 		 | x    | d  | xd    |
- 		 | x    | e  | xe    |
- 		 | x    | f  | xf    |
- 		 | x    | g  | xg    |
- 		 | x    | h  | xh    |
+    Scenario: Stress - 10km star, request 8 routes
+    #osrm-routed hangs sometimes
+        Given a grid size of 10000 meters
+        Given the node map
+            | h | a | b |
+            | g | x | c |
+            | f | e | d |
+
+        And the ways
+            | nodes | highway |
+            | xa    | primary |
+            | xb    | primary |
+            | xc    | primary |
+            | xd    | primary |
+            | xe    | primary |
+            | xf    | primary |
+            | xg    | primary |
+            | xh    | primary |
+
+        When I route 100 times I should get
+            | from | to | route |
+            | x    | a  | xa    |
+            | x    | b  | xb    |
+            | x    | c  | xc    |
+            | x    | d  | xd    |
+            | x    | e  | xe    |
+            | x    | f  | xf    |
+            | x    | g  | xg    |
+            | x    | h  | xh    |
diff --git a/features/support/config.rb b/features/support/config.rb
index 63350d5..e61c9fc 100644
--- a/features/support/config.rb
+++ b/features/support/config.rb
@@ -10,21 +10,3 @@ end
 def set_profile profile
   @profile = profile
 end
-
-def write_server_ini
-  s=<<-EOF
-Threads = 1
-IP = 0.0.0.0
-Port = #{OSRM_PORT}
-
-hsgrData=#{@osm_file}.osrm.hsgr
-nodesData=#{@osm_file}.osrm.nodes
-edgesData=#{@osm_file}.osrm.edges
-ramIndex=#{@osm_file}.osrm.ramIndex
-fileIndex=#{@osm_file}.osrm.fileIndex
-namesData=#{@osm_file}.osrm.names
-timestamp=#{@osm_file}.osrm.timestamp
-EOF
-  File.open( 'server.ini', 'w') {|f| f.write( s ) }
-end
-
diff --git a/features/support/cucumber.rb b/features/support/cucumber.rb
index 78465be..a43082a 100644
--- a/features/support/cucumber.rb
+++ b/features/support/cucumber.rb
@@ -23,7 +23,7 @@ class Cucumber::Ast::Table
     require_diff_lcs
     cell_matrix.extend(Diff::LCS)
     changes = cell_matrix.diff(other_table_cell_matrix).flatten
-    
+
     inserted = 0
     missing  = 0
 
@@ -43,7 +43,7 @@ class Cucumber::Ast::Table
         #change index so we interleave instead
         insert_row_pos = change.position + inserted + 1
         #insert_row_pos = change.position + missing     #original
-        
+
         inserted_row = change.element
         inserted_row.each{|cell| cell.status = :comment}
         cell_matrix.insert(insert_row_pos, inserted_row)
@@ -66,7 +66,7 @@ class Cucumber::Ast::Table
     end
 
     clear_cache!
-    should_raise = 
+    should_raise =
     missing_row_pos && options[:missing_row] ||
     insert_row_pos  && options[:surplus_row] ||
     missing_col     && options[:missing_col] ||
diff --git a/features/support/data.rb b/features/support/data.rb
index dbb0398..7c1ba88 100644
--- a/features/support/data.rb
+++ b/features/support/data.rb
@@ -2,29 +2,22 @@ require 'OSM/objects'       #osmlib gem
 require 'OSM/Database'
 require 'builder'
 
-OSM_USER = 'osrm'
-OSM_GENERATOR = 'osrm-test'
-OSM_UID = 1
-TEST_FOLDER = 'test'
-DATA_FOLDER = 'cache'
-PREPROCESS_LOG_FILE = 'preprocessing.log'
-LOG_FILE = 'fail.log'
-OSM_TIMESTAMP = '2000-00-00T00:00:00Z'
-DEFAULT_SPEEDPROFILE = 'bicycle'
-WAY_SPACING = 100
-DEFAULT_GRID_SIZE = 100   #meters
-PROFILES_PATH = '../profiles'
-BIN_PATH = '../build'
-
-ORIGIN = [1,1]
-
 class Location
-    attr_accessor :lon,:lat
-        
-    def initialize lon,lat
-        @lat = lat
-        @lon = lon
-    end
+  attr_accessor :lon,:lat
+
+  def initialize lon,lat
+    @lat = lat
+    @lon = lon
+  end
+end
+
+def set_input_format format
+  raise '*** Input format must be eiter "osm" or "pbf"' unless ['pbf','osm'].include? format.to_s
+  @input_format = format.to_s
+end
+
+def input_format
+  @input_format || DEFAULT_INPUT_FORMAT
 end
 
 def sanitized_scenario_title
@@ -38,22 +31,26 @@ def set_grid_size meters
   @zoom = meters.to_f*0.8990679362704610899694577444566908445396483347536032203503E-5
 end
 
+def set_origin origin
+  @origin = origin
+end
+
 def build_ways_from_table table
   #add one unconnected way for each row
   table.hashes.each_with_index do |row,ri|
     #NOTE:
     #currently osrm crashes when processing an isolated oneway with just 2 nodes, so we use 4 edges
     #this is relatated to the fact that a oneway dead-end street doesn't make a lot of sense
-    
+
     #if we stack ways on different x coordinates, routability tests get messed up, because osrm might pick a neighboring way if the one test can't be used.
     #instead we place all lines as a string on the same y coordinate. this prevents using neightboring ways.
-    
+
     #a few nodes...
-    node1 = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, ORIGIN[0]+(0+WAY_SPACING*ri)*@zoom, ORIGIN[1] 
-    node2 = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, ORIGIN[0]+(1+WAY_SPACING*ri)*@zoom, ORIGIN[1] 
-    node3 = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, ORIGIN[0]+(2+WAY_SPACING*ri)*@zoom, ORIGIN[1] 
-    node4 = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, ORIGIN[0]+(3+WAY_SPACING*ri)*@zoom, ORIGIN[1] 
-    node5 = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, ORIGIN[0]+(4+WAY_SPACING*ri)*@zoom, ORIGIN[1] 
+    node1 = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, @origin[0]+(0+WAY_SPACING*ri)*@zoom, @origin[1]
+    node2 = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, @origin[0]+(1+WAY_SPACING*ri)*@zoom, @origin[1]
+    node3 = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, @origin[0]+(2+WAY_SPACING*ri)*@zoom, @origin[1]
+    node4 = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, @origin[0]+(3+WAY_SPACING*ri)*@zoom, @origin[1]
+    node5 = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, @origin[0]+(4+WAY_SPACING*ri)*@zoom, @origin[1]
     node1.uid = OSM_UID
     node2.uid = OSM_UID
     node3.uid = OSM_UID
@@ -70,7 +67,7 @@ def build_ways_from_table table
     osm_db << node3
     osm_db << node4
     osm_db << node5
-    
+
     #...with a way between them
     way = OSM::Way.new make_osm_id, OSM_USER, OSM_TIMESTAMP
     way.uid = OSM_UID
@@ -79,22 +76,22 @@ def build_ways_from_table table
     way << node3
     way << node4
     way << node5
-    
+
     tags = row.dup
-    
+
     # remove tags that describe expected test result
     tags.reject! do |k,v|
-      k =~ /^forw\b/ || 
+      k =~ /^forw\b/ ||
       k =~ /^backw\b/ ||
       k =~ /^bothw\b/
     end
-    
+
     ##remove empty tags
     tags.reject! { |k,v| v=='' }
-    
+
     # sort tag keys in the form of 'node/....'
     way_tags = { 'highway' => 'primary' }
-    
+
     node_tags = {}
     tags.each_pair do |k,v|
       if k =~ /node\/(.*)/
@@ -111,39 +108,39 @@ def build_ways_from_table table
         end
       end
     end
-    
+
     way_tags['name'] = "w#{ri}"
     way << way_tags
     node3 << node_tags
-    
+
     osm_db << way
   end
 end
 
 def table_coord_to_lonlat ci,ri
-    [ORIGIN[0]+ci*@zoom, ORIGIN[1]-ri*@zoom]
+  [@origin[0]+ci*@zoom, @origin[1]-ri*@zoom]
 end
 
 def add_osm_node name,lon,lat
-    node = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, lon, lat
-    node << { :name => name }
-    node.uid = OSM_UID
-    osm_db << node
-    name_node_hash[name] = node
+  node = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, lon, lat
+  node << { :name => name }
+  node.uid = OSM_UID
+  osm_db << node
+  name_node_hash[name] = node
 end
 
 def add_location name,lon,lat
-    location_hash[name] = Location.new(lon,lat)
+  location_hash[name] = Location.new(lon,lat)
 end
 
 def find_node_by_name s
-    raise "***invalid node name '#{s}', must be single characters" unless s.size == 1
-    raise "*** invalid node name '#{s}', must be alphanumeric" unless s.match /[a-z0-9]/
-    if s.match /[a-z]/
-        from_node = name_node_hash[ s.to_s ]
-    else
-        from_node = location_hash[ s.to_s ]
-    end
+  raise "***invalid node name '#{s}', must be single characters" unless s.size == 1
+  raise "*** invalid node name '#{s}', must be alphanumeric" unless s.match /[a-z0-9]/
+  if s.match /[a-z]/
+    from_node = name_node_hash[ s.to_s ]
+  else
+    from_node = location_hash[ s.to_s ]
+  end
 end
 
 def find_way_by_name s
@@ -207,7 +204,7 @@ def osm_str
   @osm_str
 end
 
-def write_osm 
+def write_osm
   #write .oms file if needed
   Dir.mkdir DATA_FOLDER unless File.exist? DATA_FOLDER
   @osm_file = "#{DATA_FOLDER}/#{sanitized_scenario_title}_#{fingerprint}"
@@ -220,7 +217,7 @@ def convert_osm_to_pbf
   unless File.exist?("#{@osm_file}.osm.pbf")
     log_preprocess_info
     log "== Converting #{@osm_file}.osm to protobuffer format...", :preprocess
-    unless system "osmosis --read-xml #{@osm_file}.osm --write-pbf #{@osm_file}.osm.pbf omitmetadata=true 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE}"
+    unless system "osmosis --read-xml #{@osm_file}.osm --write-pbf #{@osm_file}.osm.pbf omitmetadata=true >>#{PREPROCESS_LOG_FILE} 2>&1"
       raise OsmosisError.new $?, "osmosis exited with code #{$?.exitstatus}"
     end
     log '', :preprocess
@@ -241,31 +238,44 @@ def write_timestamp
   File.open( "#{@osm_file}.osrm.timestamp", 'w') {|f| f.write(OSM_TIMESTAMP) }
 end
 
-def reprocess
-  use_pbf = true
+def pbf?
+  input_format=='pbf'
+end
+def write_input_data
   Dir.chdir TEST_FOLDER do
     write_osm
     write_timestamp
-    convert_osm_to_pbf if use_pbf
-    unless extracted?
-      log_preprocess_info
-      log "== Extracting #{@osm_file}.osm...", :preprocess
-      unless system "#{BIN_PATH}/osrm-extract #{@osm_file}.osm#{'.pbf' if use_pbf} 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} #{PROFILES_PATH}/#{@profile}.lua"
-        log "*** Exited with code #{$?.exitstatus}.", :preprocess
-        raise ExtractError.new $?.exitstatus, "osrm-extract exited with code #{$?.exitstatus}."
-      end
-      log '', :preprocess
+    convert_osm_to_pbf if pbf?
+  end
+end
+
+def extract_data
+  Dir.chdir TEST_FOLDER do
+    log_preprocess_info
+    log "== Extracting #{@osm_file}.osm...", :preprocess
+    unless system "#{BIN_PATH}/osrm-extract #{@osm_file}.osm#{'.pbf' if pbf?} --profile #{PROFILES_PATH}/#{@profile}.lua >>#{PREPROCESS_LOG_FILE} 2>&1"
+      log "*** Exited with code #{$?.exitstatus}.", :preprocess
+      raise ExtractError.new $?.exitstatus, "osrm-extract exited with code #{$?.exitstatus}."
     end
-    unless prepared?
-      log_preprocess_info
-      log "== Preparing #{@osm_file}.osm...", :preprocess
-      unless system "#{BIN_PATH}/osrm-prepare #{@osm_file}.osrm #{@osm_file}.osrm.restrictions 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} #{PROFILES_PATH}/#{@profile}.lua"
-        log "*** Exited with code #{$?.exitstatus}.", :preprocess
-        raise PrepareError.new $?.exitstatus, "osrm-prepare exited with code #{$?.exitstatus}."
-      end 
-      log '', :preprocess
+    log '', :preprocess
+  end
+end
+
+def prepare_data
+  Dir.chdir TEST_FOLDER do
+    log_preprocess_info
+    log "== Preparing #{@osm_file}.osm...", :preprocess
+    unless system "#{BIN_PATH}/osrm-prepare #{@osm_file}.osrm  --profile #{PROFILES_PATH}/#{@profile}.lua >>#{PREPROCESS_LOG_FILE} 2>&1"
+      log "*** Exited with code #{$?.exitstatus}.", :preprocess
+      raise PrepareError.new $?.exitstatus, "osrm-prepare exited with code #{$?.exitstatus}."
     end
-    log_preprocess_done
-    write_server_ini
+    log '', :preprocess
   end
 end
+
+def reprocess
+  write_input_data
+  extract_data unless extracted?
+  prepare_data unless prepared?
+  log_preprocess_done
+end
diff --git a/features/support/env.rb b/features/support/env.rb
index 13a0b0c..a6a9ca0 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -1,10 +1,26 @@
 require 'rspec/expectations'
 
 DEFAULT_PORT = 5000
+DEFAULT_TIMEOUT = 2
+
+ROOT_FOLDER = Dir.pwd
+OSM_USER = 'osrm'
+OSM_GENERATOR = 'osrm-test'
+OSM_UID = 1
+TEST_FOLDER = File.join ROOT_FOLDER, 'test'
+DATA_FOLDER = 'cache'
+OSM_TIMESTAMP = '2000-00-00T00:00:00Z'
+DEFAULT_SPEEDPROFILE = 'bicycle'
+WAY_SPACING = 100
+DEFAULT_GRID_SIZE = 100   #meters
+PROFILES_PATH = File.join ROOT_FOLDER, 'profiles'
+BIN_PATH = File.join ROOT_FOLDER, 'build'
+DEFAULT_INPUT_FORMAT = 'osm'
+DEFAULT_ORIGIN = [1,1]
 
 
 puts "Ruby version #{RUBY_VERSION}"
-unless RUBY_VERSION =~ /^1.9/
+unless RUBY_VERSION.to_f >= 1.9
   raise "*** Please upgrade to Ruby 1.9.x to run the OSRM cucumber tests"
 end
 
@@ -16,3 +32,26 @@ else
   puts "Using default port #{OSRM_PORT}"
 end
 
+if ENV["OSRM_TIMEOUT"]
+  OSRM_TIMEOUT = ENV["OSRM_TIMEOUT"].to_i
+  puts "Timeout set to #{OSRM_TIMEOUT}"
+else
+  OSRM_TIMEOUT = DEFAULT_TIMEOUT
+  puts "Using default timeout #{OSRM_TIMEOUT}"
+end
+
+unless File.exists? TEST_FOLDER
+  raise "*** Test folder #{TEST_FOLDER} doesn't exist."
+end
+
+if ENV['OS']=~/Windows.*/ then
+   EXE='.exe'
+   QQ='"'
+else
+   EXE=''
+   QQ=''
+end
+
+AfterConfiguration do |config|
+  clear_log_files
+end
\ No newline at end of file
diff --git a/features/support/exceptions.rb b/features/support/exceptions.rb
index 22a6868..2901bfe 100644
--- a/features/support/exceptions.rb
+++ b/features/support/exceptions.rb
@@ -10,16 +10,23 @@ class OSRMError < StandardError
     @log = log
     @extract = log_tail @log, @lines
   end
-  
+
   def to_s
     "*** #{@msg}\nLast #{@lines} lines from #{@log}:\n#{@extract}\n"
   end
-  
+
   private
-  
+
   def log_tail path, n
-    File.open(path) do |f|
-      return f.tail(n).map { |line| "  > #{line}" }.join "\n"
+    Dir.chdir TEST_FOLDER do
+      expanded = File.expand_path path
+      if File.exists? expanded
+        File.open(expanded) do |f|
+          return f.tail(n).map { |line| "    #{line}" }.join "\n"
+        end
+      else
+        return "File '#{expanded} does not exist!"
+      end
     end
   end
 end
diff --git a/features/support/file.rb b/features/support/file.rb
index cd8fd14..dfaae0a 100644
--- a/features/support/file.rb
+++ b/features/support/file.rb
@@ -1,22 +1,34 @@
 class File
-  
-  #read last n lines of a file. useful for getting last part of a big log file.
+
+  # read last n lines of a file (trailing newlines are ignored)
   def tail(n)
+    return [] if size==0
     buffer = 1024
-    idx = (size - buffer).abs
-    chunks = []
-    lines = 0
+    str = nil
 
-    begin
-      seek(idx)
-      chunk = read(buffer)
-      lines += chunk.count("\n")
-      chunks.unshift chunk
-      idx -= buffer
-    end while lines < ( n + 1 ) && pos != 0
+    if size>buffer
+      chunks = []
+      lines = 0
+      idx = size
+      begin
+        idx -= buffer     # rewind
+        if idx<0
+          buffer += idx   # adjust last read to avoid negative index
+          idx = 0
+        end
+        seek(idx)
+        chunk = read(buffer)
+        chunk.gsub!(/\n+\Z/,"") if chunks.empty? # strip newlines from end of file (first chunk)
+        lines += chunk.count("\n")  # update total lines found
+        chunks.unshift chunk        # prepend
+      end while lines<(n) && idx>0  # stop when enough lines found or no more to read
+      str = chunks.join('')
+    else
+      str = read(buffer)
+    end
 
-    tail_of_file = chunks.join('')
-    ary = tail_of_file.split(/\n/)
-    lines_to_return = ary[ ary.size - n, ary.size - 1 ]
+    # return last n lines of str
+    lines = str.split("\n")
+    lines.size>=n ? lines[-n,n] : lines
   end
 end
\ No newline at end of file
diff --git a/features/support/fuzzy.rb b/features/support/fuzzy.rb
index 611d1ef..066d9c5 100644
--- a/features/support/fuzzy.rb
+++ b/features/support/fuzzy.rb
@@ -1,14 +1,17 @@
-
 class FuzzyMatch
 
   def self.match got, want
     if got == want
       return true
     elsif want.match /(.*)\s+~(.+)%$/       #percentage range: 100 ~5%
-      margin = 1 - $2.to_f*0.01
-      from = $1.to_f*margin
-      to = $1.to_f/margin
-      return got.to_f >= from && got.to_f <= to
+      target = $1.to_f
+      percentage = $2.to_f
+      if target==0
+        return true
+      else
+        ratio = (1-(got.to_f / target)).abs;
+        return 100*ratio < percentage;
+      end
     elsif want.match /(.*)\s+\+\-(.+)$/    #absolute range: 100 +-5
       margin = $2.to_f
       from = $1.to_f-margin
@@ -18,13 +21,12 @@ class FuzzyMatch
       return got =~ /#{$1}/
     else
       return false
-    end      
+    end
   end
-  
+
   def self.match_location got, want
     match( got[0], "#{want.lat} ~0.0025%" ) &&
     match( got[1], "#{want.lon} ~0.0025%" )
   end
-  
-end
 
+end
diff --git a/features/support/hash.rb b/features/support/hash.rb
index e37a6f2..197cd42 100644
--- a/features/support/hash.rb
+++ b/features/support/hash.rb
@@ -1,10 +1,13 @@
 require 'digest/sha1'
 
+bin_extract_hash = nil
+profile_hashes = nil
+
 def hash_of_files paths
   paths = [paths] unless paths.is_a? Array
   hash = Digest::SHA1.new
   for path in paths do
-    open(path,'r') do |io|
+    open(path,'rb') do |io|
       while !io.eof
         buf = io.readpartial 1024
         hash.update buf
@@ -16,8 +19,8 @@ end
 
 
 def profile_hash
-  @@profile_hashes ||= {}
-  @@profile_hashes[@profile] ||= hash_of_files "#{PROFILES_PATH}/#{@profile}.lua"
+  profile_hashes ||= {}
+  profile_hashes[@profile] ||= hash_of_files "#{PROFILES_PATH}/#{@profile}.lua"
 end
 
 def osm_hash
@@ -29,19 +32,18 @@ def lua_lib_hash
 end
 
 def bin_extract_hash
-  @@bin_extract_hash ||= hash_of_files "#{BIN_PATH}/osrm-extract"
+  bin_extract_hash ||= hash_of_files "#{BIN_PATH}/osrm-extract#{EXE}"
 end
 
 def bin_prepare_hash
-  @@bin_prepare_hash ||= hash_of_files "#{BIN_PATH}/osrm-prepare"
+  bin_prepare_hash ||= hash_of_files "#{BIN_PATH}/osrm-prepare#{EXE}"
 end
 
 def bin_routed_hash
-  @@bin_routed_hash ||= hash_of_files "#{BIN_PATH}/osrm-routed"
+  bin_routed_hash ||= hash_of_files "#{BIN_PATH}/osrm-routed#{EXE}"
 end
 
 #combine state of data, profile and binaries into a hash that identifies the exact test scenario
 def fingerprint
   @fingerprint ||= Digest::SHA1.hexdigest "#{bin_extract_hash}-#{bin_prepare_hash}-#{bin_routed_hash}-#{profile_hash}-#{lua_lib_hash}-#{osm_hash}"
 end
-
diff --git a/features/support/hooks.rb b/features/support/hooks.rb
index 41f9b3d..4c58a17 100644
--- a/features/support/hooks.rb
+++ b/features/support/hooks.rb
@@ -2,16 +2,33 @@
 STRESS_TIMEOUT = 300
 
 Before do |scenario|
-  @scenario_title = scenario.title
+  # feature name
+  case scenario
+    when Cucumber::Ast::Scenario
+      @feature_name = scenario.feature.name
+    when Cucumber::Ast::OutlineTable::ExampleRow
+      @feature_name = scenario.scenario_outline.feature.name
+  end
+
+  # scenario name
+  case scenario
+    when Cucumber::Ast::Scenario
+      @scenario_title = scenario.name
+    when Cucumber::Ast::OutlineTable::ExampleRow
+      @scenario_title = scenario.scenario_outline.name
+  end
+
+
   @scenario_time = Time.now.strftime("%Y-%m-%dT%H:%m:%SZ")
   reset_data
   @has_logged_preprocess_info = false
   @has_logged_scenario_info = false
   set_grid_size DEFAULT_GRID_SIZE
+  set_origin DEFAULT_ORIGIN
 end
 
 Around('@stress') do |scenario, block|
- Timeout.timeout(STRESS_TIMEOUT) do
+  Timeout.timeout(STRESS_TIMEOUT) do
     block.call
   end
 end
diff --git a/features/support/launch.rb b/features/support/launch.rb
index e4252d8..e55867a 100644
--- a/features/support/launch.rb
+++ b/features/support/launch.rb
@@ -1,12 +1,17 @@
 require 'socket'
 require 'open3'
 
-LAUNCH_TIMEOUT = 2
-SHUTDOWN_TIMEOUT = 2
+if ENV['OS']==/Windows.*/ then
+  TERMSIGNAL='TERM'
+else
+  TERMSIGNAL=9
+end
+
 OSRM_ROUTED_LOG_FILE = 'osrm-routed.log'
 
-class OSRMLauncher
-  def initialize &block
+class OSRMBackgroundLauncher
+  def initialize input_file, &block
+    @input_file = input_file
     Dir.chdir TEST_FOLDER do
       begin
         launch
@@ -18,42 +23,49 @@ class OSRMLauncher
   end
 
   private
-  
+
   def launch
-    Timeout.timeout(LAUNCH_TIMEOUT) do
+    Timeout.timeout(OSRM_TIMEOUT) do
       osrm_up
       wait_for_connection
     end
   rescue Timeout::Error
     raise RoutedError.new "Launching osrm-routed timed out."
   end
-  
+
   def shutdown
-    Timeout.timeout(SHUTDOWN_TIMEOUT) do
+    Timeout.timeout(OSRM_TIMEOUT) do
       osrm_down
     end
   rescue Timeout::Error
     kill
     raise RoutedError.new "Shutting down osrm-routed timed out."
   end
-  
-  
+
+
   def osrm_up?
     if @pid
-      `ps -o state -p #{@pid}`.split[1].to_s =~ /^[DRST]/
-    else
-      false
+      begin
+        if Process.waitpid(@pid, Process::WNOHANG) then
+           false
+        else
+           true
+        end
+      rescue Errno::ESRCH, Errno::ECHILD
+        false
+      end
     end
   end
 
   def osrm_up
     return if osrm_up?
-    @pid = Process.spawn(["#{BIN_PATH}/osrm-routed",''],:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE)
+    @pid = Process.spawn("#{BIN_PATH}/osrm-routed #{@input_file} --port #{OSRM_PORT}",:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE)
+    Process.detach(@pid)    # avoid zombie processes
   end
 
   def osrm_down
     if @pid
-      Process.kill 'TERM', @pid
+      Process.kill TERMSIGNAL, @pid
       wait_for_shutdown
     end
   end
@@ -67,7 +79,7 @@ class OSRMLauncher
   def wait_for_connection
     while true
       begin
-        socket = TCPSocket.new('localhost', OSRM_PORT)
+        socket = TCPSocket.new('127.0.0.1', OSRM_PORT)
         return
       rescue Errno::ECONNREFUSED
         sleep 0.1
diff --git a/features/support/nearest.rb b/features/support/locate.rb
similarity index 66%
copy from features/support/nearest.rb
copy to features/support/locate.rb
index e371307..9007247 100644
--- a/features/support/nearest.rb
+++ b/features/support/locate.rb
@@ -1,9 +1,9 @@
 require 'net/http'
 
-def request_nearest_url path
+def request_locate_url path
   @query = path
   uri = URI.parse "#{HOST}/#{path}"
-  Timeout.timeout(REQUEST_TIMEOUT) do
+  Timeout.timeout(OSRM_TIMEOUT) do
     Net::HTTP.get_response uri
   end
 rescue Errno::ECONNREFUSED => e
@@ -12,6 +12,6 @@ rescue Timeout::Error
   raise "*** osrm-routed did not respond."
 end
 
-def request_nearest a
-  request_nearest_url "nearest?loc=#{a}"
+def request_locate a
+  request_locate_url "locate?loc=#{a}"
 end
diff --git a/features/support/log.rb b/features/support/log.rb
index 7aed850..e5d34cc 100644
--- a/features/support/log.rb
+++ b/features/support/log.rb
@@ -1,3 +1,19 @@
+# logging
+
+PREPROCESS_LOG_FILE = 'preprocessing.log'
+LOG_FILE = 'fail.log'
+
+
+def clear_log_files
+  Dir.chdir TEST_FOLDER do
+    # emptying existing files, rather than deleting and writing new ones makes it 
+    # easier to use tail -f from the command line
+    `echo '' > #{OSRM_ROUTED_LOG_FILE}`
+    `echo '' > #{PREPROCESS_LOG_FILE}`
+    `echo '' > #{LOG_FILE}`
+  end
+end
+
 def log s='', type=nil
   if type == :preprocess
     file = PREPROCESS_LOG_FILE
@@ -24,17 +40,20 @@ def log_scenario_fail_info
   @has_logged_scenario_info = true
 end
 
-def log_fail expected,actual,failed
+def log_fail expected,got,attempts
   log_scenario_fail_info
   log "== "
   log "Expected: #{expected}"
-  log "Got:      #{actual}"
+  log "Got:      #{got}"
   log
-  failed.each do |fail|
-    log "Attempt: #{fail[:attempt]}"
-    log "Query: #{fail[:query]}"
-    log "Response: #{fail[:response].body}"
-    log
+  ['route','forw','backw'].each do |direction|
+    if attempts[direction]
+      attempts[direction]
+      log "Direction: #{direction}"
+      log "Query: #{attempts[direction][:query]}"
+      log "Response: #{attempts[direction][:response].body}"
+      log
+    end
   end
 end
 
@@ -63,5 +82,3 @@ end
 
 def log_preprocess_done
 end
-
-
diff --git a/features/support/nearest.rb b/features/support/nearest.rb
index e371307..77fc351 100644
--- a/features/support/nearest.rb
+++ b/features/support/nearest.rb
@@ -3,7 +3,7 @@ require 'net/http'
 def request_nearest_url path
   @query = path
   uri = URI.parse "#{HOST}/#{path}"
-  Timeout.timeout(REQUEST_TIMEOUT) do
+  Timeout.timeout(OSRM_TIMEOUT) do
     Net::HTTP.get_response uri
   end
 rescue Errno::ECONNREFUSED => e
diff --git a/features/support/osm_parser.rb b/features/support/osm_parser.rb
index ea4e9bd..1da7c73 100644
--- a/features/support/osm_parser.rb
+++ b/features/support/osm_parser.rb
@@ -1,23 +1,25 @@
 require 'OSM/StreamParser'
 
+locations = nil
+
 class OSMTestParserCallbacks < OSM::Callbacks
-  @@locations = nil
-  
+  locations = nil
+
   def self.locations
-    if @@locations
-      @@locations
+    if locations
+      locations
     else
-      #parse the test file, so we can later reference nodes and ways by name in tests 
-      @@locations = {}
+      #parse the test file, so we can later reference nodes and ways by name in tests
+      locations = {}
       file = 'test/data/test.osm'
       callbacks = OSMTestParserCallbacks.new
       parser = OSM::StreamParser.new(:filename => file, :callbacks => callbacks)
       parser.parse
-      puts @@locations
+      puts locations
     end
   end
 
   def node(node)
-    @@locations[node.name] = [node.lat,node.lon]
+    locations[node.name] = [node.lat,node.lon]
   end
 end
\ No newline at end of file
diff --git a/features/support/route.rb b/features/support/route.rb
index 9cfbbfa..745edc0 100644
--- a/features/support/route.rb
+++ b/features/support/route.rb
@@ -1,7 +1,6 @@
 require 'net/http'
 
-HOST = "http://localhost:#{OSRM_PORT}"
-REQUEST_TIMEOUT = 1
+HOST = "http://127.0.0.1:#{OSRM_PORT}"
 DESTINATION_REACHED = 15      #OSRM instruction code
 
 class Hash
@@ -17,7 +16,20 @@ def request_path path, waypoints=[], options={}
   params = (locs + options.to_param).join('&')
   params = nil if params==""
   uri = URI.parse ["#{HOST}/#{path}", params].compact.join('?')
-  Timeout.timeout(REQUEST_TIMEOUT) do
+  @query = uri.to_s
+  Timeout.timeout(OSRM_TIMEOUT) do
+    Net::HTTP.get_response uri
+  end
+rescue Errno::ECONNREFUSED => e
+  raise "*** osrm-routed is not running."
+rescue Timeout::Error
+  raise "*** osrm-routed did not respond."
+end
+
+def request_url path
+  uri = URI.parse"#{HOST}/#{path}"
+  @query = uri.to_s
+  Timeout.timeout(OSRM_TIMEOUT) do
     Net::HTTP.get_response uri
   end
 rescue Errno::ECONNREFUSED => e
@@ -31,26 +43,6 @@ def request_route waypoints, params={}
   request_path "viaroute", waypoints, defaults.merge(params)
 end
 
-def parse_response response
-  if response.code == "200" && response.body.empty? == false
-    json = JSON.parse response.body
-    if json['status'] == 0
-      route = way_list json['route_instructions']
-      if route.empty?
-        "Empty route: #{json['route_instructions']}"
-      else
-        "Route: #{route}"
-      end
-    elsif json['status'] == 207
-      "No route"
-    else
-      "Status: #{json['status']}"
-    end
-  else
-    "HTTP: #{response.code}"
-  end
-end
-
 def got_route? response
   if response.code == "200" && !response.body.empty?
     json = JSON.parse response.body
@@ -80,56 +72,67 @@ def route_status response
   end
 end
 
+def extract_instruction_list instructions, index, postfix=nil
+  if instructions
+    instructions.reject { |r| r[0].to_s=="#{DESTINATION_REACHED}" }.
+    map { |r| r[index] }.
+    map { |r| (r=="" || r==nil) ? '""' : "#{r}#{postfix}" }.
+    join(',')
+  end
+end
+
 def way_list instructions
-  instructions.reject { |r| r[0].to_s=="#{DESTINATION_REACHED}" }.
-  map { |r| r[1] }.
-  map { |r| r=="" ? '""' : r }.
-  join(',')
+  extract_instruction_list instructions, 1
 end
 
 def compass_list instructions
-  instructions.reject { |r| r[0].to_s=="#{DESTINATION_REACHED}" }.
-  map { |r| r[6] }.
-  map { |r| r=="" ? '""' : r }.
-  join(',')
+  extract_instruction_list instructions, 6
 end
 
 def bearing_list instructions
-  instructions.reject { |r| r[0].to_s=="#{DESTINATION_REACHED}" }.
-  map { |r| r[7] }.
-  map { |r| r=="" ? '""' : r }.
-  join(',')
+  extract_instruction_list instructions, 7
 end
 
 def turn_list instructions
-  types = {
-    0 => :none,
-    1 => :straight,
-    2 => :slight_right,
-    3 => :right,
-    4 => :sharp_right,
-    5 => :u_turn,
-    6 => :sharp_left,
-    7 => :left,
-    8 => :slight_left,
-    9 => :via,
-    10 => :head,
-    11 => :enter_roundabout,
-    12 => :leave_roundabout,
-    13 => :stay_roundabout,
-    14 => :start_end_of_street,
-    15 => :destination,
-    16 => :enter_contraflow,
-    17 => :leave_contraflow
-  }
-  instructions.
-  map { |r| types[r[0].to_i].to_s }.
-  join(',')
+  if instructions
+    types = {
+      0 => :none,
+      1 => :straight,
+      2 => :slight_right,
+      3 => :right,
+      4 => :sharp_right,
+      5 => :u_turn,
+      6 => :sharp_left,
+      7 => :left,
+      8 => :slight_left,
+      9 => :via,
+      10 => :head,
+      11 => :enter_roundabout,
+      12 => :leave_roundabout,
+      13 => :stay_roundabout,
+      14 => :start_end_of_street,
+      15 => :destination,
+      16 => :enter_contraflow,
+      17 => :leave_contraflow
+    }
+    # replace instructions codes with strings
+    # "11-3" (enter roundabout and leave a 3rd exit) gets converted to "enter_roundabout-3"
+    instructions.map do |r|
+      r[0].to_s.gsub(/^\d*/) do |match|
+        types[match.to_i].to_s
+      end
+    end.join(',')
+  end
 end
 
 def mode_list instructions
-  instructions.reject { |r| r[0].to_s=="#{DESTINATION_REACHED}" }.
-  map { |r| r[8] }.
-  map { |r| (r=="" || r==nil) ? '""' : r }.
-  join(',')
-end
\ No newline at end of file
+  extract_instruction_list instructions, 8
+end
+
+def time_list instructions
+  extract_instruction_list instructions, 4, "s"
+end
+
+def distance_list instructions
+  extract_instruction_list instructions, 2, "m"
+end
diff --git a/features/support/run.rb b/features/support/run.rb
new file mode 100644
index 0000000..794050a
--- /dev/null
+++ b/features/support/run.rb
@@ -0,0 +1,18 @@
+def run_bin bin, options
+  Dir.chdir TEST_FOLDER do
+    opt = options.dup
+    
+    if opt.include? '{base}'
+      raise "*** {base} is missing" unless @osm_file
+      opt.gsub! "{base}", "#{@osm_file}" 
+    end
+
+    if opt.include? '{profile}'
+      opt.gsub! "{profile}", "#{PROFILES_PATH}/#{@profile}.lua" 
+    end
+
+    @stdout = `#{QQ}#{BIN_PATH}/#{bin}#{EXE}#{QQ} #{opt} 2>error.log`
+    @stderr = File.read 'error.log'
+    @exit_code = $?.exitstatus
+  end
+end
\ No newline at end of file
diff --git a/features/testbot/bad.feature b/features/testbot/bad.feature
index 8fb3703..f0f3cfa 100644
--- a/features/testbot/bad.feature
+++ b/features/testbot/bad.feature
@@ -1,86 +1,86 @@
 @routing @bad
 Feature: Handle bad data in a graceful manner
-	
-	Background:
-		Given the profile "testbot"
 
-	Scenario: Empty dataset
-		Given the node map
-		 |  |
+    Background:
+        Given the profile "testbot"
 
-		Given the ways
-		 | nodes |
-		
-		When I preprocess data
-		Then "osrm-extract" should return code 255
+    Scenario: Empty dataset
+        Given the node map
+            |  |
 
-	Scenario: Only dead-end oneways
-		Given the node map
-		 | a | b | c | d | e |
+        Given the ways
+            | nodes |
 
-		Given the ways
-		 | nodes | oneway |
-		 | abcde | yes    |
+        When the data has been prepared
+        Then "osrm-extract" should return code 1
+
+    Scenario: Only dead-end oneways
+        Given the node map
+            | a | b | c | d | e |
+
+        Given the ways
+            | nodes | oneway |
+            | abcde | yes    |
+
+        When I route I should get
+            | from | to | route |
+            | b    | d  | abcde |
 
-		When I route I should get
-		 | from | to | route |
-		 | b    | d  | abcde |
-    
     @todo
-	Scenario: Start/end point at the same location
-		Given the node map
-		 | a | b |
-		 | 1 | 2 |
+    Scenario: Start/end point at the same location
+        Given the node map
+            | a | b |
+            | 1 | 2 |
 
-		Given the ways
-		 | nodes |
-		 | ab    |
+        Given the ways
+            | nodes |
+            | ab    |
 
-		When I route I should get
-		 | from | to | route |
-		 | a    | a  |       |
-		 | b    | b  |       |
-		 | 1    | 1  |       |
-		 | 2    | 2  |       |
+        When I route I should get
+            | from | to | route |
+            | a    | a  |       |
+            | b    | b  |       |
+            | 1    | 1  |       |
+            | 2    | 2  |       |
 
-	@poles
-	Scenario: Routing close to the north/south pole
-	Mercator is undefined close to the poles.
-	All nodes and request with latitude to close to either of the poles should therefore be ignored.
+    @poles
+    Scenario: Routing close to the north/south pole
+    # Mercator is undefined close to the poles.
+    # All nodes and request with latitude to close to either of the poles should therefore be ignored.
 
-		Given the node locations
-		 | node | lat | lon |
-		 | a    | 89  | 0   |
-		 | b    | 87  | 0   |
-		 | c    | 82  | 0   |
-		 | d    | 80  | 0   |
-		 | e    | 78  | 0   |
-		 | k    | -78 | 0   |
-		 | l    | -80 | 0   |
-		 | m    | -82 | 0   |
-#		 | n    | -87 | 0   |
-#		 | o    | -89 | 0   |
+        Given the node locations
+            | node | lat | lon |
+            | a    | 89  | 0   |
+            | b    | 87  | 0   |
+            | c    | 82  | 0   |
+            | d    | 80  | 0   |
+            | e    | 78  | 0   |
+            | k    | -78 | 0   |
+            | l    | -80 | 0   |
+            | m    | -82 | 0   |
+        # | n    | -87 | 0   |
+        # | o    | -89 | 0   |
 
-		And the ways
-		 | nodes |
-#		 | ab    |
-		 | bc    |
-		 | cd    |
-		 | de    |
-		 | kl    |
-		 | lm    |
-#		 | mn    |
-#		 | no    |
+        And the ways
+            | nodes |
+        # | ab    |
+            | bc    |
+            | cd    |
+            | de    |
+            | kl    |
+            | lm    |
+        # | mn    |
+        # | no    |
 
-		When I route I should get
-		 | from | to | route |
-#		 | a    | b  | cd    |
-#		 | b    | c  | cd    |
-#		 | a    | d  | cd    |
-#		 | c    | d  | cd    |
-		 | d    | e  | de    |
-#		 | k    | l  | kl    |
-#		 | l    | m  | lm    |
-#		 | o    | l  | lm    |
-#		 | n    | m  | lm    |
-#		 | o    | n  | lm    |
+        When I route I should get
+            | from | to | route |
+        # | a    | b  | cd    |
+        # | b    | c  | cd    |
+        # | a    | d  | cd    |
+        # | c    | d  | cd    |
+            | d    | e  | de    |
+        # | k    | l  | kl    |
+        # | l    | m  | lm    |
+        # | o    | l  | lm    |
+        # | n    | m  | lm    |
+        # | o    | n  | lm    |
diff --git a/features/testbot/basic.feature b/features/testbot/basic.feature
index aabdcaa..4164319 100644
--- a/features/testbot/basic.feature
+++ b/features/testbot/basic.feature
@@ -1,272 +1,253 @@
 @routing @basic
 Feature: Basic Routing
-	
-	Background:
-		Given the profile "testbot"
-	
-	@smallest
-	Scenario: A single way with two nodes
-		Given the node map
-		 | a | b |
-	
-		And the ways
-		 | nodes |
-		 | ab    |
-    
-		When I route I should get
-		 | from | to | route |
-		 | a    | b  | ab    |
-		 | b    | a  | ab    |
-		
-	Scenario: Routing in between two nodes of way
-		Given the node map
-		 | a | b | 1 | 2 | c | d |
-		
-		And the ways
-		 | nodes |
-		 | abcd  |
-
-		When I route I should get
-		 | from | to | route |
-		 | 1    | 2  | abcd  |
-		 | 2    | 1  | abcd  |
-
-	Scenario: Routing between the middle nodes of way
-		Given the node map
-		 | a | b | c | d | e | f |
-
-		And the ways
-		 | nodes  |
-		 | abcdef |
-
-		When I route I should get
-		 | from | to | route  |
-		 | b    | c  | abcdef |
-		 | b    | d  | abcdef |
-		 | b    | e  | abcdef |
-		 | c    | b  | abcdef |
-		 | c    | d  | abcdef |
-		 | c    | e  | abcdef |
-		 | d    | b  | abcdef |
-		 | d    | c  | abcdef |
-		 | d    | e  | abcdef |
-		 | e    | b  | abcdef |
-		 | e    | c  | abcdef |
-		 | e    | d  | abcdef |
-
-	Scenario: Two ways connected in a straight line
-		Given the node map
-		 | a | b | c |
-	
-		And the ways
-		 | nodes |
-		 | ab    |
-		 | bc    |
+
+    Background:
+        Given the profile "testbot"
+
+    @smallest
+    Scenario: A single way with two nodes
+        Given the node map
+            | a | b |
+
+        And the ways
+            | nodes |
+            | ab    |
+
+        When I route I should get
+            | from | to | route |
+            | a    | b  | ab    |
+            | b    | a  | ab    |
+
+    Scenario: Routing in between two nodes of way
+        Given the node map
+            | a | b | 1 | 2 | c | d |
+
+        And the ways
+            | nodes |
+            | abcd  |
+
+        When I route I should get
+            | from | to | route |
+            | 1    | 2  | abcd  |
+            | 2    | 1  | abcd  |
+
+    Scenario: Routing between the middle nodes of way
+        Given the node map
+            | a | b | c | d | e | f |
+
+        And the ways
+            | nodes  |
+            | abcdef |
+
+        When I route I should get
+            | from | to | route  |
+            | b    | c  | abcdef |
+            | b    | d  | abcdef |
+            | b    | e  | abcdef |
+            | c    | b  | abcdef |
+            | c    | d  | abcdef |
+            | c    | e  | abcdef |
+            | d    | b  | abcdef |
+            | d    | c  | abcdef |
+            | d    | e  | abcdef |
+            | e    | b  | abcdef |
+            | e    | c  | abcdef |
+            | e    | d  | abcdef |
+
+    Scenario: Two ways connected in a straight line
+        Given the node map
+            | a | b | c |
+
+        And the ways
+            | nodes |
+            | ab    |
+            | bc    |
+
+        When I route I should get
+            | from | to | route |
+            | a    | c  | ab,bc |
+            | c    | a  | bc,ab |
+            | a    | b  | ab    |
+            | b    | a  | ab    |
+            | b    | c  | bc    |
+            | c    | b  | bc    |
+
+    Scenario: 2 unconnected parallel ways
+        Given the node map
+            | a | b | c |
+            | d | e | f |
+
+        And the ways
+            | nodes |
+            | abc   |
+            | def   |
+
+        When I route I should get
+            | from | to | route |
+            | a    | b  | abc   |
+            | b    | a  | abc   |
+            | b    | c  | abc   |
+            | c    | b  | abc   |
+            | d    | e  | def   |
+            | e    | d  | def   |
+            | e    | f  | def   |
+            | f    | e  | def   |
+            | a    | d  |       |
+            | d    | a  |       |
+            | b    | d  |       |
+            | d    | b  |       |
+            | c    | d  |       |
+            | d    | c  |       |
+            | a    | e  |       |
+            | e    | a  |       |
+            | b    | e  |       |
+            | e    | b  |       |
+            | c    | e  |       |
+            | e    | c  |       |
+            | a    | f  |       |
+            | f    | a  |       |
+            | b    | f  |       |
+            | f    | b  |       |
+            | c    | f  |       |
+            | f    | c  |       |
+
+    Scenario: 3 ways connected in a triangle
+        Given the node map
+            | a |   | b |
+            |   |   |   |
+            |   | c |   |
+
+        And the ways
+            | nodes |
+            | ab    |
+            | bc    |
+            | ca    |
+
+        When I route I should get
+            | from | to | route |
+            | a    | b  | ab    |
+            | a    | c  | ca    |
+            | b    | c  | bc    |
+            | b    | a  | ab    |
+            | c    | a  | ca    |
+            | c    | b  | bc    |
+
+    Scenario: 3 connected triangles
+        Given a grid size of 100 meters
+        Given the node map
+            | x | a |   | b | s |
+            | y |   |   |   | t |
+            |   |   | c |   |   |
+            |   | v |   | w |   |
+
+        And the ways
+            | nodes |
+            | ab    |
+            | bc    |
+            | ca    |
+            | ax    |
+            | xy    |
+            | ya    |
+            | bs    |
+            | st    |
+            | tb    |
+            | cv    |
+            | vw    |
+            | wc    |
+
+        When I route I should get
+            | from | to | route |
+            | a    | b  | ab    |
+            | a    | c  | ca    |
+            | b    | c  | bc    |
+            | b    | a  | ab    |
+            | c    | a  | ca    |
+            | c    | b  | bc    |
+
+    Scenario: To ways connected at a 45 degree angle
+        Given the node map
+            | a |   |   |
+            | b |   |   |
+            | c | d | e |
+
+        And the ways
+            | nodes |
+            | abc   |
+            | cde   |
+
+        When I route I should get
+            | from | to | route   |
+            | b    | d  | abc,cde |
+            | a    | e  | abc,cde |
+            | a    | c  | abc     |
+            | c    | a  | abc     |
+            | c    | e  | cde     |
+            | e    | c  | cde     |
+
+    Scenario: Grid city center
+        Given the node map
+            | a | b | c | d |
+            | e | f | g | h |
+            | i | j | k | l |
+            | m | n | o | p |
+
+        And the ways
+            | nodes |
+            | abcd  |
+            | efgh  |
+            | ijkl  |
+            | mnop  |
+            | aeim  |
+            | bfjn  |
+            | cgko  |
+            | dhlp  |
+
+        When I route I should get
+            | from | to | route |
+            | f    | g  | efgh  |
+            | g    | f  | efgh  |
+            | f    | j  | bfjn  |
+            | j    | f  | bfjn  |
+
+    Scenario: Grid city periphery
+        Given the node map
+            | a | b | c | d |
+            | e | f | g | h |
+            | i | j | k | l |
+            | m | n | o | p |
+
+        And the ways
+            | nodes |
+            | abcd  |
+            | efgh  |
+            | ijkl  |
+            | mnop  |
+            | aeim  |
+            | bfjn  |
+            | cgko  |
+            | dhlp  |
+
+        When I route I should get
+            | from | to | route |
+            | a    | d  | abcd  |
+            | d    | a  | abcd  |
+            | a    | m  | aeim  |
+            | m    | a  | aeim  |
     
-		When I route I should get
-		 | from | to | route |
-		 | a    | c  | ab,bc |
-		 | c    | a  | bc,ab |
-		 | a    | b  | ab    |
-		 | b    | a  | ab    |
-		 | b    | c  | bc    |
-		 | c    | b  | bc    |
-		
-	Scenario: 2 unconnected parallel ways
-		Given the node map
-		 | a | b | c |
-		 | d | e | f |
-		
-		And the ways
-		 | nodes |
-		 | abc   |
-		 | def   |
-	    
-		When I route I should get
-		 | from | to | route |
-		 | a    | b  | abc   |
-		 | b    | a  | abc   |
-		 | b    | c  | abc   |
-		 | c    | b  | abc   |
-		 | d    | e  | def   |
-		 | e    | d  | def   |
-		 | e    | f  | def   |
-		 | f    | e  | def   |
-		 | a    | d  |       |
-		 | d    | a  |       |
-		 | b    | d  |       |
-		 | d    | b  |       |
-		 | c    | d  |       |
-		 | d    | c  |       |
-		 | a    | e  |       |
-		 | e    | a  |       |
-		 | b    | e  |       |
-		 | e    | b  |       |
-		 | c    | e  |       |
-		 | e    | c  |       |
-		 | a    | f  |       |
-		 | f    | a  |       |
-		 | b    | f  |       |
-		 | f    | b  |       |
-		 | c    | f  |       |
-		 | f    | c  |       |
-
-	Scenario: 3 ways connected in a triangle
-		Given the node map
-		 | a |   | b |
-		 |   |   |   |
-		 |   | c |   |
-
-		And the ways
-		 | nodes |
-		 | ab    |
-		 | bc    |
-		 | ca    |
-		
-		When I route I should get
-		 | from | to | route |
-		 | a    | b  | ab    |
-		 | a    | c  | ca    |
-		 | b    | c  | bc    |
-		 | b    | a  | ab    |
-		 | c    | a  | ca    |
-		 | c    | b  | bc    |
-
-	Scenario: 3 connected triangles
-		Given a grid size of 100 meters
-		Given the node map
-		 | x | a |   | b | s |
-		 | y |   |   |   | t |
-		 |   |   | c |   |   |
-		 |   | v |   | w |   |
-
-		And the ways
-		 | nodes |
-		 | ab    |
-		 | bc    |
-		 | ca    |
-		 | ax    |
-		 | xy    |
-		 | ya    |
-		 | bs    |
-		 | st    |
-		 | tb    |
-		 | cv    |
-		 | vw    |
-		 | wc    |
-		
-		When I route I should get
-		 | from | to | route |
-		 | a    | b  | ab    |
-		 | a    | c  | ca    |
-		 | b    | c  | bc    |
-		 | b    | a  | ab    |
-		 | c    | a  | ca    |
-		 | c    | b  | bc    |
-
-	Scenario: To ways connected at a 45 degree angle
-		Given the node map
-		 | a |   |   |
-		 | b |   |   |
-		 | c | d | e |
-
-		And the ways
-		 | nodes |
-		 | abc   |
-		 | cde   |
-
-		When I route I should get
-		 | from | to | route   |
-		 | b    | d  | abc,cde |
-		 | a    | e  | abc,cde |
-		 | a    | c  | abc     |
-		 | c    | a  | abc     |
-		 | c    | e  | cde     |
-		 | e    | c  | cde     |
-		
-	Scenario: Grid city center
-		Given the node map
-		 | a | b | c | d |
-		 | e | f | g | h |
-		 | i | j | k | l |
-		 | m | n | o | p |
-
-		And the ways
-		 | nodes |
-		 | abcd  |
-		 | efgh  |
-		 | ijkl  |
-		 | mnop  |
-		 | aeim  |
-		 | bfjn  |
-		 | cgko  |
-		 | dhlp  |
-
-		When I route I should get
-		 | from | to | route |
-		 | f    | g  | efgh  |
-		 | g    | f  | efgh  |
-		 | f    | j  | bfjn  |
-		 | j    | f  | bfjn  |
-
-	Scenario: Grid city periphery
-		Given the node map
-		 | a | b | c | d |
-		 | e | f | g | h |
-		 | i | j | k | l |
-		 | m | n | o | p |
-
-		And the ways
-		 | nodes |
-		 | abcd  |
-		 | efgh  |
-		 | ijkl  |
-		 | mnop  |
-		 | aeim  |
-		 | bfjn  |
-		 | cgko  |
-		 | dhlp  |
-
-		When I route I should get
-		 | from | to | route |
-		 | a    | d  | abcd  |
-		 | d    | a  | abcd  |
-		 | a    | m  | aeim  |
-		 | m    | a  | aeim  |
-
-	Scenario: Routing on a oneway roundabout
-		Given the node map
-		 |   | d | c |   |
-		 | e |   |   | b |
-		 | f |   |   | a |
-		 |   | g | h |   |
-
-		And the ways
-		 | nodes | oneway |
-		 | ab    | yes    |
-		 | bc    | yes    |
-		 | cd    | yes    |
-		 | de    | yes    |
-		 | ef    | yes    |
-		 | fg    | yes    |
-		 | gh    | yes    |
-		 | ha    | yes    |
-
-		When I route I should get
-		 | from | to | route                |
-		 | a    | b  | ab                   |
-		 | b    | c  | bc                   |
-		 | c    | d  | cd                   |
-		 | d    | e  | de                   |
-		 | e    | f  | ef                   |
-		 | f    | g  | fg                   |
-		 | g    | h  | gh                   |
-		 | h    | a  | ha                   |
-		 | b    | a  | bc,cd,de,ef,fg,gh,ha |
-		 | c    | b  | cd,de,ef,fg,gh,ha,ab |
-		 | d    | c  | de,ef,fg,gh,ha,ab,bc |
-		 | e    | d  | ef,fg,gh,ha,ab,bc,cd |
-		 | f    | e  | fg,gh,ha,ab,bc,cd,de |
-		 | g    | f  | gh,ha,ab,bc,cd,de,ef |
-		 | h    | g  | ha,ab,bc,cd,de,ef,fg |
-		 | a    | h  | ab,bc,cd,de,ef,fg,gh |
+    Scenario: Testbot - Triangle challenge
+        Given the node map
+            |   |   |   | d |
+            | a | b | c |   |
+            |   |   |   | e |
+
+        And the ways
+            | nodes | highway | oneway |
+            | abc   | primary |        |
+            | cd    | primary | yes    |
+            | ce    | river   |        |
+            | de    | primary |        |
+
+        When I route I should get
+            | from | to | route |
+            | d    | c  | de,ce |
+            | e    | d  | de    |
diff --git a/features/testbot/bearing.feature b/features/testbot/bearing.feature
index 48ac5bd..c306af9 100644
--- a/features/testbot/bearing.feature
+++ b/features/testbot/bearing.feature
@@ -1,141 +1,211 @@
 @routing @bearing
 Feature: Compass bearing
-	
-	Background:
-		Given the profile "testbot"
-	
-	Scenario: Bearing when going northwest
-		Given the node map
-		 | b |   |
-		 |   | a |
-
-		And the ways
-		 | nodes |
-		 | ab    |
-
-		When I route I should get
-		 | from | to | route | compass | bearing |
-		 | a    | b  | ab    | NW      | 315     |
-
-	Scenario: Bearing when going west
-		Given the node map
-		 | b | a |
-
-		And the ways
-		 | nodes |
-		 | ab    |
-
-		When I route I should get
-		 | from | to | route | compass | bearing |
-		 | a    | b  | ab    | W       | 270     |
-
-	Scenario: Bearing af 45 degree intervals
-		Given the node map
-		 | b | a | h |
-		 | c | x | g |
-		 | d | e | f |
-
-		And the ways
-		 | nodes |
-		 | xa    |
-		 | xb    |
-		 | xc    |
-		 | xd    |
-		 | xe    |
-		 | xf    |
-		 | xg    |
-		 | xh    |
-
-		When I route I should get
-		 | from | to | route | compass | bearing |
-		 | x    | a  | xa    | N       | 0       |
-		 | x    | b  | xb    | NW      | 315     |
-		 | x    | c  | xc    | W       | 270     |
-		 | x    | d  | xd    | SW      | 225     |
-		 | x    | e  | xe    | S       | 180     |
-		 | x    | f  | xf    | SE      | 135     |
-		 | x    | g  | xg    | E       | 90      |
-		 | x    | h  | xh    | NE      | 45      |
-
-	Scenario: Bearing in a roundabout
-		Given the node map
-		 |   | d | c |   |
-		 | e |   |   | b |
-		 | f |   |   | a |
-		 |   | g | h |   |
-
-		And the ways
-		 | nodes | oneway |
-		 | ab    | yes    |
-		 | bc    | yes    |
-		 | cd    | yes    |
-		 | de    | yes    |
-		 | ef    | yes    |
-		 | fg    | yes    |
-		 | gh    | yes    |
-		 | ha    | yes    |
-
-		When I route I should get
-		 | from | to | route                | compass          | bearing                 |
-		 | c    | b  | cd,de,ef,fg,gh,ha,ab | W,SW,S,SE,E,NE,N | 270,225,180,135,90,45,0 |
-		 | g    | f  | gh,ha,ab,bc,cd,de,ef | E,NE,N,NW,W,SW,S | 90,45,0,315,270,225,180 |
-
-	Scenario: Bearing should stay constant when zig-zagging
-		Given the node map
-		 | b | d | f | h |
-		 | a | c | e | g |
-
-		And the ways
-		 | nodes |
-		 | ab    |
-		 | bc    |
-		 | cd    |
-		 | de    |
-		 | ef    |
-		 | fg    |
-		 | gh    |
-
-		When I route I should get
-		 | from | to | route                | compass          | bearing             |
-		 | a    | h  | ab,bc,cd,de,ef,fg,gh | N,SE,N,SE,N,SE,N | 0,135,0,135,0,135,0 |
-	
-	Scenario: Bearings on an east-west way.
-		Given the node map
-		 | a | b | c | d | e | f |
-
-		And the ways
-		 | nodes  |
-		 | abcdef |
-
-		When I route I should get
-		 | from | to | route  | compass | bearing |
-		 | a    | b  | abcdef | E       | 90      |
-		 | a    | c  | abcdef | E       | 90      |
-		 | a    | d  | abcdef | E       | 90      |
-		 | a    | e  | abcdef | E       | 90      |
-		 | a    | f  | abcdef | E       | 90      |
-		 | b    | a  | abcdef | W       | 270     |
-		 | b    | c  | abcdef | E       | 90      |
-		 | b    | d  | abcdef | E       | 90      |
-		 | b    | e  | abcdef | E       | 90      |
-		 | b    | f  | abcdef | E       | 90      |
-		 | c    | a  | abcdef | W       | 270      |
-		 | c    | b  | abcdef | W       | 270     |
-		 | c    | d  | abcdef | E       | 90      |
-		 | c    | e  | abcdef | E       | 90      |
-		 | c    | f  | abcdef | E       | 90      |
-		 | d    | a  | abcdef | W       | 270     |
-		 | d    | b  | abcdef | W       | 270     |
-		 | d    | c  | abcdef | W       | 270     |
-		 | d    | e  | abcdef | E       | 90      |
-		 | d    | f  | abcdef | E       | 90      |
-		 | e    | a  | abcdef | W       | 270     |
-		 | e    | b  | abcdef | W       | 270     |
-		 | e    | c  | abcdef | W       | 270     |
-		 | e    | d  | abcdef | W       | 270     |
-		 | e    | f  | abcdef | E       | 90      |
-		 | f    | a  | abcdef | W       | 270     |
-		 | f    | b  | abcdef | W       | 270     |
-		 | f    | c  | abcdef | W       | 270     |
-		 | f    | d  | abcdef | W       | 270     |
-		 | f    | e  | abcdef | W       | 270     |
\ No newline at end of file
+
+    Background:
+        Given the profile "testbot"
+
+    Scenario: Bearing when going northwest
+        Given the node map
+            | b |   |
+            |   | a |
+
+        And the ways
+            | nodes |
+            | ab    |
+
+        When I route I should get
+            | from | to | route | compass | bearing |
+            | a    | b  | ab    | NW      | 315     |
+
+    Scenario: Bearing when going west
+        Given the node map
+            | b | a |
+
+        And the ways
+            | nodes |
+            | ab    |
+
+        When I route I should get
+            | from | to | route | compass | bearing |
+            | a    | b  | ab    | W       | 270     |
+
+    Scenario: Bearing af 45 degree intervals
+        Given the node map
+            | b | a | h |
+            | c | x | g |
+            | d | e | f |
+
+        And the ways
+            | nodes |
+            | xa    |
+            | xb    |
+            | xc    |
+            | xd    |
+            | xe    |
+            | xf    |
+            | xg    |
+            | xh    |
+
+        When I route I should get
+            | from | to | route | compass | bearing |
+            | x    | a  | xa    | N       | 0       |
+            | x    | b  | xb    | NW      | 315     |
+            | x    | c  | xc    | W       | 270     |
+            | x    | d  | xd    | SW      | 225     |
+            | x    | e  | xe    | S       | 180     |
+            | x    | f  | xf    | SE      | 135     |
+            | x    | g  | xg    | E       | 90      |
+            | x    | h  | xh    | NE      | 45      |
+
+    Scenario: Bearing in a roundabout
+        Given the node map
+            |   | d | c |   |
+            | e |   |   | b |
+            | f |   |   | a |
+            |   | g | h |   |
+
+        And the ways
+            | nodes | oneway |
+            | ab    | yes    |
+            | bc    | yes    |
+            | cd    | yes    |
+            | de    | yes    |
+            | ef    | yes    |
+            | fg    | yes    |
+            | gh    | yes    |
+            | ha    | yes    |
+
+        When I route I should get
+            | from | to | route                | compass          | bearing                 |
+            | c    | b  | cd,de,ef,fg,gh,ha,ab | W,SW,S,SE,E,NE,N | 270,225,180,135,90,45,0 |
+            | g    | f  | gh,ha,ab,bc,cd,de,ef | E,NE,N,NW,W,SW,S | 90,45,0,315,270,225,180 |
+
+    Scenario: Bearing should stay constant when zig-zagging
+        Given the node map
+            | b | d | f | h |
+            | a | c | e | g |
+
+        And the ways
+            | nodes |
+            | ab    |
+            | bc    |
+            | cd    |
+            | de    |
+            | ef    |
+            | fg    |
+            | gh    |
+
+        When I route I should get
+            | from | to | route                | compass          | bearing             |
+            | a    | h  | ab,bc,cd,de,ef,fg,gh | N,SE,N,SE,N,SE,N | 0,135,0,135,0,135,0 |
+
+    Scenario: Bearings on an east-west way.
+        Given the node map
+            | a | b | c | d | e | f |
+
+        And the ways
+            | nodes  |
+            | abcdef |
+
+        When I route I should get
+            | from | to | route  | compass | bearing |
+            | a    | b  | abcdef | E       | 90      |
+            | a    | c  | abcdef | E       | 90      |
+            | a    | d  | abcdef | E       | 90      |
+            | a    | e  | abcdef | E       | 90      |
+            | a    | f  | abcdef | E       | 90      |
+            | b    | a  | abcdef | W       | 270     |
+            | b    | c  | abcdef | E       | 90      |
+            | b    | d  | abcdef | E       | 90      |
+            | b    | e  | abcdef | E       | 90      |
+            | b    | f  | abcdef | E       | 90      |
+            | c    | a  | abcdef | W       | 270     |
+            | c    | b  | abcdef | W       | 270     |
+            | c    | d  | abcdef | E       | 90      |
+            | c    | e  | abcdef | E       | 90      |
+            | c    | f  | abcdef | E       | 90      |
+            | d    | a  | abcdef | W       | 270     |
+            | d    | b  | abcdef | W       | 270     |
+            | d    | c  | abcdef | W       | 270     |
+            | d    | e  | abcdef | E       | 90      |
+            | d    | f  | abcdef | E       | 90      |
+            | e    | a  | abcdef | W       | 270     |
+            | e    | b  | abcdef | W       | 270     |
+            | e    | c  | abcdef | W       | 270     |
+            | e    | d  | abcdef | W       | 270     |
+            | e    | f  | abcdef | E       | 90      |
+            | f    | a  | abcdef | W       | 270     |
+            | f    | b  | abcdef | W       | 270     |
+            | f    | c  | abcdef | W       | 270     |
+            | f    | d  | abcdef | W       | 270     |
+            | f    | e  | abcdef | W       | 270     |
+
+    Scenario: Bearings at high latitudes
+    # The coordinas below was calculated using http://www.movable-type.co.uk/scripts/latlong.html,
+    # to form square with sides of 1 km.
+
+        Given the node locations
+            | node | lat       | lon      |
+            | a    | 80        | 0        |
+            | b    | 80.006389 | 0        |
+            | c    | 80.006389 | 0.036667 |
+            | d    | 80        | 0.036667 |
+
+        And the ways
+            | nodes |
+            | ab    |
+            | bc    |
+            | cd    |
+            | da    |
+            | ac    |
+            | bd    |
+
+        When I route I should get
+            | from | to | route | compass | bearing |
+            | a    | b  | ab    | N       | 0       |
+            | b    | c  | bc    | E       | 90      |
+            | c    | d  | cd    | S       | 180     |
+            | d    | a  | da    | W       | 270     |
+            | b    | a  | ab    | S       | 180     |
+            | c    | b  | bc    | W       | 270     |
+            | d    | c  | cd    | N       | 0       |
+            | a    | d  | da    | E       | 90      |
+            | a    | c  | ac    | NE      | 45      |
+            | c    | a  | ac    | SW      | 225     |
+            | b    | d  | bd    | SE      | 135     |
+            | d    | b  | bd    | NW      | 315     |
+
+    Scenario: Bearings at high negative latitudes
+    # The coordinas below was calculated using http://www.movable-type.co.uk/scripts/latlong.html,
+    # to form square with sides of 1 km.
+
+        Given the node locations
+            | node | lat        | lon      |
+            | a    | -80        | 0        |
+            | b    | -80.006389 | 0        |
+            | c    | -80.006389 | 0.036667 |
+            | d    | -80        | 0.036667 |
+
+        And the ways
+            | nodes |
+            | ab    |
+            | bc    |
+            | cd    |
+            | da    |
+            | ac    |
+            | bd    |
+
+        When I route I should get
+            | from | to | route | compass | bearing |
+            | a    | b  | ab    | S       | 180     |
+            | b    | c  | bc    | E       | 90      |
+            | c    | d  | cd    | N       | 0       |
+            | d    | a  | da    | W       | 270     |
+            | b    | a  | ab    | N       | 0       |
+            | c    | b  | bc    | W       | 270     |
+            | d    | c  | cd    | S       | 180     |
+            | a    | d  | da    | E       | 90      |
+            | a    | c  | ac    | SE      | 135     |
+            | c    | a  | ac    | NW      | 315     |
+            | b    | d  | bd    | NE      | 45      |
+            | d    | b  | bd    | SW      | 225     |
diff --git a/features/testbot/bearing_param.feature b/features/testbot/bearing_param.feature
index 24d329d..e9db873 100644
--- a/features/testbot/bearing_param.feature
+++ b/features/testbot/bearing_param.feature
@@ -1,93 +1,93 @@
 @routing @bearing_param @todo
-Feature: Bearing parameter 
-	
-	Background:
-		Given the profile "testbot"
-	    And a grid size of 10 meters
-	
-	Scenario: Testbot - Intial bearing in simple case
-		Given the node map
-         | a |   |
-         | 0 | c |
-         | b |   |
-		
-		And the ways
-		 | nodes |
-		 | ac    |
-		 | bc    |
+Feature: Bearing parameter
 
-		When I route I should get
-		 | from | to | param:bearing | route | bearing |
-		 | 0    | c  | 0             | bc    | 45      |
-		 | 0    | c  | 45            | bc    | 45      |
-		 | 0    | c  | 85            | bc    | 45      |
-		 | 0    | c  | 95            | ac    | 135     |
-		 | 0    | c  | 135           | ac    | 135     |
-		 | 0    | c  | 180           | ac    | 135     |
-	
- 	Scenario: Testbot - Initial bearing on split way
- 		Given the node map
+    Background:
+        Given the profile "testbot"
+        And a grid size of 10 meters
+
+    Scenario: Testbot - Intial bearing in simple case
+        Given the node map
+            | a |   |
+            | 0 | c |
+            | b |   |
+
+        And the ways
+            | nodes |
+            | ac    |
+            | bc    |
+
+        When I route I should get
+            | from | to | param:bearing | route | bearing |
+            | 0    | c  | 0             | bc    | 45      |
+            | 0    | c  | 45            | bc    | 45      |
+            | 0    | c  | 85            | bc    | 45      |
+            | 0    | c  | 95            | ac    | 135     |
+            | 0    | c  | 135           | ac    | 135     |
+            | 0    | c  | 180           | ac    | 135     |
+
+    Scenario: Testbot - Initial bearing on split way
+        Given the node map
         | d |  |  |  |  | 1 |  |  |  |  | c |
         | a |  |  |  |  | 0 |  |  |  |  | b |
 
- 		And the ways
- 		 | nodes | oneway |
- 		 | ab    | yes    |
- 		 | bc    | yes    |
- 		 | cd    | yes    |
- 		 | da    | yes    |
+        And the ways
+            | nodes | oneway |
+            | ab    | yes    |
+            | bc    | yes    |
+            | cd    | yes    |
+            | da    | yes    |
+
+        When I route I should get
+            | from | to | param:bearing | route    | bearing |
+            | 0    | b  | 10            | ab       | 90      |
+            | 0    | b  | 90            | ab       | 90      |
+            | 0    | b  | 170           | ab       | 90      |
+            | 0    | b  | 190           | cd,da,ab | 270     |
+            | 0    | b  | 270           | cd,da,ab | 270     |
+            | 0    | b  | 350           | cd,da,ab | 270     |
+            | 1    | d  | 10            | cd       | 90      |
+            | 1    | d  | 90            | cd       | 90      |
+            | 1    | d  | 170           | cd       | 90      |
+            | 1    | d  | 190           | ab,bc,cd | 270     |
+            | 1    | d  | 270           | ab,bc,cd | 270     |
+            | 1    | d  | 350           | ab,bc,cd | 270     |
 
- 		When I route I should get
- 		 | from | to | param:bearing | route    | bearing |
- 		 | 0    | b  | 10            | ab       | 90      |
- 		 | 0    | b  | 90            | ab       | 90      |
- 		 | 0    | b  | 170           | ab       | 90      |
- 		 | 0    | b  | 190           | cd,da,ab | 270     |
- 		 | 0    | b  | 270           | cd,da,ab | 270     |
- 		 | 0    | b  | 350           | cd,da,ab | 270     |
- 		 | 1    | d  | 10            | cd       | 90      |
- 		 | 1    | d  | 90            | cd       | 90      |
- 		 | 1    | d  | 170           | cd       | 90      |
- 		 | 1    | d  | 190           | ab,bc,cd | 270     |
- 		 | 1    | d  | 270           | ab,bc,cd | 270     |
- 		 | 1    | d  | 350           | ab,bc,cd | 270     |
+    Scenario: Testbot - Initial bearing in all direction
+        Given the node map
+            | h |  |   | a |   |  | b |
+            |   |  |   |   |   |  |   |
+            |   |  | p | i | j |  |   |
+            | g |  | o | 0 | k |  | c |
+            |   |  | n | m | l |  |   |
+            |   |  |   |   |   |  |   |
+            | f |  |   | e |   |  | d |
 
- 	Scenario: Testbot - Initial bearing in all direction
-		Given the node map
-         | h |  |   | a |   |  | b |
-         |   |  |   |   |   |  |   |
-         |   |  | p | i | j |  |   |
-         | g |  | o | 0 | k |  | c |
-         |   |  | n | m | l |  |   |
-         |   |  |   |   |   |  |   |
-         | f |  |   | e |   |  | d |
-		
-		And the ways
-		 | nodes | oneway |
-		 | ia    | yes    |
-		 | jb    | yes    |
-		 | kc    | yes    |
-		 | ld    | yes    |
-		 | me    | yes    |
-		 | nf    | yes    |
-		 | og    | yes    |
-		 | ph    | yes    |
-		 | ab    | yes    |
-		 | bc    | yes    |
-		 | cd    | yes    |
-		 | de    | yes    |
-		 | ef    | yes    |
-		 | fg    | yes    |
-		 | gh    | yes    |
-		 | ha    | yes    |
+        And the ways
+            | nodes | oneway |
+            | ia    | yes    |
+            | jb    | yes    |
+            | kc    | yes    |
+            | ld    | yes    |
+            | me    | yes    |
+            | nf    | yes    |
+            | og    | yes    |
+            | ph    | yes    |
+            | ab    | yes    |
+            | bc    | yes    |
+            | cd    | yes    |
+            | de    | yes    |
+            | ef    | yes    |
+            | fg    | yes    |
+            | gh    | yes    |
+            | ha    | yes    |
 
-		When I route I should get
-		 | from | to | param:bearing | route                   | bearing |
-		 | 0    | a  | 0             | ia                      | 0       |
-		 | 0    | a  | 45            | jb,bc,cd,de,ef,fg,gh,ha | 45      |
-		 | 0    | a  | 90            | kc,cd,de,ef,fg,gh,ha    | 90      |
-		 | 0    | a  | 135           | ld,de,ef,fg,gh,ha       | 135     |
-		 | 0    | a  | 180           | me,de,ef,fg,gh,ha       | 180     |
-		 | 0    | a  | 225           | nf,ef,fg,gh,ha          | 225     |
-		 | 0    | a  | 270           | og,gh,ha                | 270     |
-		 | 0    | a  | 315           | pn,ha                   | 315     |
+        When I route I should get
+            | from | to | param:bearing | route                   | bearing |
+            | 0    | a  | 0             | ia                      | 0       |
+            | 0    | a  | 45            | jb,bc,cd,de,ef,fg,gh,ha | 45      |
+            | 0    | a  | 90            | kc,cd,de,ef,fg,gh,ha    | 90      |
+            | 0    | a  | 135           | ld,de,ef,fg,gh,ha       | 135     |
+            | 0    | a  | 180           | me,de,ef,fg,gh,ha       | 180     |
+            | 0    | a  | 225           | nf,ef,fg,gh,ha          | 225     |
+            | 0    | a  | 270           | og,gh,ha                | 270     |
+            | 0    | a  | 315           | pn,ha                   | 315     |
diff --git a/features/testbot/bug.feature b/features/testbot/bug.feature
deleted file mode 100644
index 6eb1349..0000000
--- a/features/testbot/bug.feature
+++ /dev/null
@@ -1,23 +0,0 @@
- at routing @testbot @bug @todo
-Feature: Testbot - Things that looks like bugs
-
-	Background:
-		Given the profile "testbot"
-    
-    Scenario: Testbot - Triangle problem
-    	Given the node map
-    	 |   |   |   | d |
-    	 | a | b | c |   |
-    	 |   |   |   | e |
-
-    	And the ways
-    	 | nodes | highway | oneway |
-    	 | abc   | primary |        |
-    	 | cd    | primary | yes    |
-    	 | ce    | river   |        |
-    	 | de    | primary |        |
-
-    	When I route I should get
-    	 | from | to | route     |
-    	 | d    | c  | de,ce     |
-    	 | e    | d  | de        |
diff --git a/features/testbot/bugs.feature b/features/testbot/bugs.feature
new file mode 100644
index 0000000..26be28a
--- /dev/null
+++ b/features/testbot/bugs.feature
@@ -0,0 +1,5 @@
+ at routing @testbot @bug
+Feature: Known bugs
+
+    Background:
+        Given the profile "testbot"
diff --git a/features/testbot/distance.feature b/features/testbot/distance.feature
index 1fb436b..f9f166b 100644
--- a/features/testbot/distance.feature
+++ b/features/testbot/distance.feature
@@ -1,228 +1,228 @@
 @routing @distance
 Feature: Distance calculation
-	
-	Background:
-		Given the profile "testbot"
-	
-	Scenario: 100m distance
-		Given a grid size of 100 meters
-		Given the node map
-		 | a | b |
-
-		And the ways
-		 | nodes |
-		 | ab    |
-
-		When I route I should get
-		 | from | to | route | distance  |
-		 | a    | b  | ab    | 100m +- 2 |
-
-	Scenario: Distance should equal sum of segments, leftwinded
-		Given the node map
-		 | e |   |
-		 | d | c |
-		 | a | b |
-
-		And the ways
-		 | nodes |
-		 | abcde |
-
-		When I route I should get
-		 | from | to | route | distance |
-		 | a    | d  | abcde | 300m +-2 |
-
-	Scenario: Distance should equal sum of segments, rightwinded
-		Given the node map
-		 |   | e |
-		 | c | d |
-		 | b | a |
-
-		And the ways
-		 | nodes |
-		 | abcde |
-
-		When I route I should get
-		 | from | to | route | distance |
-		 | a    | d  | abcde | 300m +-2 |
-
-	Scenario: 10m distances
-		Given a grid size of 10 meters
-		Given the node map
-		 | a | b |
-		 |   | c |
-
-		And the ways
-		 | nodes |
-		 | abc   |
-
-		When I route I should get
-		 | from | to | route | distance |
-		 | a    | b  | abc   | 10m +-2  |
-		 | b    | a  | abc   | 10m +-2  |
-		 | b    | c  | abc   | 10m +-2  |
-		 | c    | b  | abc   | 10m +-2  |
-		 | a    | c  | abc   | 20m +-4  |
-		 | c    | a  | abc   | 20m +-4  |
-
-	Scenario: 100m distances
-		Given a grid size of 100 meters
-		Given the node map
-		 | a | b |
-		 |   | c |
-
-		And the ways
-		 | nodes |
-		 | abc   |
-
-		When I route I should get
-		 | from | to | route | distance |
-		 | a    | b  | abc   | 100m +-2 |
-		 | b    | a  | abc   | 100m +-2 |
-		 | b    | c  | abc   | 100m +-2 |
-		 | c    | b  | abc   | 100m +-2 |
-		 | a    | c  | abc   | 200m +-4 |
-		 | c    | a  | abc   | 200m +-4 |
-
-	Scenario: 1km distance
-		Given a grid size of 1000 meters
-		Given the node map
-		 | a | b |
-		 |   | c |
-
-		And the ways
-		 | nodes |
-		 | abc   |
-
-		When I route I should get
-		 | from | to | route | distance  |
-		 | a    | b  | abc   | 1000m +-2 |
-		 | b    | a  | abc   | 1000m +-2 |
-		 | b    | c  | abc   | 1000m +-2 |
-		 | c    | b  | abc   | 1000m +-2 |
-		 | a    | c  | abc   | 2000m +-4 |
-		 | c    | a  | abc   | 2000m +-4 |
-
-	Scenario: Distance of a winding south-north path
-		Given a grid size of 10 meters
-		Given the node map
-		 | a | b |
-		 | d | c |
-		 | e | f |
-		 | h | g |
-
-		And the ways
-		 | nodes    |
-		 | abcdefgh |
-
-		When I route I should get
-		 | from | to | route    | distance |
-		 | a    | b  | abcdefgh | 10m +-2  |
-		 | a    | c  | abcdefgh | 20m +-4  |
-		 | a    | d  | abcdefgh | 30m +-6  |
-		 | a    | e  | abcdefgh | 40m +-8  |
-		 | a    | f  | abcdefgh | 50m +-10 |
-		 | a    | g  | abcdefgh | 60m +-12 |
-		 | a    | h  | abcdefgh | 70m +-14 |
-		
-	Scenario: Distance of a winding east-west path
-		Given a grid size of 10 meters
-		Given the node map
-		 | a | d | e | h |
-		 | b | c | f | g |
-
-		And the ways
-		 | nodes    |
-		 | abcdefgh |
-
-		When I route I should get
-		 | from | to | route    | distance |
-		 | a    | b  | abcdefgh | 10m +-2  |
-		 | a    | c  | abcdefgh | 20m +-4  |
-		 | a    | d  | abcdefgh | 30m +-6  |
-		 | a    | e  | abcdefgh | 40m +-8  |
-		 | a    | f  | abcdefgh | 50m +-10 |
-		 | a    | g  | abcdefgh | 60m +-12 |
-		 | a    | h  | abcdefgh | 70m +-14 |
-
-	Scenario: Geometric distances
-		Given a grid size of 1000 meters
-		Given the node map
-		 | v | w | y | a | b | c | d |
-		 | u |   |   |   |   |   | e |
-		 | t |   |   |   |   |   | f |
-		 | s |   |   | x |   |   | g |
-		 | r |   |   |   |   |   | h |
-		 | q |   |   |   |   |   | i |
-		 | p | o | n | m | l | k | j |
-		
-		And the ways
-		 | nodes |
-		 | xa    |
-		 | xb    |
-		 | xc    |
-		 | xd    |
-		 | xe    |
-		 | xf    |
-		 | xg    |
-		 | xh    |
-		 | xi    |
-		 | xj    |
-		 | xk    |
-		 | xl    |
-		 | xm    |
-		 | xn    |
-		 | xo    |
-		 | xp    |
-		 | xq    |
-		 | xr    |
-		 | xs    |
-		 | xt    |
-		 | xu    |
-		 | xv    |
-		 | xw    |
-		 | xy    |
-
-		When I route I should get
-		 | from | to | route | distance  |
-		 | x    | a  | xa    | 3000m +-2 |
-		 | x    | b  | xb    | 3162m +-2 |
-		 | x    | c  | xc    | 3606m +-2 |
-		 | x    | d  | xd    | 4243m +-2 |
-		 | x    | e  | xe    | 3606m +-2 |
-		 | x    | f  | xf    | 3162m +-2 |
-		 | x    | g  | xg    | 3000m +-2 |
-		 | x    | h  | xh    | 3162m +-2 |
-		 | x    | i  | xi    | 3606m +-2 |
-		 | x    | j  | xj    | 4243m +-2 |
-		 | x    | k  | xk    | 3606m +-2 |
-		 | x    | l  | xl    | 3162m +-2 |
-		 | x    | m  | xm    | 3000m +-2 |
-		 | x    | n  | xn    | 3162m +-2 |
-		 | x    | o  | xo    | 3606m +-2 |
-		 | x    | p  | xp    | 4243m +-2 |
-		 | x    | q  | xq    | 3606m +-2 |
-		 | x    | r  | xr    | 3162m +-2 |
-		 | x    | s  | xs    | 3000m +-2 |
-		 | x    | t  | xt    | 3162m +-2 |
-		 | x    | u  | xu    | 3606m +-2 |
-		 | x    | v  | xv    | 4243m +-2 |
-		 | x    | w  | xw    | 3606m +-2 |
-		 | x    | y  | xy    | 3162m +-2 |
-
-	@maze
-	Scenario: Distance of a maze of short segments
-		Given a grid size of 7 meters
-		Given the node map
-		 | a | b | s | t |
-		 | d | c | r | q |
-		 | e | f | o | p |
-		 | h | g | n | m |
-		 | i | j | k | l |
-
-		And the ways
-		 | nodes                |
-		 | abcdefghijklmnopqrst |
-
-		When I route I should get
-		 | from | to | route                | distance |
-		 | a    | t  | abcdefghijklmnopqrst | 133m +-2 |
+
+    Background:
+        Given the profile "testbot"
+
+    Scenario: 100m distance
+        Given a grid size of 100 meters
+        Given the node map
+            | a | b |
+
+        And the ways
+            | nodes |
+            | ab    |
+
+        When I route I should get
+            | from | to | route | distance  |
+            | a    | b  | ab    | 100m +- 2 |
+
+    Scenario: Distance should equal sum of segments, leftwinded
+        Given the node map
+            | e |   |
+            | d | c |
+            | a | b |
+
+        And the ways
+            | nodes |
+            | abcde |
+
+        When I route I should get
+            | from | to | route | distance |
+            | a    | d  | abcde | 300m +-2 |
+
+    Scenario: Distance should equal sum of segments, rightwinded
+        Given the node map
+            |   | e |
+            | c | d |
+            | b | a |
+
+        And the ways
+            | nodes |
+            | abcde |
+
+        When I route I should get
+            | from | to | route | distance |
+            | a    | d  | abcde | 300m +-2 |
+
+    Scenario: 10m distances
+        Given a grid size of 10 meters
+        Given the node map
+            | a | b |
+            |   | c |
+
+        And the ways
+            | nodes |
+            | abc   |
+
+        When I route I should get
+            | from | to | route | distance |
+            | a    | b  | abc   | 10m +-2  |
+            | b    | a  | abc   | 10m +-2  |
+            | b    | c  | abc   | 10m +-2  |
+            | c    | b  | abc   | 10m +-2  |
+            | a    | c  | abc   | 20m +-4  |
+            | c    | a  | abc   | 20m +-4  |
+
+    Scenario: 100m distances
+        Given a grid size of 100 meters
+        Given the node map
+            | a | b |
+            |   | c |
+
+        And the ways
+            | nodes |
+            | abc   |
+
+        When I route I should get
+            | from | to | route | distance |
+            | a    | b  | abc   | 100m +-2 |
+            | b    | a  | abc   | 100m +-2 |
+            | b    | c  | abc   | 100m +-2 |
+            | c    | b  | abc   | 100m +-2 |
+            | a    | c  | abc   | 200m +-4 |
+            | c    | a  | abc   | 200m +-4 |
+
+    Scenario: 1km distance
+        Given a grid size of 1000 meters
+        Given the node map
+            | a | b |
+            |   | c |
+
+        And the ways
+            | nodes |
+            | abc   |
+
+        When I route I should get
+            | from | to | route | distance  |
+            | a    | b  | abc   | 1000m +-2 |
+            | b    | a  | abc   | 1000m +-2 |
+            | b    | c  | abc   | 1000m +-2 |
+            | c    | b  | abc   | 1000m +-2 |
+            | a    | c  | abc   | 2000m +-4 |
+            | c    | a  | abc   | 2000m +-4 |
+
+    Scenario: Distance of a winding south-north path
+        Given a grid size of 10 meters
+        Given the node map
+            | a | b |
+            | d | c |
+            | e | f |
+            | h | g |
+
+        And the ways
+            | nodes    |
+            | abcdefgh |
+
+        When I route I should get
+            | from | to | route    | distance |
+            | a    | b  | abcdefgh | 10m +-2  |
+            | a    | c  | abcdefgh | 20m +-4  |
+            | a    | d  | abcdefgh | 30m +-6  |
+            | a    | e  | abcdefgh | 40m +-8  |
+            | a    | f  | abcdefgh | 50m +-10 |
+            | a    | g  | abcdefgh | 60m +-12 |
+            | a    | h  | abcdefgh | 70m +-14 |
+
+    Scenario: Distance of a winding east-west path
+        Given a grid size of 10 meters
+        Given the node map
+            | a | d | e | h |
+            | b | c | f | g |
+
+        And the ways
+            | nodes    |
+            | abcdefgh |
+
+        When I route I should get
+            | from | to | route    | distance |
+            | a    | b  | abcdefgh | 10m +-2  |
+            | a    | c  | abcdefgh | 20m +-4  |
+            | a    | d  | abcdefgh | 30m +-6  |
+            | a    | e  | abcdefgh | 40m +-8  |
+            | a    | f  | abcdefgh | 50m +-10 |
+            | a    | g  | abcdefgh | 60m +-12 |
+            | a    | h  | abcdefgh | 70m +-14 |
+
+    Scenario: Geometric distances
+        Given a grid size of 1000 meters
+        Given the node map
+            | v | w | y | a | b | c | d |
+            | u |   |   |   |   |   | e |
+            | t |   |   |   |   |   | f |
+            | s |   |   | x |   |   | g |
+            | r |   |   |   |   |   | h |
+            | q |   |   |   |   |   | i |
+            | p | o | n | m | l | k | j |
+
+        And the ways
+            | nodes |
+            | xa    |
+            | xb    |
+            | xc    |
+            | xd    |
+            | xe    |
+            | xf    |
+            | xg    |
+            | xh    |
+            | xi    |
+            | xj    |
+            | xk    |
+            | xl    |
+            | xm    |
+            | xn    |
+            | xo    |
+            | xp    |
+            | xq    |
+            | xr    |
+            | xs    |
+            | xt    |
+            | xu    |
+            | xv    |
+            | xw    |
+            | xy    |
+
+        When I route I should get
+            | from | to | route | distance  |
+            | x    | a  | xa    | 3000m +-2 |
+            | x    | b  | xb    | 3162m +-2 |
+            | x    | c  | xc    | 3606m +-2 |
+            | x    | d  | xd    | 4243m +-2 |
+            | x    | e  | xe    | 3606m +-2 |
+            | x    | f  | xf    | 3162m +-2 |
+            | x    | g  | xg    | 3000m +-2 |
+            | x    | h  | xh    | 3162m +-2 |
+            | x    | i  | xi    | 3606m +-2 |
+            | x    | j  | xj    | 4243m +-2 |
+            | x    | k  | xk    | 3606m +-2 |
+            | x    | l  | xl    | 3162m +-2 |
+            | x    | m  | xm    | 3000m +-2 |
+            | x    | n  | xn    | 3162m +-2 |
+            | x    | o  | xo    | 3606m +-2 |
+            | x    | p  | xp    | 4243m +-2 |
+            | x    | q  | xq    | 3606m +-2 |
+            | x    | r  | xr    | 3162m +-2 |
+            | x    | s  | xs    | 3000m +-2 |
+            | x    | t  | xt    | 3162m +-2 |
+            | x    | u  | xu    | 3606m +-2 |
+            | x    | v  | xv    | 4243m +-2 |
+            | x    | w  | xw    | 3606m +-2 |
+            | x    | y  | xy    | 3162m +-2 |
+
+    @maze
+    Scenario: Distance of a maze of short segments
+        Given a grid size of 7 meters
+        Given the node map
+            | a | b | s | t |
+            | d | c | r | q |
+            | e | f | o | p |
+            | h | g | n | m |
+            | i | j | k | l |
+
+        And the ways
+            | nodes                |
+            | abcdefghijklmnopqrst |
+
+        When I route I should get
+            | from | to | route                | distance |
+            | a    | t  | abcdefghijklmnopqrst | 133m +-2 |
diff --git a/features/testbot/duration.feature b/features/testbot/duration.feature
index ab6571c..d5c6e46 100644
--- a/features/testbot/duration.feature
+++ b/features/testbot/duration.feature
@@ -1,42 +1,42 @@
 @routing @testbot @routes @duration
 Feature: Durations
 
-	Background:
-		Given the profile "testbot"
-		
+    Background:
+        Given the profile "testbot"
+
     Scenario: Duration of ways
-    	Given the node map
-    	 | a | b |  |   |   | f |
-    	 |   |   |  | e |   |   |
-    	 |   | c |  |   | d |   |
-	 
-    	And the ways
-    	 | nodes | highway | duration |
-    	 | ab    | primary | 0:01     |
-    	 | bc    | primary | 0:10     |
-    	 | cd    | primary | 1:00     |
-    	 | de    | primary | 10:00    |
-    	 | ef    | primary | 01:02:03 |
+        Given the node map
+            | a | b |  |   |   | f |
+            |   |   |  | e |   |   |
+            |   | c |  |   | d |   |
+
+        And the ways
+            | nodes | highway | duration |
+            | ab    | primary | 0:01     |
+            | bc    | primary | 0:10     |
+            | cd    | primary | 1:00     |
+            | de    | primary | 10:00    |
+            | ef    | primary | 01:02:03 |
+
+        When I route I should get
+            | from | to | route | distance | time       |
+            | a    | b  | ab    | 100m +-1 | 60s +-1    |
+            | b    | c  | bc    | 200m +-1 | 600s +-1   |
+            | c    | d  | cd    | 300m +-1 | 3600s +-1  |
+            | d    | e  | de    | 141m +-2 | 36000s +-1 |
+            | e    | f  | ef    | 224m +-2 | 3723s +-1  |
 
- 		When I route I should get
- 		 | from | to | route | distance | time       |
- 		 | a    | b  | ab    | 100m +-1 | 60s +-1    |
- 		 | b    | c  | bc    | 200m +-1 | 600s +-1   |
- 		 | c    | d  | cd    | 300m +-1 | 3600s +-1  |
- 		 | d    | e  | de    | 144m +-2 | 36000s +-1 |
- 		 | e    | f  | ef    | 224m +-2 | 3723s +-1  |
-    
     @todo
     Scenario: Partial duration of ways
-    	Given the node map
-    	 | a | b |  | c |
+        Given the node map
+            | a | b |  | c |
 
-    	And the ways
-    	 | nodes | highway | duration |
-    	 | abc   | primary | 0:01     |
+        And the ways
+            | nodes | highway | duration |
+            | abc   | primary | 0:01     |
 
- 		When I route I should get
- 		 | from | to | route | distance | time    |
- 		 | a    | c  | abc   | 300m +-1 | 60s +-1 |
- 		 | a    | b  | ab    | 100m +-1 | 20s +-1 |
- 		 | b    | c  | bc    | 200m +-1 | 40s +-1 |
+        When I route I should get
+            | from | to | route | distance | time    |
+            | a    | c  | abc   | 300m +-1 | 60s +-1 |
+            | a    | b  | ab    | 100m +-1 | 20s +-1 |
+            | b    | c  | bc    | 200m +-1 | 40s +-1 |
diff --git a/features/testbot/example.feature b/features/testbot/example.feature
index 699d35c..c2aa1e9 100644
--- a/features/testbot/example.feature
+++ b/features/testbot/example.feature
@@ -1,38 +1,37 @@
 @routing @testbot @example
 Feature: Testbot - Walkthrough
-
 # A complete walk-through of how this data is processed can be found at:
 # https://github.com/DennisOSRM/Project-OSRM/wiki/Processing-Flow
 
-	Background:
-		Given the profile "testbot"
-    
+    Background:
+        Given the profile "testbot"
+
     Scenario: Testbot - Processing Flow
-    	Given the node map
-    	 |   |   |   | d |
-    	 | a | b | c |   |
-    	 |   |   |   | e |
+        Given the node map
+            |   |   |   | d |
+            | a | b | c |   |
+            |   |   |   | e |
 
-    	And the ways
-    	 | nodes | highway | oneway |
-    	 | abc   | primary |        |
-    	 | cd    | primary | yes    |
-    	 | ce    | river   |        |
-    	 | de    | primary |        |
+        And the ways
+            | nodes | highway | oneway |
+            | abc   | primary |        |
+            | cd    | primary | yes    |
+            | ce    | river   |        |
+            | de    | primary |        |
 
-    	When I route I should get
-    	 | from | to | route     |
-    	 | a    | b  | abc       |
-    	 | a    | c  | abc       |
-    	 | a    | d  | abc,cd    |
-    	 | a    | e  | abc,ce    |
-    	 | b    | a  | abc       |
-    	 | b    | c  | abc       |
-    	 | b    | d  | abc,cd    |
-    	 | b    | e  | abc,ce    |
-    	 | d    | a  | de,ce,abc |
-    	 | d    | b  | de,ce,abc |
-    	 | d    | e  | de        |
-    	 | e    | a  | ce,abc    |
-    	 | e    | b  | ce,abc    |
-    	 | e    | c  | ce        |
+        When I route I should get
+            | from | to | route     |
+            | a    | b  | abc       |
+            | a    | c  | abc       |
+            | a    | d  | abc,cd    |
+            | a    | e  | abc,ce    |
+            | b    | a  | abc       |
+            | b    | c  | abc       |
+            | b    | d  | abc,cd    |
+            | b    | e  | abc,ce    |
+            | d    | a  | de,ce,abc |
+            | d    | b  | de,ce,abc |
+            | d    | e  | de        |
+            | e    | a  | ce,abc    |
+            | e    | b  | ce,abc    |
+            | e    | c  | ce        |
diff --git a/features/testbot/fastest.feature b/features/testbot/fastest.feature
index 572280c..9a5cf24 100644
--- a/features/testbot/fastest.feature
+++ b/features/testbot/fastest.feature
@@ -1,38 +1,38 @@
 @routing @fastest
 Feature: Choosing fastest route
-	
-	Background:
-		Given the profile "testbot"
-	
-	Scenario: Pick the geometrically shortest route, way types being equal
-		Given the node map
-		 |   |   | s |   |   |
-		 |   |   | t |   |   |
-		 | x | a |   | b | y |
 
-		And the ways
-		 | nodes | highway |
-		 | xa    | primary |
-		 | by    | primary |
-		 | atb   | primary |
-		 | asb   | primary |
+    Background:
+        Given the profile "testbot"
 
-		When I route I should get
-		 | from | to | route     |
-		 | x    | y  | xa,atb,by |
-		 | y    | x  | by,atb,xa |
+    Scenario: Pick the geometrically shortest route, way types being equal
+        Given the node map
+            |   |   | s |   |   |
+            |   |   | t |   |   |
+            | x | a |   | b | y |
 
-	Scenario: Pick the fastest route, even when it's longer
-		Given the node map
-		 |   | p |   |
-		 | a | s | b |
+        And the ways
+            | nodes | highway |
+            | xa    | primary |
+            | by    | primary |
+            | atb   | primary |
+            | asb   | primary |
 
-		And the ways
-		 | nodes | highway   |
-		 | apb   | primary   |
-		 | asb   | secondary |
+        When I route I should get
+            | from | to | route     |
+            | x    | y  | xa,atb,by |
+            | y    | x  | by,atb,xa |
 
-		When I route I should get
-		 | from | to | route |
-		 | a    | b  | apb   |
-		 | b    | a  | apb   |
+    Scenario: Pick the fastest route, even when it's longer
+        Given the node map
+            |   | p |   |
+            | a | s | b |
+
+        And the ways
+            | nodes | highway   |
+            | apb   | primary   |
+            | asb   | secondary |
+
+        When I route I should get
+            | from | to | route |
+            | a    | b  | apb   |
+            | b    | a  | apb   |
diff --git a/features/testbot/ferry.feature b/features/testbot/ferry.feature
index 7bd4353..5516061 100644
--- a/features/testbot/ferry.feature
+++ b/features/testbot/ferry.feature
@@ -1,175 +1,175 @@
 @routing @testbot @ferry
 Feature: Testbot - Handle ferry routes
 
-	Background:
-		Given the profile "testbot"
-
-	Scenario: Testbot - Ferry duration, single node
-		Given the node map
-		 | a | b | c | d |
-		 | e | f | g | h |
-		 | i | j | k | l |
-		 | m | n | o | p |
-		 | q | r | s | t |
-		 
-		And the ways
-		 | nodes | highway | route | duration |
-		 | ab    | primary |       |          |
-		 | cd    | primary |       |          |
-		 | ef    | primary |       |          |
-		 | gh    | primary |       |          |
-		 | ij    | primary |       |          |
-		 | kl    | primary |       |          |
-		 | mn    | primary |       |          |
-		 | op    | primary |       |          |
-		 | qr    | primary |       |          |
-		 | st    | primary |       |          |
-		 | bc    |         | ferry | 0:01     |
-		 | fg    |         | ferry | 0:10     |
-		 | jk    |         | ferry | 1:00     |
-		 | no    |         | ferry | 24:00    |
-		 | rs    |         | ferry | 96:00    |
+    Background:
+        Given the profile "testbot"
+
+    Scenario: Testbot - Ferry duration, single node
+        Given the node map
+            | a | b | c | d |
+            | e | f | g | h |
+            | i | j | k | l |
+            | m | n | o | p |
+            | q | r | s | t |
+
+        And the ways
+            | nodes | highway | route | duration |
+            | ab    | primary |       |          |
+            | cd    | primary |       |          |
+            | ef    | primary |       |          |
+            | gh    | primary |       |          |
+            | ij    | primary |       |          |
+            | kl    | primary |       |          |
+            | mn    | primary |       |          |
+            | op    | primary |       |          |
+            | qr    | primary |       |          |
+            | st    | primary |       |          |
+            | bc    |         | ferry | 0:01     |
+            | fg    |         | ferry | 0:10     |
+            | jk    |         | ferry | 1:00     |
+            | no    |         | ferry | 24:00    |
+            | rs    |         | ferry | 96:00    |
 
         When I route I should get
-         | from | to | route | time        |
-         | b    | c  | bc    | 60s +-1     |
-         | f    | g  | fg    | 600s +-1    |
-         | j    | k  | jk    | 3600s +-1   |
-         | n    | o  | no    | 86400s +-1  |
-         | r    | s  | rs    | 345600s +-1 |
-    
+            | from | to | route | time        |
+            | b    | c  | bc    | 60s +-1     |
+            | f    | g  | fg    | 600s +-1    |
+            | j    | k  | jk    | 3600s +-1   |
+            | n    | o  | no    | 86400s +-1  |
+            | r    | s  | rs    | 345600s +-1 |
+
     @todo
- 	Scenario: Testbot - Week long ferry routes
- 		Given the node map
- 		 | a | b | c | d |
- 		 | e | f | g | h |
- 		 | i | j | k | l |
-
- 		And the ways
- 		 | nodes | highway | route | duration |
- 		 | ab    | primary |       |          |
- 		 | cd    | primary |       |          |
- 		 | ef    | primary |       |          |
- 		 | gh    | primary |       |          |
- 		 | ij    | primary |       |          |
- 		 | kl    | primary |       |          |
- 		 | bc    |         | ferry | 24:00    |
- 		 | fg    |         | ferry | 168:00   |
- 		 | jk    |         | ferry | 720:00   |
-
-         When I route I should get
-          | from | to | route | time        |
-          | b    | c  | bc    | 86400s +-1  |
-          | f    | g  | fg    | 604800s +-1 |
-          | j    | k  | jk    | 259200s +-1 |
-
-	Scenario: Testbot - Ferry duration, multiple nodes
-		Given the node map
-		  | x |   |   |   |   | y |
-		  |   | a | b | c | d |   |
-
-		And the ways
-		 | nodes | highway | route | duration |
-		 | xa    | primary |       |          |
-		 | yd    | primary |       |          |
-		 | ad    |         | ferry | 1:00     |
-
-		When I route I should get
-		 | from | to | route | time      |
-		 | a    | d  | ad    | 3600s +-1 |
-		 | d    | a  | ad    | 3600s +-1 |
-    
+    Scenario: Testbot - Week long ferry routes
+        Given the node map
+            | a | b | c | d |
+            | e | f | g | h |
+            | i | j | k | l |
+
+        And the ways
+            | nodes | highway | route | duration |
+            | ab    | primary |       |          |
+            | cd    | primary |       |          |
+            | ef    | primary |       |          |
+            | gh    | primary |       |          |
+            | ij    | primary |       |          |
+            | kl    | primary |       |          |
+            | bc    |         | ferry | 24:00    |
+            | fg    |         | ferry | 168:00   |
+            | jk    |         | ferry | 720:00   |
+
+        When I route I should get
+            | from | to | route | time        |
+            | b    | c  | bc    | 86400s +-1  |
+            | f    | g  | fg    | 604800s +-1 |
+            | j    | k  | jk    | 259200s +-1 |
+
+    Scenario: Testbot - Ferry duration, multiple nodes
+        Given the node map
+            | x |   |   |   |   | y |
+            |   | a | b | c | d |   |
+
+        And the ways
+            | nodes | highway | route | duration |
+            | xa    | primary |       |          |
+            | yd    | primary |       |          |
+            | ad    |         | ferry | 1:00     |
+
+        When I route I should get
+            | from | to | route | time      |
+            | a    | d  | ad    | 3600s +-1 |
+            | d    | a  | ad    | 3600s +-1 |
+
     @todo
-	Scenario: Testbot - Ferry duration, individual parts, fast
+    Scenario: Testbot - Ferry duration, individual parts, fast
     Given a grid size of 10000 meters
-		Given the node map
-		  | x | y |  | z |  |  | v |
-		  | a | b |  | c |  |  | d |
-
-		And the ways
-		 | nodes | highway | route | duration |
-		 | xa    | primary |       |          |
-		 | yb    | primary |       |          |
-		 | zc    | primary |       |          |
-		 | vd    | primary |       |          |
-		 | abcd  |         | ferry | 0:06     |
-
-		When I route I should get
-		 | from | to | route | time     |
-		 | a    | d  | abcd  | 360s +-1 |
-		 | a    | b  | abcd  | 60s +-1  |
-		 | b    | c  | abcd  | 120s +-1 |
-		 | c    | d  | abcd  | 180s +-1 |
-    
+        Given the node map
+            | x | y |  | z |  |  | v |
+            | a | b |  | c |  |  | d |
+
+        And the ways
+            | nodes | highway | route | duration |
+            | xa    | primary |       |          |
+            | yb    | primary |       |          |
+            | zc    | primary |       |          |
+            | vd    | primary |       |          |
+            | abcd  |         | ferry | 0:06     |
+
+        When I route I should get
+            | from | to | route | time     |
+            | a    | d  | abcd  | 360s +-1 |
+            | a    | b  | abcd  | 60s +-1  |
+            | b    | c  | abcd  | 120s +-1 |
+            | c    | d  | abcd  | 180s +-1 |
+
     @todo
- 	Scenario: Testbot - Ferry duration, individual parts, slow
- 		Given the node map
- 		  | x | y |  | z |  |  | v |
- 		  | a | b |  | c |  |  | d |
-
- 		And the ways
- 		 | nodes | highway | route | duration |
- 		 | xa    | primary |       |          |
- 		 | yb    | primary |       |          |
- 		 | zc    | primary |       |          |
- 		 | vd    | primary |       |          |
- 		 | abcd  |         | ferry | 1:00     |
-
- 		When I route I should get
- 		 | from | to | route | time      |
- 		 | a    | d  | abcd  | 3600s ~1% |
- 		 | a    | b  | abcd  | 600s ~1%  |
- 		 | b    | c  | abcd  | 1200s ~1% |
- 		 | c    | d  | abcd  | 1800s ~1% |
- 
- 	Scenario: Testbot - Ferry duration, connected routes
- 		Given the node map
- 		  | x |   |   |   | d |   |   |   | y |
- 		  |   | a | b | c |   | e | f | g | t |
-
- 		And the ways
- 		 | nodes | highway | route | duration |
- 		 | xa    | primary |       |          |
- 		 | yg    | primary |       |          |
- 		 | abcd  |         | ferry | 0:30     |
- 		 | defg  |         | ferry | 0:30     |
-
- 		When I route I should get
- 		 | from | to | route     | time      |
- 		 | a    | g  | abcd,defg | 3600s +-1 |
- 		 | g    | a  | defg,abcd | 3600s +-1 |
-
- 	Scenario: Testbot - Prefer road when faster than ferry
- 		Given the node map
- 		  | x | a | b | c |   |
- 		  |   |   |   |   | d |
- 		  | y | g | f | e |   |
-
- 		And the ways
- 		 | nodes | highway | route | duration |
- 		 | xa    | primary |       |          |
- 		 | yg    | primary |       |          |
- 		 | xy    | primary |       |          |
- 		 | abcd  |         | ferry | 0:01     |
- 		 | defg  |         | ferry | 0:01     |
-
- 		When I route I should get
- 		 | from | to | route    | time      |
- 		 | a    | g  | xa,xy,yg | 60s +-25% |
- 		 | g    | a  | yg,xy,xa | 60s +-25% |
-
- 	Scenario: Testbot - Long winding ferry route
- 		Given the node map
- 		  | x |   | b |   | d |   | f |   | y |
- 		  |   | a |   | c |   | e |   | g |   |
-
- 		And the ways
- 		 | nodes   | highway | route | duration |
- 		 | xa      | primary |       |          |
- 		 | yg      | primary |       |          |
- 		 | abcdefg |         | ferry | 6:30     |
-
- 		When I route I should get
- 		 | from | to | route   | time       |
- 		 | a    | g  | abcdefg | 23400s +-1 |
- 		 | g    | a  | abcdefg | 23400s +-1 |
+    Scenario: Testbot - Ferry duration, individual parts, slow
+        Given the node map
+            | x | y |  | z |  |  | v |
+            | a | b |  | c |  |  | d |
+
+        And the ways
+            | nodes | highway | route | duration |
+            | xa    | primary |       |          |
+            | yb    | primary |       |          |
+            | zc    | primary |       |          |
+            | vd    | primary |       |          |
+            | abcd  |         | ferry | 1:00     |
+
+        When I route I should get
+            | from | to | route | time      |
+            | a    | d  | abcd  | 3600s ~1% |
+            | a    | b  | abcd  | 600s ~1%  |
+            | b    | c  | abcd  | 1200s ~1% |
+            | c    | d  | abcd  | 1800s ~1% |
+
+    Scenario: Testbot - Ferry duration, connected routes
+        Given the node map
+            | x |   |   |   | d |   |   |   | y |
+            |   | a | b | c |   | e | f | g | t |
+
+        And the ways
+            | nodes | highway | route | duration |
+            | xa    | primary |       |          |
+            | yg    | primary |       |          |
+            | abcd  |         | ferry | 0:30     |
+            | defg  |         | ferry | 0:30     |
+
+        When I route I should get
+            | from | to | route     | time      |
+            | a    | g  | abcd,defg | 3600s +-1 |
+            | g    | a  | defg,abcd | 3600s +-1 |
+
+    Scenario: Testbot - Prefer road when faster than ferry
+        Given the node map
+            | x | a | b | c |   |
+            |   |   |   |   | d |
+            | y | g | f | e |   |
+
+        And the ways
+            | nodes | highway | route | duration |
+            | xa    | primary |       |          |
+            | yg    | primary |       |          |
+            | xy    | primary |       |          |
+            | abcd  |         | ferry | 0:01     |
+            | defg  |         | ferry | 0:01     |
+
+        When I route I should get
+            | from | to | route    | time      |
+            | a    | g  | xa,xy,yg | 60s +-25% |
+            | g    | a  | yg,xy,xa | 60s +-25% |
+
+    Scenario: Testbot - Long winding ferry route
+        Given the node map
+            | x |   | b |   | d |   | f |   | y |
+            |   | a |   | c |   | e |   | g |   |
+
+        And the ways
+            | nodes   | highway | route | duration |
+            | xa      | primary |       |          |
+            | yg      | primary |       |          |
+            | abcdefg |         | ferry | 6:30     |
+
+        When I route I should get
+            | from | to | route   | time       |
+            | a    | g  | abcdefg | 23400s +-2 |
+            | g    | a  | abcdefg | 23400s +-2 |
diff --git a/features/testbot/fixed.feature b/features/testbot/fixed.feature
new file mode 100644
index 0000000..0edf25c
--- /dev/null
+++ b/features/testbot/fixed.feature
@@ -0,0 +1,26 @@
+ at routing @testbot @fixed
+Feature: Fixed bugs, kept to check for regressions
+
+    Background:
+        Given the profile "testbot"
+
+    @726
+    Scenario: Weird looping, manual input
+        Given the node locations
+            | node | lat       | lon       |
+            | a    | 55.660778 | 12.573909 |
+            | b    | 55.660672 | 12.573693 |
+            | c    | 55.660128 | 12.572546 |
+            | d    | 55.660015 | 12.572476 |
+            | e    | 55.660119 | 12.572325 |
+            | x    | 55.660818 | 12.574051 |
+            | y    | 55.660073 | 12.574067 |
+
+        And the ways
+            | nodes |
+            | abc   |
+            | cdec  |
+
+        When I route I should get
+            | from | to | route | turns            |
+            | x    | y  | abc   | head,destination |
diff --git a/features/testbot/geometry.feature b/features/testbot/geometry.feature
new file mode 100644
index 0000000..553af93
--- /dev/null
+++ b/features/testbot/geometry.feature
@@ -0,0 +1,30 @@
+ at routing
+Feature: Retrieve geometry
+
+    Background: Use some profile
+        Given the profile "testbot"
+
+
+    @geometry
+    Scenario: Route retrieving geometry
+       Given the node locations
+            | node | lat | lon |
+            | a    | 1.0 | 1.5 |
+            | b    | 2.0 | 2.5 |
+            | c    | 3.0 | 3.5 |
+            | d    | 4.0 | 4.5 |
+
+        And the ways
+            | nodes |
+            | ab    |
+            | bc    |
+            | cd    |
+
+        When I route I should get
+            | from | to | route | geometry                             |
+            | a    | c  | ab,bc | _c`\|@_upzA_c`\|@_c`\|@_c`\|@_c`\|@  |
+            | b    | d  | bc,cd | _gayB_yqwC_c`\|@_c`\|@_c`\|@_c`\|@   |
+
+# Mind the \ before the pipes
+# polycodec.rb decode2 '_c`|@_upzA_c`|@_c`|@_c`|@_c`|@' [[1.0, 1.5], [2.0, 2.5], [3.0, 3.5]]
+# polycodec.rb decode2 '_gayB_yqwC_c`|@_c`|@_c`|@_c`|@' [[2.0, 2.5], [3.0, 3.5], [4.0, 4.5]]
diff --git a/features/testbot/graph.feature b/features/testbot/graph.feature
index 97a5171..a870106 100644
--- a/features/testbot/graph.feature
+++ b/features/testbot/graph.feature
@@ -1,22 +1,21 @@
 @routing @graph
 Feature: Basic Routing
-Test the input data descibed on https://github.com/DennisOSRM/Project-OSRM/wiki/Graph-representation
+#Test the input data descibed on https://github.com/DennisOSRM/Project-OSRM/wiki/Graph-representation
 
-	Background:
-		Given the profile "testbot"
-	
-	@smallest
-	Scenario: Graph transformation
-		Given the node map
-        |   |   | d |
-        | a | b | c |
-        |   |   | e |
-	
-		And the ways
-		 | nodes |
-		 | abc   |
-		 | dce   |
-    
-		When I route I should get
-		 | from | to | route   |
-		 | a    | e  | abc,dce |
+    Background:
+        Given the profile "testbot"
+
+    Scenario: Graph transformation
+        Given the node map
+            |   |   | d |
+            | a | b | c |
+            |   |   | e |
+
+        And the ways
+            | nodes |
+            | abc   |
+            | dce   |
+
+        When I route I should get
+            | from | to | route   |
+            | a    | e  | abc,dce |
diff --git a/features/testbot/impedance.feature b/features/testbot/impedance.feature
index 0e53623..cab9ec3 100644
--- a/features/testbot/impedance.feature
+++ b/features/testbot/impedance.feature
@@ -1,96 +1,95 @@
 @routing @testbot @impedance @todo
 Feature: Setting impedance and speed separately
-These tests assume that the speed is not factored into the impedance by OSRM internally.
-Instead the speed can optionally be factored into the weiht in the lua profile.
+# These tests assume that the speed is not factored into the impedance by OSRM internally.
+# Instead the speed can optionally be factored into the weiht in the lua profile.
+# Note: With the default grid size of 100m, the diagonals has a length if 141.42m
 
-Note: With the default grid size of 100m, the diagonals has a length if 141.42m
+    Background:
+        Given the profile "testbot"
 
-	Background:
-		Given the profile "testbot"
-	
-	Scenario: Use impedance to pick route, even when longer/slower
-		Given the node map
-		 |   | s |   | t |   | u |   | v |   |
-		 | a |   | b |   | c |   | d |   | e |
+    Scenario: Use impedance to pick route, even when longer/slower
+        Given the node map
+            |   | s |   | t |   | u |   | v |   |
+            | a |   | b |   | c |   | d |   | e |
 
-		And the ways
-		 | nodes | impedance |
-		 | ab    | 1.3    |
-		 | asb   | 1      |
-		 | bc    | 1.5    |
-		 | btc   | 1      |
-		 | cd    | 0.015  |
-		 | cud   | 0.010  |
-		 | de    | 150000 |
-		 | dve   | 100000 |
+        And the ways
+            | nodes | impedance |
+            | ab    | 1.3       |
+            | asb   | 1         |
+            | bc    | 1.5       |
+            | btc   | 1         |
+            | cd    | 0.015     |
+            | cud   | 0.010     |
+            | de    | 150000    |
+            | dve   | 100000    |
 
-		When I route I should get
-		 | from | to | route | distance |
-		 | a    | b  | ab    | 200m +-1 |
-		 | b    | a  | ab    | 200m +-1 |
-		 | b    | c  | btc   | 282m +-1 |
-		 | c    | b  | btc   | 282m +-1 |
-		 | c    | d  | cud   | 282m +-1 |
-		 | d    | c  | cud   | 282m +-1 |
-		 | d    | e  | dve   | 282m +-1 |
-		 | e    | d  | dve   | 282m +-1 |
+        When I route I should get
+            | from | to | route | distance |
+            | a    | b  | ab    | 200m +-1 |
+            | b    | a  | ab    | 200m +-1 |
+            | b    | c  | btc   | 282m +-1 |
+            | c    | b  | btc   | 282m +-1 |
+            | c    | d  | cud   | 282m +-1 |
+            | d    | c  | cud   | 282m +-1 |
+            | d    | e  | dve   | 282m +-1 |
+            | e    | d  | dve   | 282m +-1 |
 
- 	Scenario: Weight should default to 1
- 		Given the node map
- 		 |   | s |   | t |   |
- 		 | a |   | b |   | c |
+    Scenario: Weight should default to 1
+        Given the node map
+            |   | s |   | t |   |
+            | a |   | b |   | c |
 
- 		And the ways
- 		 | nodes | impedance |
- 		 | ab    | 1.40   |
- 		 | asb   |        |
- 		 | bc    | 1.42   |
- 		 | btc   |        |
+        And the ways
+            | nodes | impedance |
+            | ab    | 1.40      |
+            | asb   |           |
+            | bc    | 1.42      |
+            | btc   |           |
 
- 		When I route I should get
- 		 | from | to | route |
- 		 | a    | b  | ab    |
- 		 | b    | a  | ab    |
- 		 | b    | c  | btc   |
- 		 | c    | b  | btc   |
+        When I route I should get
+            | from | to | route |
+            | a    | b  | ab    |
+            | b    | a  | ab    |
+            | b    | c  | btc   |
+            | c    | b  | btc   |
 
-  	Scenario: Use both impedance and speed (multiplied) when picking route
-  	OSRM should not factor speed into impedance internally. However, the profile can choose to do so,
-  	and this test expect the testbot profile to do it.
-  		Given the node map
-  		 |   | s |   | t |   |
-  		 | a |   | b |   | c |
+    Scenario: Use both impedance and speed (multiplied) when picking route
+    # OSRM should not factor speed into impedance internally. However, the profile can choose to do so,
+    # and this test expect the testbot profile to do it.
+        Given the node map
+            |   | s |   | t |   |
+            | a |   | b |   | c |
 
-  		And the ways
-  		 | nodes | impedance | highway   |
-  		 | ab    | 2.80   | primary   |
-  		 | asb   | 1      | secondary |
-  		 | bc    | 2.84   | primary   |
-  		 | btc   | 1      | secondary |
+        And the ways
+            | nodes | impedance | highway   |
+            | ab    | 2.80      | primary   |
+            | asb   | 1         | secondary |
+            | bc    | 2.84      | primary   |
+            | btc   | 1         | secondary |
 
-  		When I route I should get
-  		 | from | to | route |
-  		 | a    | b  | ab    |
-  		 | b    | a  | ab    |
-  		 | b    | c  | btc   |
-  		 | c    | b  | btc   |
+        When I route I should get
+            | from | to | route |
+            | a    | b  | ab    |
+            | b    | a  | ab    |
+            | b    | c  | btc   |
+            | c    | b  | btc   |
 
- 	Scenario: Weight should influence neither speed nor travel time. 
- 		Given the node map
- 		 | a | b | c |
- 		 | t |   |   |
+    Scenario: Weight should influence neither speed nor travel time.
+        Given the node map
+            | a | b | c |
+            | t |   |   |
 
- 		And the ways
- 		 | nodes |
- 		 | ab    |
- 		 | bc    |
- 		 | at    |
+        And the ways
+            | nodes |
+            | ab    |
+            | bc    |
+            | at    |
 
- 		When I route I should get
- 		 | from | to | route | distance | time    |
- 		 | a    | b  | ab    | 100m +-1 | 10s +-1 |
- 		 | b    | a  | ab    | 100m +-1 | 10s +-1 |
- 		 | b    | c  | bc    | 100m +-1 | 10s +-1 |
- 		 | c    | b  | bc    | 100m +-1 | 10s +-1 |
- 		 | a    | c  | ab,bc | 200m +-1 | 20s +-1 |
- 		 | c    | a  | bc,ab | 200m +-1 | 20s +-1 |
+        When I route I should get
+            | from | to | route | distance | time    |
+            | a    | b  | ab    | 100m +-1 | 10s +-1 |
+            | b    | a  | ab    | 100m +-1 | 10s +-1 |
+            | b    | c  | bc    | 100m +-1 | 10s +-1 |
+            | c    | b  | bc    | 100m +-1 | 10s +-1 |
+            | a    | c  | ab,bc | 200m +-1 | 20s +-1 |
+            | c    | a  | bc,ab | 200m +-1 | 20s +-1 |
diff --git a/features/testbot/loop.feature b/features/testbot/loop.feature
new file mode 100644
index 0000000..eb5b45e
--- /dev/null
+++ b/features/testbot/loop.feature
@@ -0,0 +1,78 @@
+ at routing @726
+Feature: Avoid weird loops caused by rounding errors
+
+    Background:
+        Given the profile "testbot"
+
+    Scenario: Avoid weird loops 1
+        Given the node locations
+            | node | lat        | lon        |
+            | a    | 55.6602463 | 12.5717242 |
+            | b    | 55.6600270 | 12.5723008 |
+            | c    | 55.6601840 | 12.5725037 |
+            | d    | 55.6604146 | 12.5719299 |
+            | e    | 55.6599410 | 12.5727592 |
+            | f    | 55.6606727 | 12.5736932 |
+            | g    | 55.6603422 | 12.5732619 |
+            | h    | 55.6607785 | 12.5739097 |
+            | i    | 55.6600566 | 12.5725070 |
+            | x    | 55.6608180 | 12.5740510 |
+            | y    | 55.6600730 | 12.5740670 |
+
+        And the ways
+            | nodes |
+            | ab    |
+            | hfgd  |
+            | icd   |
+            | ad    |
+            | ie    |
+
+        When I route I should get
+            | from | to | route | turns            |
+            | x    | y  | hfgd  | head,destination |
+
+    Scenario: Avoid weird loops 2
+        Given the node locations
+            | node | lat       | lon       |
+            | a    | 55.660778 | 12.573909 |
+            | b    | 55.660672 | 12.573693 |
+            | c    | 55.660128 | 12.572546 |
+            | d    | 55.660015 | 12.572476 |
+            | e    | 55.660119 | 12.572325 |
+            | x    | 55.660818 | 12.574051 |
+            | y    | 55.660073 | 12.574067 |
+
+        And the ways
+            | nodes |
+            | abc   |
+            | cdec  |
+
+        When I route I should get
+            | from | to | route | turns            |
+            | x    | y  | abc   | head,destination |
+
+    @412
+    Scenario: Avoid weird loops 3
+        And the node map
+            | a |   |   |
+            | b | e |   |
+            |   |   | 1 |
+            |   |   |   |
+            |   |   | 2 |
+            |   |   |   |
+            |   | c | f |
+            |   | d |   |
+
+        And the ways
+            | nodes | highway   |
+            | ab    | primary   |
+            | bc    | primary   |
+            | cd    | primary   |
+            | be    | secondary |
+            | ef    | secondary |
+            | cf    | secondary |
+
+        When I route I should get
+            | waypoints | route          | turns                                  |
+            | a,2,d     | ab,be,ef,cf,cd | head,left,right,right,left,destination |
+            | a,1,d     | ab,be,ef,cf,cd | head,left,right,right,left,destination |
diff --git a/features/testbot/maxspeed.feature b/features/testbot/maxspeed.feature
index c6b210e..5b27f9d 100644
--- a/features/testbot/maxspeed.feature
+++ b/features/testbot/maxspeed.feature
@@ -1,52 +1,29 @@
 @routing @maxspeed @testbot
 Feature: Car - Max speed restrictions
 
-	Background: Use specific speeds
-		Given the profile "testbot"
-	
-	Scenario: Testbot - Respect maxspeeds when lower that way type speed
-		Given the node map
-		 | a | b | c | d |
+    Background: Use specific speeds
+        Given the profile "testbot"
 
-		And the ways
-		 | nodes | maxspeed |
-		 | ab    |          |
-		 | bc    | 24       |
-		 | cd    | 18       |
+    Scenario: Testbot - Respect maxspeeds when lower that way type speed
+        Then routability should be
+            | maxspeed | bothw   |
+            |          | 36 km/h |
+            | 18       | 18 km/h |
 
-		When I route I should get
-		 | from | to | route | time    |
-		 | a    | b  | ab    | 10s +-1 |
-		 | b    | a  | ab    | 10s +-1 |
-		 | b    | c  | bc    | 15s +-1 |
-		 | c    | b  | bc    | 15s +-1 |
-		 | c    | d  | cd    | 20s +-1 |
-		 | d    | c  | cd    | 20s +-1 |
-
-	Scenario: Testbot - Ignore maxspeed when higher than way speed
-		Given the node map
-		 | a | b | c |
-
-		And the ways
-		 | nodes | maxspeed |
-		 | ab    |          |
-		 | bc    | 200      |
-
-		When I route I should get
-		 | from | to | route | time    |
-		 | a    | b  | ab    | 10s +-1 |
-		 | b    | a  | ab    | 10s +-1 |
-		 | b    | c  | bc    | 10s +-1 |
-		 | c    | b  | bc    | 10s +-1 |
+    Scenario: Testbot - Ignore maxspeed when higher than way speed
+        Then routability should be
+            | maxspeed | bothw   |
+            |          | 36 km/h |
+            | 100 km/h | 36 km/h |
 
     @opposite
     Scenario: Testbot - Forward/backward maxspeed
-     	Then routability should be
-     	 | maxspeed | maxspeed:forward | maxspeed:backward | forw    | backw   |
-     	 |          |                  |                   | 20s +-1 | 20s +-1 |
-     	 | 18       |                  |                   | 40s +-1 | 40s +-1 |
-     	 |          | 18               |                   | 40s +-1 | 20s +-1 |
-     	 |          |                  | 18                | 20s +-1 | 40s +-1 |
-     	 | 9        | 18               |                   | 40s +-1 | 80s +-1 |
-     	 | 9        |                  | 18                | 80s +-1 | 40s +-1 |
-     	 | 9        | 24               | 18                | 30s +-1 | 40s +-1 |
\ No newline at end of file
+        Then routability should be
+            | maxspeed | maxspeed:forward | maxspeed:backward | forw    | backw   |
+            |          |                  |                   | 36 km/h | 36 km/h |
+            | 18       |                  |                   | 18 km/h | 18 km/h |
+            |          | 18               |                   | 18 km/h | 36 km/h |
+            |          |                  | 18                | 36 km/h | 18 km/h |
+            | 9        | 18               |                   | 18 km/h | 9 km/h  |
+            | 9        |                  | 18                | 9 km/h  | 18 km/h |
+            | 9        | 24               | 18                | 24 km/h | 18 km/h |
\ No newline at end of file
diff --git a/features/testbot/mode.feature b/features/testbot/mode.feature
index 3192c48..bcc087e 100644
--- a/features/testbot/mode.feature
+++ b/features/testbot/mode.feature
@@ -1,26 +1,26 @@
 @routing @testbot @mode
 Feature: Testbot - Mode flag
 
-	Background:
-		Given the profile "testbot"
-    
+    Background:
+        Given the profile "testbot"
+
     @todo
-  	Scenario: Bike - Mode
-  		Given the node map
-  		 | a | b |   |
-  		 |   | c | d |
+    Scenario: Bike - Mode
+        Given the node map
+            | a | b |   |
+            |   | c | d |
 
-  		And the ways
-  		 | nodes | highway | route | duration |
-  		 | ab    | primary |       |          |
-  		 | bc    |         | ferry | 0:01     |
-  		 | cd    | primary |       |          |
+        And the ways
+            | nodes | highway | route | duration |
+            | ab    | primary |       |          |
+            | bc    |         | ferry | 0:01     |
+            | cd    | primary |       |          |
 
-  		When I route I should get
-  		 | from | to | route    | turns                       | modes         |
-  		 | a    | d  | ab,bc,cd | head,right,left,destination | bot,ferry,bot |
-  		 | d    | a  | cd,bc,ab | head,right left,destination | bot,ferry,bot |
-  		 | c    | a  | bc,ab    | head,left,destination       | ferry,bot     |
-  		 | d    | b  | cd,bc    | head,right,destination      | bot,ferry     |
-  		 | a    | c  | ab,bc    | head,right,destination      | bot,ferry     |
-  		 | b    | d  | bc,cd    | head,left,destination       | ferry,bot     |
+        When I route I should get
+            | from | to | route    | turns                       | modes         |
+            | a    | d  | ab,bc,cd | head,right,left,destination | bot,ferry,bot |
+            | d    | a  | cd,bc,ab | head,right left,destination | bot,ferry,bot |
+            | c    | a  | bc,ab    | head,left,destination       | ferry,bot     |
+            | d    | b  | cd,bc    | head,right,destination      | bot,ferry     |
+            | a    | c  | ab,bc    | head,right,destination      | bot,ferry     |
+            | b    | d  | bc,cd    | head,left,destination       | ferry,bot     |
diff --git a/features/testbot/oneway.feature b/features/testbot/oneway.feature
new file mode 100644
index 0000000..c21d8b1
--- /dev/null
+++ b/features/testbot/oneway.feature
@@ -0,0 +1,44 @@
+ at routing @testbot @oneway
+Feature: Testbot - oneways
+
+    Background:
+        Given the profile "testbot"
+
+    Scenario: Routing on a oneway roundabout
+        Given the node map
+        | x |   |   | v |   |   |
+        |   |   | d | c |   |   |
+        |   | e |   |   | b |   |
+        |   | f |   |   | a |   |
+        |   |   | g | h |   |   |
+
+        And the ways
+            | nodes | oneway |
+            | ab    | yes    |
+            | bc    | yes    |
+            | cd    | yes    |
+            | de    | yes    |
+            | ef    | yes    |
+            | fg    | yes    |
+            | gh    | yes    |
+            | ha    | yes    |
+            | vx    | yes    |
+
+        When I route I should get
+            | from | to | route                |
+            | a    | b  | ab                   |
+            | b    | c  | bc                   |
+            | c    | d  | cd                   |
+            | d    | e  | de                   |
+            | e    | f  | ef                   |
+            | f    | g  | fg                   |
+            | g    | h  | gh                   |
+            | h    | a  | ha                   |
+            | b    | a  | bc,cd,de,ef,fg,gh,ha |
+            | c    | b  | cd,de,ef,fg,gh,ha,ab |
+            | d    | c  | de,ef,fg,gh,ha,ab,bc |
+            | e    | d  | ef,fg,gh,ha,ab,bc,cd |
+            | f    | e  | fg,gh,ha,ab,bc,cd,de |
+            | g    | f  | gh,ha,ab,bc,cd,de,ef |
+            | h    | g  | ha,ab,bc,cd,de,ef,fg |
+            | a    | h  | ab,bc,cd,de,ef,fg,gh |
diff --git a/features/testbot/opposite.feature b/features/testbot/opposite.feature
index c242c97..c19755c 100644
--- a/features/testbot/opposite.feature
+++ b/features/testbot/opposite.feature
@@ -1,18 +1,18 @@
 @routing @testbot @opposite
 Feature: Separate settings for forward/backward direction
-	
-	Background:
-		Given the profile "testbot"
-	
-	Scenario: Testbot - Going against the flow
-		Given the node map
-		 | a | b | c | d |
-	
-		And the ways
-		 | nodes | highway |
-		 | abcd  | river   |
-    
-		When I route I should get
-		 | from | to | route | distance  | time |
-		 | a    | d  | abcd  | 300 +- 1m | 30s  |
-		 | d    | a  | abcd  | 300 +- 1m | 68s  |
\ No newline at end of file
+
+    Background:
+        Given the profile "testbot"
+
+    Scenario: Testbot - Going against the flow
+        Given the node map
+            | a | b | c | d |
+
+        And the ways
+            | nodes | highway |
+            | abcd  | river   |
+
+        When I route I should get
+            | from | to | route | distance  | speed        |
+            | a    | d  | abcd  | 300 +- 1m | 36 km/h      |
+            | d    | a  | abcd  | 300 +- 1m | 16 km/h +- 1 |
diff --git a/features/testbot/origin.feature b/features/testbot/origin.feature
index 3fe6d97..c43e04e 100644
--- a/features/testbot/origin.feature
+++ b/features/testbot/origin.feature
@@ -1,75 +1,75 @@
 @routing @origin
 Feature: Routing close to the [0,0] origin
-	
-	Background:
-		Given the profile "testbot"
- 	
-	Scenario: East-west oneways close to the origin
-		Given the node locations
-		 | node | lat                   | lon |
-		 | a    | 0                     | 0   |
-		 | b    | 0.0008990679362704611 | 0   |
-		 | c    | 0.0017981358725409223 | 0   |
-		 | d    | 0.0026972038088113833 | 0   |
 
-		And the ways
-		 | nodes | oneway |
-		 | abcd  | yes    |
+    Background:
+        Given the profile "testbot"
 
-		When I route I should get
-		 | from | to | route | distance  |
-		 | b    | c  | abcd  | 100m +-1  |
-		 | c    | b  |       |           |
+    Scenario: East-west oneways close to the origin
+        Given the node locations
+            | node | lat                   | lon |
+            | a    | 0                     | 0   |
+            | b    | 0.0008990679362704611 | 0   |
+            | c    | 0.0017981358725409223 | 0   |
+            | d    | 0.0026972038088113833 | 0   |
 
-	Scenario: North-south oneways close to the origin
-		Given the node locations
-		 | node | lat | lon                   |
-		 | a    | 0   | 0                     |
-		 | b    | 0   | 0.0008990679362704611 |
-		 | c    | 0   | 0.0017981358725409223 |
-		 | d    | 0   | 0.0026972038088113833 |
+        And the ways
+            | nodes | oneway |
+            | abcd  | yes    |
 
-		And the ways
-		 | nodes | oneway |
-		 | abcd  | yes    |
+        When I route I should get
+            | from | to | route | distance |
+            | b    | c  | abcd  | 100m +-1 |
+            | c    | b  |       |          |
 
-		When I route I should get
-		 | from | to | route | distance  |
-		 | b    | c  | abcd  | 100m +-1  |
-		 | c    | b  |       |           |
-		
-	Scenario: East-west oneways crossing the origin
-		Given the node locations
-		 | node | lat                    | lon |
-		 | a    | -0.0017981358725409223 | 0   |
-		 | b    | -0.0008990679362704611 | 0   |
-		 | c    | 0                      | 0   |
-		 | d    | 0.0008990679362704611  | 0   |
-		 | e    | 0.0017981358725409223  | 0   |
+    Scenario: North-south oneways close to the origin
+        Given the node locations
+            | node | lat | lon                   |
+            | a    | 0   | 0                     |
+            | b    | 0   | 0.0008990679362704611 |
+            | c    | 0   | 0.0017981358725409223 |
+            | d    | 0   | 0.0026972038088113833 |
 
-		And the ways
-		 | nodes | oneway |
-		 | abcde | yes    |
+        And the ways
+            | nodes | oneway |
+            | abcd  | yes    |
 
-		When I route I should get
-		 | from | to | route | distance  |
-		 | b    | d  | abcde | 200m +-2  |
-		 | d    | b  |       |           |
-	
-	Scenario: North-south oneways crossing the origin
-		Given the node locations
-		 | node | lat | lon                    |
-		 | a    | 0   | -0.0017981358725409223 |
-		 | b    | 0   | -0.0008990679362704611 |
-		 | c    | 0   | 0                      |
-		 | d    | 0   | 0.0008990679362704611  |
-		 | e    | 0   | 0.0017981358725409223  |
+        When I route I should get
+            | from | to | route | distance |
+            | b    | c  | abcd  | 100m +-1 |
+            | c    | b  |       |          |
 
-		And the ways
-		 | nodes | oneway |
-		 | abcde | yes    |
+    Scenario: East-west oneways crossing the origin
+        Given the node locations
+            | node | lat                    | lon |
+            | a    | -0.0017981358725409223 | 0   |
+            | b    | -0.0008990679362704611 | 0   |
+            | c    | 0                      | 0   |
+            | d    | 0.0008990679362704611  | 0   |
+            | e    | 0.0017981358725409223  | 0   |
 
-		When I route I should get
-		 | from | to | route | distance  |
-		 | b    | d  | abcde | 200m +-2  |
-		 | d    | b  |       |           |
+        And the ways
+            | nodes | oneway |
+            | abcde | yes    |
+
+        When I route I should get
+            | from | to | route | distance |
+            | b    | d  | abcde | 200m +-2 |
+            | d    | b  |       |          |
+
+    Scenario: North-south oneways crossing the origin
+        Given the node locations
+            | node | lat | lon                    |
+            | a    | 0   | -0.0017981358725409223 |
+            | b    | 0   | -0.0008990679362704611 |
+            | c    | 0   | 0                      |
+            | d    | 0   | 0.0008990679362704611  |
+            | e    | 0   | 0.0017981358725409223  |
+
+        And the ways
+            | nodes | oneway |
+            | abcde | yes    |
+
+        When I route I should get
+            | from | to | route | distance |
+            | b    | d  | abcde | 200m +-2 |
+            | d    | b  |       |          |
diff --git a/features/testbot/overlap.feature b/features/testbot/overlap.feature
new file mode 100644
index 0000000..509867f
--- /dev/null
+++ b/features/testbot/overlap.feature
@@ -0,0 +1,39 @@
+ at routing @testbot @overlap
+Feature: Testbot - overlapping ways
+ 
+    Background:
+        Given the profile "testbot"
+
+    @bug @610
+    Scenario: Testbot - multiple way between same nodes 
+    Note that cb is connecting the same two nodes as bc
+        Given the node map
+            | a | b | c | d |
+
+        And the ways
+            | nodes | highway   |
+            | ab    | primary   |
+            | bc    | primary   |
+            | cd    | primary   |
+            | cb    | secondary |
+
+        When I route I should get
+            | from | to | route    |
+            | a    | d  | ab,bc,cd |
+            | d    | a  | cd,bc,ab |
+    
+    @bug @610
+    Scenario: Testbot - area on top of way
+        Given the node map
+            | x | a | b | y |
+            |   | d | c |   |
+
+        And the ways
+            | nodes | highway   | area |
+            | xaby  | primary   |      |
+            | abcda | secondary | yes  |
+
+        When I route I should get
+            | from | to | route |
+            | x    | y  | xaby  |
+            | y    | x  | xaby  |
diff --git a/features/testbot/penalty.feature b/features/testbot/penalty.feature
index 97d5e6a..85f43c7 100644
--- a/features/testbot/penalty.feature
+++ b/features/testbot/penalty.feature
@@ -1,168 +1,168 @@
 @routing @penalty @signal
 Feature: Penalties
-Testbot uses a signal penalty of 7s.
-
-	Background:
-		Given the profile "testbot"
-
-	Scenario: Traffic signals should incur a delay, without changing distance
-		Given the node map
-		 | a | b | c |
-		 | d | e | f |
-
-		And the nodes
-		 | node | highway         |
-		 | e    | traffic_signals |
-
-		And the ways
-		 | nodes |
-		 | abc   |
-		 | def   |
-
-		When I route I should get
-		 | from | to | route | time    | distance |
-		 | a    | c  | abc   | 20s +-1 | 200m +-1 |
-		 | d    | f  | def   | 27s +-1 | 200m +-1 |
-
-	Scenario: Signal penalty should not depend on way type
-		Given the node map
-		 | a | b | c |
-		 | d | e | f |
-		 | g | h | i |
-
-		And the nodes
-		 | node | highway         |
-		 | b    | traffic_signals |
-		 | e    | traffic_signals |
-		 | h    | traffic_signals |
-
-		And the ways
-		 | nodes | highway   |
-		 | abc   | primary   |
-		 | def   | secondary |
-		 | ghi   | tertiary  |
-
-		When I route I should get
-		 | from | to | route | time    |
-		 | a    | c  | abc   | 27s +-1 |
-		 | d    | f  | def   | 47s +-1 |
-		 | g    | i  | ghi   | 67s +-1 |
-
-	Scenario: Passing multiple traffic signals should incur a accumulated delay
-		Given the node map
-		 | a | b | c | d | e |
-
-		And the nodes
-		 | node | highway         |
-		 | b    | traffic_signals |
-		 | c    | traffic_signals |
-		 | d    | traffic_signals |
-
-		And the ways
-		 | nodes  |
-		 | abcde |
-
-		When I route I should get
-		 | from | to | route | time    |
-		 | a    | e  | abcde | 61s +-1 |
-
-		@todo
-		Scenario: Signal penalty should not depend on way type
-			Given the node map
-			 | a | b | c |
-			 | d | e | f |
-			 | g | h | i |
-
-			And the nodes
-			 | node | highway         |
-			 | b    | traffic_signals |
-			 | e    | traffic_signals |
-			 | h    | traffic_signals |
-
-			And the ways
-			 | nodes | highway   |
-			 | abc   | primary   |
-			 | def   | secondary |
-			 | ghi   | tertiary  |
-
-			When I route I should get
-			 | from | to | route | time    |
-			 | a    | b  | abc   | 10s +-1 |
-			 | a    | c  | abc   | 27s +-1 |
-			 | d    | e  | def   | 20s +-1 |
-			 | d    | f  | def   | 47s +-1 |
-			 | g    | h  | ghi   | 30s +-1 |
-			 | g    | i  | ghi   | 67s +-1 |
-
-		Scenario: Passing multiple traffic signals should incur a accumulated delay
-			Given the node map
-			 | a | b | c | d | e |
-
-			And the nodes
-			 | node | highway         |
-			 | b    | traffic_signals |
-			 | c    | traffic_signals |
-			 | d    | traffic_signals |
-
-			And the ways
-			 | nodes  |
-			 | abcde |
-
-			When I route I should get
-			 | from | to | route | time    |
-			 | a    | e  | abcde | 61s +-1 |
-
-	@todo
-	Scenario: Starting or ending at a traffic signal should not incur a delay
-		Given the node map
-		 | a | b | c |
-
-		And the nodes
-		 | node | highway         |
-		 | b    | traffic_signals |
-
-		And the ways
-		 | nodes |
-		 | abc   |
-
-		When I route I should get
-		 | from | to | route | time    |
-		 | a    | b  | abc   | 10s +-1 |
-		 | b    | a  | abc   | 10s +-1 |
-
-	Scenario: Routing between signals on the same way should not incur a delay
-		Given the node map
-		 | a | b | c | d |
-
-		And the nodes
-		 | node | highway         |
-		 | a    | traffic_signals |
-		 | d    | traffic_signals |
-
-		And the ways
-		 | nodes | highway |
-		 | abcd  | primary |
-
-		When I route I should get
-		 | from | to | route | time    |
-		 | b    | c  | abcd  | 10s +-1 |
-		 | c    | b  | abcd  | 10s +-1 |
-
-	Scenario: Prefer faster route without traffic signals
-		Given a grid size of 50 meters
-		And the node map
-		 | a |  | b |  | c |
-		 |   |  | d |  |   |
-
-		And the nodes
-		 | node | highway         |
-		 | b    | traffic_signals |
-
-		And the ways
-		 | nodes | highway |
-		 | abc   | primary |
-		 | adc   | primary |
-
-		When I route I should get
-		 | from | to | route |
-		 | a    | c  | adc   |
\ No newline at end of file
+# Testbot uses a signal penalty of 7s.
+
+    Background:
+        Given the profile "testbot"
+
+    Scenario: Traffic signals should incur a delay, without changing distance
+        Given the node map
+            | a | b | c |
+            | d | e | f |
+
+        And the nodes
+            | node | highway         |
+            | e    | traffic_signals |
+
+        And the ways
+            | nodes |
+            | abc   |
+            | def   |
+
+        When I route I should get
+            | from | to | route | time    | distance |
+            | a    | c  | abc   | 20s +-1 | 200m +-1 |
+            | d    | f  | def   | 27s +-1 | 200m +-1 |
+
+    Scenario: Signal penalty should not depend on way type
+        Given the node map
+            | a | b | c |
+            | d | e | f |
+            | g | h | i |
+
+        And the nodes
+            | node | highway         |
+            | b    | traffic_signals |
+            | e    | traffic_signals |
+            | h    | traffic_signals |
+
+        And the ways
+            | nodes | highway   |
+            | abc   | primary   |
+            | def   | secondary |
+            | ghi   | tertiary  |
+
+        When I route I should get
+            | from | to | route | time    |
+            | a    | c  | abc   | 27s +-1 |
+            | d    | f  | def   | 47s +-1 |
+            | g    | i  | ghi   | 67s +-1 |
+
+    Scenario: Passing multiple traffic signals should incur a accumulated delay
+        Given the node map
+            | a | b | c | d | e |
+
+        And the nodes
+            | node | highway         |
+            | b    | traffic_signals |
+            | c    | traffic_signals |
+            | d    | traffic_signals |
+
+        And the ways
+            | nodes |
+            | abcde |
+
+        When I route I should get
+            | from | to | route | time    |
+            | a    | e  | abcde | 61s +-1 |
+
+        @todo
+        Scenario: Signal penalty should not depend on way type
+            Given the node map
+                | a | b | c |
+                | d | e | f |
+                | g | h | i |
+
+            And the nodes
+                | node | highway         |
+                | b    | traffic_signals |
+                | e    | traffic_signals |
+                | h    | traffic_signals |
+
+            And the ways
+                | nodes | highway   |
+                | abc   | primary   |
+                | def   | secondary |
+                | ghi   | tertiary  |
+
+            When I route I should get
+                | from | to | route | time    |
+                | a    | b  | abc   | 10s +-1 |
+                | a    | c  | abc   | 27s +-1 |
+                | d    | e  | def   | 20s +-1 |
+                | d    | f  | def   | 47s +-1 |
+                | g    | h  | ghi   | 30s +-1 |
+                | g    | i  | ghi   | 67s +-1 |
+
+        Scenario: Passing multiple traffic signals should incur a accumulated delay
+            Given the node map
+                | a | b | c | d | e |
+
+            And the nodes
+                | node | highway         |
+                | b    | traffic_signals |
+                | c    | traffic_signals |
+                | d    | traffic_signals |
+
+            And the ways
+                | nodes |
+                | abcde |
+
+            When I route I should get
+                | from | to | route | time    |
+                | a    | e  | abcde | 61s +-1 |
+
+    @todo
+    Scenario: Starting or ending at a traffic signal should not incur a delay
+        Given the node map
+            | a | b | c |
+
+        And the nodes
+            | node | highway         |
+            | b    | traffic_signals |
+
+        And the ways
+            | nodes |
+            | abc   |
+
+        When I route I should get
+            | from | to | route | time    |
+            | a    | b  | abc   | 10s +-1 |
+            | b    | a  | abc   | 10s +-1 |
+
+    Scenario: Routing between signals on the same way should not incur a delay
+        Given the node map
+            | a | b | c | d |
+
+        And the nodes
+            | node | highway         |
+            | a    | traffic_signals |
+            | d    | traffic_signals |
+
+        And the ways
+            | nodes | highway |
+            | abcd  | primary |
+
+        When I route I should get
+            | from | to | route | time    |
+            | b    | c  | abcd  | 10s +-1 |
+            | c    | b  | abcd  | 10s +-1 |
+
+    Scenario: Prefer faster route without traffic signals
+        Given a grid size of 50 meters
+        And the node map
+            | a |  | b |  | c |
+            |   |  | d |  |   |
+
+        And the nodes
+            | node | highway         |
+            | b    | traffic_signals |
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | adc   | primary |
+
+        When I route I should get
+            | from | to | route |
+            | a    | c  | adc   |
diff --git a/features/testbot/planetary.feature b/features/testbot/planetary.feature
index 242ba8b..f2ba21e 100644
--- a/features/testbot/planetary.feature
+++ b/features/testbot/planetary.feature
@@ -1,86 +1,86 @@
 @routing @planetary
 Feature: Distance calculation
- 
-	Scenario: Approximated Longitudinal distances at equator
-		Given the node locations
-		 | node | lat | lon |
-		 | a    | 0   | 80  |
-		 | b    | 0   | 0   |
-
-		And the ways
-		 | nodes |
-		 | ab    |
-
-		When I route I should get
-		 | from | to | route | distance       |
-		 | a    | b  | ab    | 8905559m ~0.1% |
-
-	Scenario: Approximated Longitudinal distances at latitude 45
-		Given the node locations
-		 | node | lat | lon |
-		 | c    | 45   | 80 |
-		 | d    | 45   | 0  |
-
-		And the ways
-		 | nodes |
-		 | cd    |
-
-		When I route I should get
-		 | from | to | route | distance       |
-		 | c    | d  | cd    | 6028844m ~4.5% |
-
-	Scenario: Approximated Longitudinal distances at latitude 80
-		Given the node locations
-		 | node | lat | lon |
-		 | c    | 80   | 80 |
-		 | d    | 80   | 0  |
-
-		And the ways
-		 | nodes |
-		 | cd    |
-
-		When I route I should get
-		 | from | to | route | distance       |
-		 | c    | d  | cd    | 1431469m ~9.5% |
-
-	Scenario: Approximated Latitudinal distances at longitude 0
-		Given the node locations
-		 | node | lat | lon |
-		 | a    | 80  | 0   |
-		 | b    | 0   | 0   |
-
-		And the ways
-		 | nodes |
-		 | ab    |
-
-		When I route I should get
-		 | from | to | route | distance       |
-		 | a    | b  | ab    | 8905559m ~0.1% |
-
-	Scenario: Approximated Latitudinal distances at longitude 45
-		Given the node locations
-		 | node | lat | lon |
-		 | a    | 80  | 45   |
-		 | b    | 0   | 45   |
-
-		And the ways
-		 | nodes |
-		 | ab    |
-
-		When I route I should get
-		 | from | to | route | distance       |
-		 | a    | b  | ab    | 8905559m ~0.1% |
-
-	Scenario: Approximated Latitudinal distances at longitude 80
-		Given the node locations
-		 | node | lat | lon |
-		 | a    | 80  | 80   |
-		 | b    | 0   | 80   |
-
-		And the ways
-		 | nodes |
-		 | ab    |
-
-		When I route I should get
-		 | from | to | route | distance       |
-		 | a    | b  | ab    | 8905559m ~0.1% |
+
+    Scenario: Approximated Longitudinal distances at equator
+        Given the node locations
+            | node | lat | lon |
+            | a    | 0   | 80  |
+            | b    | 0   | 0   |
+
+        And the ways
+            | nodes |
+            | ab    |
+
+        When I route I should get
+            | from | to | route | distance       |
+            | a    | b  | ab    | 8905559m ~0.1% |
+
+    Scenario: Approximated Longitudinal distances at latitude 45
+        Given the node locations
+            | node | lat | lon |
+            | c    | 45  | 80  |
+            | d    | 45  | 0   |
+
+        And the ways
+            | nodes |
+            | cd    |
+
+        When I route I should get
+            | from | to | route | distance       |
+            | c    | d  | cd    | 6028844m ~4.5% |
+
+    Scenario: Approximated Longitudinal distances at latitude 80
+        Given the node locations
+            | node | lat | lon |
+            | c    | 80  | 80  |
+            | d    | 80  | 0   |
+
+        And the ways
+            | nodes |
+            | cd    |
+
+        When I route I should get
+            | from | to | route | distance       |
+            | c    | d  | cd    | 1431469m ~9.5% |
+
+    Scenario: Approximated Latitudinal distances at longitude 0
+        Given the node locations
+            | node | lat | lon |
+            | a    | 80  | 0   |
+            | b    | 0   | 0   |
+
+        And the ways
+            | nodes |
+            | ab    |
+
+        When I route I should get
+            | from | to | route | distance       |
+            | a    | b  | ab    | 8905559m ~0.1% |
+
+    Scenario: Approximated Latitudinal distances at longitude 45
+        Given the node locations
+            | node | lat | lon |
+            | a    | 80  | 45  |
+            | b    | 0   | 45  |
+
+        And the ways
+            | nodes |
+            | ab    |
+
+        When I route I should get
+            | from | to | route | distance       |
+            | a    | b  | ab    | 8905559m ~0.1% |
+
+    Scenario: Approximated Latitudinal distances at longitude 80
+        Given the node locations
+            | node | lat | lon |
+            | a    | 80  | 80  |
+            | b    | 0   | 80  |
+
+        And the ways
+            | nodes |
+            | ab    |
+
+        When I route I should get
+            | from | to | route | distance       |
+            | a    | b  | ab    | 8905559m ~0.1% |
diff --git a/features/testbot/projection.feature b/features/testbot/projection.feature
new file mode 100644
index 0000000..ed2f2fc
--- /dev/null
+++ b/features/testbot/projection.feature
@@ -0,0 +1,38 @@
+ at routing @projection
+Feature: Projection to nearest point on road
+# Waypoints are projected perpendiculary onto the closest road
+
+    Background:
+    # The coordinas below was calculated using http://www.movable-type.co.uk/scripts/latlong.html
+    # The nodes are placed as follows, with ab, bc and bd all being 1 km in length each:
+    #   |   |   | c |
+    #   |   | b |   |   (this is sketch only, real data is in the table below)
+    #   | a |   | d |
+
+        Given the profile "testbot"
+        Given the node locations
+            | node | lat      | lon     |
+            | a    | 80.00000 | 0.00000 |
+            | b    | 80.00639 | 0.03667 |
+            | c    | 80.01278 | 0.07333 |
+            | d    | 80.00000 | 0.07333 |
+
+        And the ways
+            | nodes |
+            | abc   |
+
+    Scenario: Projection onto way at high latitudes, 1km distance
+        When I route I should get
+            | from | to | route | compass | bearing | distance  |
+            | b    | a  | abc   | SW      | 225     | 1000m +-7 |
+            | b    | c  | abc   | NE      | 45      | 1000m +-7 |
+            | a    | d  | abc   | NE      | 45      | 1000m +-7 |
+            | d    | a  | abc   | SW      | 225     | 1000m +-7 |
+            | c    | d  | abc   | SW      | 225     | 1000m +-8 |
+            | d    | c  | abc   | NE      | 45  +-5 | 1000m +-8 |
+
+    Scenario: Projection onto way at high latitudes, no distance
+        When I route I should get
+            | from | to | route | distance |
+            | d    | b  | abc   | 0m  +-5  |
+            | b    | d  | abc   | 0m  +-5  |
diff --git a/features/testbot/protobuffer.feature b/features/testbot/protobuffer.feature
new file mode 100644
index 0000000..a77ff34
--- /dev/null
+++ b/features/testbot/protobuffer.feature
@@ -0,0 +1,156 @@
+ at routing @pbf
+Feature: Importing protobuffer (.pbf) format
+# Test normally read .osm, which is faster than .pbf files,
+# since we don't need to use osmosis to first convert to .pbf
+# The scenarios in this file test the ability to import .pbf files,
+# including nodes, way, restictions, and a various special situations.
+
+    Background:
+        Given the profile "testbot"
+        And the import format "pbf"
+
+    Scenario: Testbot - Protobuffer import, nodes and ways
+        Given the node map
+            |   |   |   | d |
+            | a | b | c |   |
+            |   |   |   | e |
+
+        And the ways
+            | nodes | highway | oneway |
+            | abc   | primary |        |
+            | cd    | primary | yes    |
+            | ce    | river   |        |
+            | de    | primary |        |
+
+        When I route I should get
+            | from | to | route |
+            | d    | c  | de,ce |
+            | e    | d  | de    |
+
+
+    Scenario: Testbot - Protobuffer import, turn restiction relations
+        Given the node map
+            |   | n |   |
+            | w | j | e |
+            |   | s |   |
+
+        And the ways
+            | nodes | oneway |
+            | sj    | yes    |
+            | nj    | -1     |
+            | wj    | -1     |
+            | ej    | -1     |
+
+        And the relations
+            | type        | way:from | way:to | node:via | restriction  |
+            | restriction | sj       | wj     | j        | no_left_turn |
+
+        When I route I should get
+            | from | to | route |
+            | s    | w  |       |
+            | s    | n  | sj,nj |
+            | s    | e  | sj,ej |
+
+
+    Scenario: Testbot - Protobuffer import, distances at longitude 45
+        Given the node locations
+            | node | lat | lon |
+            | a    | 80  | 45  |
+            | b    | 0   | 45  |
+
+        And the ways
+            | nodes |
+            | ab    |
+
+        When I route I should get
+            | from | to | route | distance       |
+            | a    | b  | ab    | 8905559m ~0.1% |
+
+    Scenario: Testbot - Protobuffer import, distances at longitude 80
+        Given the node locations
+            | node | lat | lon |
+            | a    | 80  | 80  |
+            | b    | 0   | 80  |
+
+        And the ways
+            | nodes |
+            | ab    |
+
+        When I route I should get
+            | from | to | route | distance       |
+            | a    | b  | ab    | 8905559m ~0.1% |
+
+    Scenario: Testbot - Protobuffer import, empty dataset
+        Given the node map
+            |  |
+
+        Given the ways
+            | nodes |
+
+        When the data has been prepared
+        Then "osrm-extract" should return code 1
+
+
+    Scenario: Testbot - Protobuffer import, streetnames with UTF characters
+        Given the node map
+            | a | b | c | d |
+
+        And the ways
+            | nodes | name                   |
+            | ab    | Scandinavian København |
+            | bc    | Japanese 東京            |
+            | cd    | Cyrillic Москва        |
+
+        When I route I should get
+            | from | to | route                  |
+            | a    | b  | Scandinavian København |
+            | b    | c  | Japanese 東京            |
+            | c    | d  | Cyrillic Москва        |
+
+    Scenario: Testbot - Protobuffer import, bearing af 45 degree intervals
+        Given the node map
+            | b | a | h |
+            | c | x | g |
+            | d | e | f |
+
+        And the ways
+            | nodes |
+            | xa    |
+            | xb    |
+            | xc    |
+            | xd    |
+            | xe    |
+            | xf    |
+            | xg    |
+            | xh    |
+
+        When I route I should get
+            | from | to | route | compass | bearing |
+            | x    | a  | xa    | N       | 0       |
+            | x    | b  | xb    | NW      | 315     |
+            | x    | c  | xc    | W       | 270     |
+            | x    | d  | xd    | SW      | 225     |
+            | x    | e  | xe    | S       | 180     |
+            | x    | f  | xf    | SE      | 135     |
+            | x    | g  | xg    | E       | 90      |
+            | x    | h  | xh    | NE      | 45      |
+
+
+    Scenario: Testbot - Protobuffer import, rraffic signals should incur a delay
+        Given the node map
+            | a | b | c |
+            | d | e | f |
+
+        And the nodes
+            | node | highway         |
+            | e    | traffic_signals |
+
+        And the ways
+            | nodes |
+            | abc   |
+            | def   |
+
+        When I route I should get
+            | from | to | route | time    | distance |
+            | a    | c  | abc   | 20s +-1 | 200m +-1 |
+            | d    | f  | def   | 27s +-1 | 200m +-1 |
diff --git a/features/testbot/roundabout.feature b/features/testbot/roundabout.feature
new file mode 100644
index 0000000..570b14b
--- /dev/null
+++ b/features/testbot/roundabout.feature
@@ -0,0 +1,76 @@
+ at routing @testbot @roundabout @instruction
+Feature: Roundabout Instructions
+
+    Background:
+        Given the profile "testbot"
+
+    Scenario: Testbot - Roundabout
+        Given the node map
+            |   |   | v |   |   |
+            |   |   | d |   |   |
+            | s | a |   | c | u |
+            |   |   | b |   |   |
+            |   |   | t |   |   |
+
+        And the ways
+            | nodes | junction   |
+            | sa    |            |
+            | tb    |            |
+            | uc    |            |
+            | vd    |            |
+            | abcda | roundabout |
+
+        When I route I should get
+            | from | to | route | turns                               |
+            | s    | t  | sa,tb | head,enter_roundabout-1,destination |
+            | s    | u  | sa,uc | head,enter_roundabout-2,destination |
+            | s    | v  | sa,vd | head,enter_roundabout-3,destination |
+            | t    | u  | tb,uc | head,enter_roundabout-1,destination |
+            | t    | v  | tb,vd | head,enter_roundabout-2,destination |
+            | t    | s  | tb,sa | head,enter_roundabout-3,destination |
+            | u    | v  | uc,vd | head,enter_roundabout-1,destination |
+            | u    | s  | uc,sa | head,enter_roundabout-2,destination |
+            | u    | t  | uc,tb | head,enter_roundabout-3,destination |
+            | v    | s  | vd,sa | head,enter_roundabout-1,destination |
+            | v    | t  | vd,tb | head,enter_roundabout-2,destination |
+            | v    | u  | vd,uc | head,enter_roundabout-3,destination |
+
+    Scenario: Testbot - Roundabout with oneway links
+        Given the node map
+            |   |   | p | o |   |   |
+            |   |   | h | g |   |   |
+            | i | a |   |   | f | n |
+            | j | b |   |   | e | m |
+            |   |   | c | d |   |   |
+            |   |   | k | l |   |   |
+
+        And the ways
+            | nodes     | junction   | oneway |
+            | ai        |            | yes    |
+            | jb        |            | yes    |
+            | ck        |            | yes    |
+            | ld        |            | yes    |
+            | em        |            | yes    |
+            | nf        |            | yes    |
+            | go        |            | yes    |
+            | ph        |            | yes    |
+            | abcdefgha | roundabout |        |
+
+        When I route I should get
+            | from | to | route | turns                               |
+            | j    | k  | jb,ck | head,enter_roundabout-1,destination |
+            | j    | m  | jb,em | head,enter_roundabout-2,destination |
+            | j    | o  | jb,go | head,enter_roundabout-3,destination |
+            | j    | i  | jb,ai | head,enter_roundabout-4,destination |
+            | l    | m  | ld,em | head,enter_roundabout-1,destination |
+            | l    | o  | ld,go | head,enter_roundabout-2,destination |
+            | l    | i  | ld,ai | head,enter_roundabout-3,destination |
+            | l    | k  | ld,ck | head,enter_roundabout-4,destination |
+            | n    | o  | nf,go | head,enter_roundabout-1,destination |
+            | n    | i  | nf,ai | head,enter_roundabout-2,destination |
+            | n    | k  | nf,ck | head,enter_roundabout-3,destination |
+            | n    | m  | nf,em | head,enter_roundabout-4,destination |
+            | p    | i  | ph,ai | head,enter_roundabout-1,destination |
+            | p    | k  | ph,ck | head,enter_roundabout-2,destination |
+            | p    | m  | ph,em | head,enter_roundabout-3,destination |
+            | p    | o  | ph,go | head,enter_roundabout-4,destination |
diff --git a/features/testbot/routes.feature b/features/testbot/routes.feature
index 763b347..bc1d75e 100644
--- a/features/testbot/routes.feature
+++ b/features/testbot/routes.feature
@@ -1,35 +1,35 @@
 @routing @testbot @routes @todo
 Feature: OSM Route Relation
 
-	Background:
-		Given the profile "testbot"
-	
-	Scenario: Prioritize ways that are part of route relations
-	This scenario assumes that the testbot uses an impedance of 0.5 for ways that are part of 'testbot' routes.
-	
-		Given the node map
-		 | s |  |  | t |  |  |   |
-		 | a |  |  | b |  |  | c |
-		 |   |  |  |   |  |  |   |
-		 |   |  |  | u |  |  | v |
+    Background:
+        Given the profile "testbot"
 
-		And the ways
-		 | nodes |
-		 | ab    |
-		 | bc    |
-		 | as    |
-		 | stb   |
-		 | bu    |
-		 | uvc   |
+    Scenario: Prioritize ways that are part of route relations
+    # This scenario assumes that the testbot uses an impedance of 0.5 for ways that are part of 'testbot' routes.
 
-   		And the relations
-		 | type  | route   | way:route |
-		 | route | testbot | as,stb    |
-		 | route | testbot | bu,uvc    |
+        Given the node map
+            | s |  |  | t |  |  |   |
+            | a |  |  | b |  |  | c |
+            |   |  |  |   |  |  |   |
+            |   |  |  | u |  |  | v |
 
-		When I route I should get
-		 | from | to | route  | distance | time    |
-		 | b    | c  | bc     | 300m +-1 | 30s +-1 |
-		 | c    | b  | bc     | 300m +-1 | 30s +-1 |
-		 | a    | b  | as,stb | 500m +-1 | 50s +-1 |
-		 | b    | a  | stb,as | 500m +-1 | 50s +-1 |
\ No newline at end of file
+        And the ways
+            | nodes |
+            | ab    |
+            | bc    |
+            | as    |
+            | stb   |
+            | bu    |
+            | uvc   |
+
+        And the relations
+            | type  | route   | way:route |
+            | route | testbot | as,stb    |
+            | route | testbot | bu,uvc    |
+
+        When I route I should get
+            | from | to | route  | distance | time    |
+            | b    | c  | bc     | 300m +-1 | 30s +-1 |
+            | c    | b  | bc     | 300m +-1 | 30s +-1 |
+            | a    | b  | as,stb | 500m +-1 | 50s +-1 |
+            | b    | a  | stb,as | 500m +-1 | 50s +-1 |
diff --git a/features/testbot/snap.feature b/features/testbot/snap.feature
index bb3156d..c8a04bf 100644
--- a/features/testbot/snap.feature
+++ b/features/testbot/snap.feature
@@ -1,154 +1,154 @@
 @routing @snap
-Feature: Snap start/end point to the nearest way 
-	
-	Background:
-		Given the profile "testbot"
-	
-	Scenario: Snap to nearest protruding oneway
-		Given the node map
-		 |   | 1 |   | 2 |   |
-		 | 8 |   | n |   | 3 |
-		 |   | w | c | e |   |
-		 | 7 |   | s |   | 4 |
-		 |   | 6 |   | 5 |   |
-
-		And the ways
-		 | nodes |
-		 | nc    |
-		 | ec    |
-		 | sc    |
-		 | wc    |
-
-		When I route I should get
-		 | from | to | route |
-		 | 1    | c  | nc    |
-		 | 2    | c  | nc    |
-		 | 3    | c  | ec    |
-		 | 4    | c  | ec    |
-		 | 5    | c  | sc    |
-		 | 6    | c  | sc    |
-		 | 7    | c  | wc    |
-		 | 8    | c  | wc    |
-	
-	Scenario: Snap to nearest edge of a square
-		Given the node map
-		 | 4 | 5 | 6 | 7 |
-		 | 3 | a |   | u |
-		 | 2 |   |   |   |
-		 | 1 | d |   | b |
-
-		And the ways
-		 | nodes |
-		 | aub   |
-		 | adb   |
-
-		When I route I should get
-		 | from | to | route |
-		 | 1    | b  | adb   |
-		 | 2    | b  | adb   |
-		 | 6    | b  | aub   |
-		 | 7    | b  | aub   |
-
-	Scenario: Snap to edge right under start/end point
-		Given the node map
-		 | d | e | f | g |
-		 | c |   |   | h |
-		 | b |   |   | i |
-		 | a | l | k | j |
-
-		And the ways
-		 | nodes |
-		 | abcd  |
-		 | defg  |
-		 | ghij  |
-		 | jkla  |
-
-		When I route I should get
-		 | from | to | route     |
-		 | a    | b  | abcd      |
-		 | a    | c  | abcd      |
-		 | a    | d  | abcd      |
-		 | a    | e  | abcd,defg |
-		 | a    | f  | abcd,defg |
-		 | a    | h  | jkla,ghij |
-		 | a    | i  | jkla,ghij |
-		 | a    | j  | jkla      |
-		 | a    | k  | jkla      |
-		 | a    | l  | jkla      |
-
-	Scenario: Snap to correct way at large scales 
-		Given a grid size of 1000 meters
-		Given the node map
-		 |   |   |   | a |
-		 | x |   |   | b |
-		 |   |   |   | c |
-
-		And the ways
-		 | nodes |
-		 | xa    |
-		 | xb    |
-		 | xc    |
-
-		When I route I should get
-		 | from | to | route |
-		 | x    | a  | xa    |
-		 | x    | b  | xb    |
-		 | x    | c  | xc    |
-		 | a    | x  | xa    |
-		 | b    | x  | xb    |
-		 | c    | x  | xc    |
-	
-	Scenario: Find edges within 1km, and the same from 10km
-		Given a grid size of 1000 meters
-		Given the node map
-		 | p |   |   |   |   |   |   |   |   |   |   | i |   |   |   |   |   |   |   |   |   |   | j |
-		 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
-		 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
-		 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
-		 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
-		 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
-		 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
-		 |   |   |   |   |   |   |   |   |   | 8 |   | 1 |   | 2 |   |   |   |   |   |   |   |   |   |
-		 |   |   |   |   |   |   |   |   |   |   | h | a | b |   |   |   |   |   |   |   |   |   |   |
-		 | o |   |   |   |   |   |   |   |   | 7 | g | x | c | 3 |   |   |   |   |   |   |   |   | k |
-		 |   |   |   |   |   |   |   |   |   |   | f | e | d |   |   |   |   |   |   |   |   |   |   |
-		 |   |   |   |   |   |   |   |   |   | 6 |   | 5 |   | 4 |   |   |   |   |   |   |   |   |   |
-		 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
-		 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
-		 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
-		 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
-		 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
-		 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
-		 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
-		 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
-		 | n |   |   |   |   |   |   |   |   |   |   | m |   |   |   |   |   |   |   |   |   |   | l |
-
-		Given the ways
-		 | nodes |
-		 | xa    |
-		 | xb    |
-		 | xc    |
-		 | xd    |
-		 | xe    |
-		 | xf    |
-		 | xg    |
-		 | xh    |
-
-		When I route I should get
-		 | from | to | route |
-		 | x    | 1  | xa    |
-		 | x    | 2  | xb    |
-		 | x    | 3  | xc    |
-		 | x    | 4  | xd    |
-		 | x    | 5  | xe    |
-		 | x    | 6  | xf    |
-		 | x    | 7  | xg    |
-		 | x    | 8  | xh    |
-		 | x    | i  | xa    |
-		 | x    | j  | xb    |
-		 | x    | k  | xc    |
-		 | x    | l  | xd    |
-		 | x    | m  | xe    |
-		 | x    | n  | xf    |
-		 | x    | o  | xg    |
-		 | x    | p  | xh    |
\ No newline at end of file
+Feature: Snap start/end point to the nearest way
+
+    Background:
+        Given the profile "testbot"
+
+    Scenario: Snap to nearest protruding oneway
+        Given the node map
+            |   | 1 |   | 2 |   |
+            | 8 |   | n |   | 3 |
+            |   | w | c | e |   |
+            | 7 |   | s |   | 4 |
+            |   | 6 |   | 5 |   |
+
+        And the ways
+            | nodes |
+            | nc    |
+            | ec    |
+            | sc    |
+            | wc    |
+
+        When I route I should get
+            | from | to | route |
+            | 1    | c  | nc    |
+            | 2    | c  | nc    |
+            | 3    | c  | ec    |
+            | 4    | c  | ec    |
+            | 5    | c  | sc    |
+            | 6    | c  | sc    |
+            | 7    | c  | wc    |
+            | 8    | c  | wc    |
+
+    Scenario: Snap to nearest edge of a square
+        Given the node map
+            | 4 | 5 | 6 | 7 |
+            | 3 | a |   | u |
+            | 2 |   |   |   |
+            | 1 | d |   | b |
+
+        And the ways
+            | nodes |
+            | aub   |
+            | adb   |
+
+        When I route I should get
+            | from | to | route |
+            | 1    | b  | adb   |
+            | 2    | b  | adb   |
+            | 6    | b  | aub   |
+            | 7    | b  | aub   |
+
+    Scenario: Snap to edge right under start/end point
+        Given the node map
+            | d | e | f | g |
+            | c |   |   | h |
+            | b |   |   | i |
+            | a | l | k | j |
+
+        And the ways
+            | nodes |
+            | abcd  |
+            | defg  |
+            | ghij  |
+            | jkla  |
+
+        When I route I should get
+            | from | to | route     |
+            | a    | b  | abcd      |
+            | a    | c  | abcd      |
+            | a    | d  | abcd      |
+            | a    | e  | abcd,defg |
+            | a    | f  | abcd,defg |
+            | a    | h  | jkla,ghij |
+            | a    | i  | jkla,ghij |
+            | a    | j  | jkla      |
+            | a    | k  | jkla      |
+            | a    | l  | jkla      |
+
+    Scenario: Snap to correct way at large scales
+        Given a grid size of 1000 meters
+        Given the node map
+            |   |  |  | a |
+            | x |  |  | b |
+            |   |  |  | c |
+
+        And the ways
+            | nodes |
+            | xa    |
+            | xb    |
+            | xc    |
+
+        When I route I should get
+            | from | to | route |
+            | x    | a  | xa    |
+            | x    | b  | xb    |
+            | x    | c  | xc    |
+            | a    | x  | xa    |
+            | b    | x  | xb    |
+            | c    | x  | xc    |
+
+    Scenario: Find edges within 1km, and the same from 10km
+        Given a grid size of 1000 meters
+        Given the node map
+            | p |  |  |  |  |  |  |  |  |   |   | i |   |   |  |  |  |  |  |  |  |  | j |
+            |   |  |  |  |  |  |  |  |  |   |   |   |   |   |  |  |  |  |  |  |  |  |   |
+            |   |  |  |  |  |  |  |  |  |   |   |   |   |   |  |  |  |  |  |  |  |  |   |
+            |   |  |  |  |  |  |  |  |  |   |   |   |   |   |  |  |  |  |  |  |  |  |   |
+            |   |  |  |  |  |  |  |  |  |   |   |   |   |   |  |  |  |  |  |  |  |  |   |
+            |   |  |  |  |  |  |  |  |  |   |   |   |   |   |  |  |  |  |  |  |  |  |   |
+            |   |  |  |  |  |  |  |  |  |   |   |   |   |   |  |  |  |  |  |  |  |  |   |
+            |   |  |  |  |  |  |  |  |  | 8 |   | 1 |   | 2 |  |  |  |  |  |  |  |  |   |
+            |   |  |  |  |  |  |  |  |  |   | h | a | b |   |  |  |  |  |  |  |  |  |   |
+            | o |  |  |  |  |  |  |  |  | 7 | g | x | c | 3 |  |  |  |  |  |  |  |  | k |
+            |   |  |  |  |  |  |  |  |  |   | f | e | d |   |  |  |  |  |  |  |  |  |   |
+            |   |  |  |  |  |  |  |  |  | 6 |   | 5 |   | 4 |  |  |  |  |  |  |  |  |   |
+            |   |  |  |  |  |  |  |  |  |   |   |   |   |   |  |  |  |  |  |  |  |  |   |
+            |   |  |  |  |  |  |  |  |  |   |   |   |   |   |  |  |  |  |  |  |  |  |   |
+            |   |  |  |  |  |  |  |  |  |   |   |   |   |   |  |  |  |  |  |  |  |  |   |
+            |   |  |  |  |  |  |  |  |  |   |   |   |   |   |  |  |  |  |  |  |  |  |   |
+            |   |  |  |  |  |  |  |  |  |   |   |   |   |   |  |  |  |  |  |  |  |  |   |
+            |   |  |  |  |  |  |  |  |  |   |   |   |   |   |  |  |  |  |  |  |  |  |   |
+            |   |  |  |  |  |  |  |  |  |   |   |   |   |   |  |  |  |  |  |  |  |  |   |
+            |   |  |  |  |  |  |  |  |  |   |   |   |   |   |  |  |  |  |  |  |  |  |   |
+            | n |  |  |  |  |  |  |  |  |   |   | m |   |   |  |  |  |  |  |  |  |  | l |
+
+        Given the ways
+            | nodes |
+            | xa    |
+            | xb    |
+            | xc    |
+            | xd    |
+            | xe    |
+            | xf    |
+            | xg    |
+            | xh    |
+
+        When I route I should get
+            | from | to | route |
+            | x    | 1  | xa    |
+            | x    | 2  | xb    |
+            | x    | 3  | xc    |
+            | x    | 4  | xd    |
+            | x    | 5  | xe    |
+            | x    | 6  | xf    |
+            | x    | 7  | xg    |
+            | x    | 8  | xh    |
+            | x    | i  | xa    |
+            | x    | j  | xb    |
+            | x    | k  | xc    |
+            | x    | l  | xd    |
+            | x    | m  | xe    |
+            | x    | n  | xf    |
+            | x    | o  | xg    |
+            | x    | p  | xh    |
diff --git a/features/testbot/speed.feature b/features/testbot/speed.feature
new file mode 100644
index 0000000..2eb3724
--- /dev/null
+++ b/features/testbot/speed.feature
@@ -0,0 +1,31 @@
+ at routing @speed @testbot
+Feature: Testbot - speeds
+
+    Background: Use specific speeds
+        Given the profile "testbot"
+
+    Scenario: Testbot - Speed on roads
+        Then routability should be
+            | highway   | bothw   |
+            | primary   | 36 km/h |
+            | unknown   | 24 km/h |
+            | secondary | 18 km/h |
+            | tertiary  | 12 km/h |
+
+    Scenario: Testbot - Speed on rivers, table
+        Then routability should be
+            | highway | forw    | backw   |
+            | river   | 36 km/h | 16 km/h |
+
+    Scenario: Testbot - Speed on rivers, map
+        Given the node map
+            | a | b |
+
+        And the ways
+            | nodes | highway |
+            | ab    | river   |
+
+        When I route I should get
+            | from | to | route | speed        | time | distance |
+            | a    | b  | ab    | 36 km/h      | 10s  | 100m     |
+            | b    | a  | ab    | 16 km/h +- 1 | 23s  | 100m     |
diff --git a/features/testbot/status.feature b/features/testbot/status.feature
new file mode 100644
index 0000000..4fa15eb
--- /dev/null
+++ b/features/testbot/status.feature
@@ -0,0 +1,67 @@
+ at routing @status
+Feature: Status messages
+
+    Background:
+        Given the profile "testbot"
+
+    Scenario: Route found
+        Given the node map
+            | a | b |
+
+        Given the ways
+            | nodes |
+            | ab    |
+
+        When I route I should get
+            | from | to | route | status | message                    |
+            | a    | b  | ab    | 0      | Found route between points |
+            | b    | a  | ab    | 0      | Found route between points |
+
+    Scenario: No route found
+        Given the node map
+            | a | b |
+            |   |   |
+            | c | d |
+
+        Given the ways
+            | nodes |
+            | ab    |
+            | cd    |
+
+        When I route I should get
+            | from | to | route | status | message                          |
+            | a    | b  | ab    | 0      | Found route between points       |
+            | c    | d  | cd    | 0      | Found route between points       |
+            | a    | c  |       | 207    | Cannot find route between points |
+            | b    | d  |       | 207    | Cannot find route between points |
+
+    Scenario: Malformed requests
+        Given the node locations
+            | node | lat  | lon  |
+            | a    | 1.00 | 1.00 |
+            | b    | 1.01 | 1.00 |
+
+        And the ways
+            | nodes |
+            | ab    |
+
+        When I route I should get
+            | request                     | status | message                                    |
+            | viaroute?loc=1,1&loc=1.01,1 | 0      | Found route between points                 |
+            | nonsense                    | 400    | Bad Request                                |
+            | nonsense?loc=1,1&loc=1.01,1 | 400    | Bad Request                                |
+            |                             | 400    | Query string malformed close to position 0 |
+            | /                           | 400    | Query string malformed close to position 0 |
+            | ?                           | 400    | Query string malformed close to position 0 |
+            | viaroute/loc=               | 400    | Query string malformed close to position 9 |
+            | viaroute/loc=1              | 400    | Query string malformed close to position 9 |
+            | viaroute/loc=1,1            | 400    | Query string malformed close to position 9 |
+            | viaroute/loc=1,1,1          | 400    | Query string malformed close to position 9 |
+            | viaroute/loc=x              | 400    | Query string malformed close to position 9 |
+            | viaroute/loc=x,y            | 400    | Query string malformed close to position 9 |
+            | viaroute/loc=1,1&loc=       | 400    | Query string malformed close to position 9 |
+            | viaroute/loc=1,1&loc=1      | 400    | Query string malformed close to position 9 |
+            | viaroute/loc=1,1&loc=1,1    | 400    | Query string malformed close to position 9 |
+            | viaroute/loc=1,1&loc=1,1,1  | 400    | Query string malformed close to position 9 |
+            | viaroute/loc=1,1&loc=x      | 400    | Query string malformed close to position 9 |
+            | viaroute/loc=1,1&loc=x,y    | 400    | Query string malformed close to position 9 |
diff --git a/features/testbot/time.feature b/features/testbot/time.feature
index b10544f..e0ccc37 100644
--- a/features/testbot/time.feature
+++ b/features/testbot/time.feature
@@ -1,215 +1,237 @@
 @routing @time
 Feature: Estimation of travel time
-Testbot speeds:
-Primary road:	36km/h = 36000m/3600s = 100m/10s
-Secondary road:	18km/h = 18000m/3600s = 100m/20s
-Tertiary road:	12km/h = 12000m/3600s = 100m/30s
-	
-	Background: Use specific speeds
-		Given the profile "testbot"
-	
-	Scenario: Basic travel time, 10m scale
-		Given a grid size of 10 meters
-		Given the node map
-		 | h | a | b |
-		 | g | x | c |
-		 | f | e | d |
-
-		And the ways
-		 | nodes | highway   |
-		 | xa    | primary   |
-		 | xb    | primary   |
-		 | xc    | primary   |
-		 | xd    | primary   |
-		 | xe    | primary   |
-		 | xf    | primary   |
-		 | xg    | primary   |
-		 | xh    | primary   |
-
-		When I route I should get
-		 | from | to | route | time   |
-		 | x    | a  | xa    | 1s +-1 |
-		 | x    | b  | xb    | 1s +-1 |
-		 | x    | c  | xc    | 1s +-1 |
-		 | x    | d  | xd    | 1s +-1 |
-		 | x    | e  | xe    | 1s +-1 |
-		 | x    | f  | xf    | 1s +-1 |
-		 | x    | g  | xg    | 1s +-1 |
-		 | x    | h  | xh    | 1s +-1 |
-
-	Scenario: Basic travel time, 100m scale
-		Given a grid size of 100 meters
-		Given the node map
-		 | h | a | b |
-		 | g | x | c |
-		 | f | e | d |
-
-		And the ways
-		 | nodes | highway   |
-		 | xa    | primary   |
-		 | xb    | primary   |
-		 | xc    | primary   |
-		 | xd    | primary   |
-		 | xe    | primary   |
-		 | xf    | primary   |
-		 | xg    | primary   |
-		 | xh    | primary   |
-	
-		When I route I should get
-		 | from | to | route | time    |
-		 | x    | a  | xa    | 10s +-1 |
-		 | x    | b  | xb    | 14s +-1 |
-		 | x    | c  | xc    | 10s +-1 |
-		 | x    | d  | xd    | 14s +-1 |
-		 | x    | e  | xe    | 10s +-1 |
-		 | x    | f  | xf    | 14s +-1 |
-		 | x    | g  | xg    | 10s +-1 |
-		 | x    | h  | xh    | 14s +-1 |
-
-	Scenario: Basic travel time, 1km scale
-		Given a grid size of 1000 meters
-		Given the node map
-		 | h | a | b |
-		 | g | x | c |
-		 | f | e | d |
-
-		And the ways
-		 | nodes | highway   |
-		 | xa    | primary   |
-		 | xb    | primary   |
-		 | xc    | primary   |
-		 | xd    | primary   |
-		 | xe    | primary   |
-		 | xf    | primary   |
-		 | xg    | primary   |
-		 | xh    | primary   |
-
-		When I route I should get
-		 | from | to | route | time     |
-		 | x    | a  | xa    | 100s +-1 |
-		 | x    | b  | xb    | 141s +-1 |
-		 | x    | c  | xc    | 100s +-1 |
-		 | x    | d  | xd    | 141s +-1 |
-		 | x    | e  | xe    | 100s +-1 |
-		 | x    | f  | xf    | 141s +-1 |
-		 | x    | g  | xg    | 100s +-1 |
-		 | x    | h  | xh    | 141s +-1 |
-
-	Scenario: Basic travel time, 10km scale
-		Given a grid size of 10000 meters
-		Given the node map
-		 | h | a | b |
-		 | g | x | c |
-		 | f | e | d |
-		
-		And the ways
-		 | nodes | highway   |
-		 | xa    | primary   |
-		 | xb    | primary   |
-		 | xc    | primary   |
-		 | xd    | primary   |
-		 | xe    | primary   |
-		 | xf    | primary   |
-		 | xg    | primary   |
-		 | xh    | primary   |
-		
-		When I route I should get
-		 | from | to | route | time      |
-		 | x    | a  | xa    | 1000s +-1 |
-		 | x    | b  | xb    | 1414s +-1 |
-		 | x    | c  | xc    | 1000s +-1 |
-		 | x    | d  | xd    | 1414s +-1 |
-		 | x    | e  | xe    | 1000s +-1 |
-		 | x    | f  | xf    | 1414s +-1 |
-		 | x    | g  | xg    | 1000s +-1 |
-		 | x    | h  | xh    | 1414s +-1 |
-
-	Scenario: Time of travel depending on way type
-		Given the node map
-		 | a | b |
-		 | c | d |
-		 | e | f |
-
-		And the ways
-		 | nodes | highway   |
-		 | ab    | primary   |
-		 | cd    | secondary |
-		 | ef    | tertiary  |
-		 | ace   | something |
-		
-		When I route I should get
-		 | from | to | route | time    |
-		 | a    | b  | ab    | 10s +-1 |
-		 | c    | d  | cd    | 20s +-1 |
-		 | e    | f  | ef    | 30s +-1 |
-
-	Scenario: Time of travel on a series of ways
-		Given the node map
-		 | a | b |   |
-		 |   | c | d |
-
-		And the ways
-		 | nodes | highway |
-		 | ab    | primary |
-		 | bc    | primary |
-		 | cd    | primary |
-
-		When I route I should get
-		 | from | to | route    | time    |
-		 | a    | b  | ab       | 10s +-1 |
-		 | a    | c  | ab,bc    | 20s +-1 |
-		 | a    | d  | ab,bc,cd | 30s +-1 |
-
-	Scenario: Time of travel on a winding way
-		Given the node map
-		 | a |   | i | h |
-		 | b | c |   | g |
-		 |   | d | e | f |
-
-		And the ways
-		 | nodes     | highway |
-		 | abcdefghi | primary |
-
-		When I route I should get
-		 | from | to | route     | time    |
-		 | a    | b  | abcdefghi | 10s +-1 |
-		 | a    | e  | abcdefghi | 40s +-1 |
-		 | a    | i  | abcdefghi | 80s +-1 |
-
-	Scenario: Time of travel on combination of road types
-		Given the node map
-		 | a | b | c |
-		 |   |   | d |
-		 |   |   | e |
-		
-		And the ways
-		 | nodes | highway   |
-		 | abc   | primary   |
-		 | cde   | tertiary  |
-
-		When I route I should get
-		 | from | to | route   | time    |
-		 | b    | c  | abc     | 10s +-1 |
-		 | c    | e  | cde     | 60s +-1 |
-		 | b    | d  | abc,cde | 40s +-1 |
-		 | a    | e  | abc,cde | 80s +-1 |
-
-	Scenario: Time of travel on part of a way
-		Given the node map
-		 | a | 1 |
-		 |   | 2 |
-		 |   | 3 |
-		 | b | 4 |
-
-		And the ways
-		 | nodes | highway |
-		 | ab    | primary |
-
-		When I route I should get
-		 | from | to | route | time    |
-		 | 1    | 2  | ab    | 10s +-1 |
-		 | 1    | 3  | ab    | 20s +-1 |
-		 | 1    | 4  | ab    | 30s +-1 |
-		 | 4    | 3  | ab    | 10s +-1 |
-		 | 4    | 2  | ab    | 20s +-1 |
-		 | 4    | 1  | ab    | 30s +-1 |
+# Testbot speeds:
+# Primary road:    36km/h = 36000m/3600s = 100m/10s
+# Secondary road:    18km/h = 18000m/3600s = 100m/20s
+# Tertiary road:    12km/h = 12000m/3600s = 100m/30s
+
+    Background: Use specific speeds
+        Given the profile "testbot"
+
+    Scenario: Basic travel time, 10m scale
+        Given a grid size of 10 meters
+        Given the node map
+            | h | a | b |
+            | g | x | c |
+            | f | e | d |
+
+        And the ways
+            | nodes | highway |
+            | xa    | primary |
+            | xb    | primary |
+            | xc    | primary |
+            | xd    | primary |
+            | xe    | primary |
+            | xf    | primary |
+            | xg    | primary |
+            | xh    | primary |
+
+        When I route I should get
+            | from | to | route | time   |
+            | x    | a  | xa    | 1s +-1 |
+            | x    | b  | xb    | 1s +-1 |
+            | x    | c  | xc    | 1s +-1 |
+            | x    | d  | xd    | 1s +-1 |
+            | x    | e  | xe    | 1s +-1 |
+            | x    | f  | xf    | 1s +-1 |
+            | x    | g  | xg    | 1s +-1 |
+            | x    | h  | xh    | 1s +-1 |
+
+    Scenario: Basic travel time, 100m scale
+        Given a grid size of 100 meters
+        Given the node map
+            | h | a | b |
+            | g | x | c |
+            | f | e | d |
+
+        And the ways
+            | nodes | highway |
+            | xa    | primary |
+            | xb    | primary |
+            | xc    | primary |
+            | xd    | primary |
+            | xe    | primary |
+            | xf    | primary |
+            | xg    | primary |
+            | xh    | primary |
+
+        When I route I should get
+            | from | to | route | time    |
+            | x    | a  | xa    | 10s +-1 |
+            | x    | b  | xb    | 14s +-1 |
+            | x    | c  | xc    | 10s +-1 |
+            | x    | d  | xd    | 14s +-1 |
+            | x    | e  | xe    | 10s +-1 |
+            | x    | f  | xf    | 14s +-1 |
+            | x    | g  | xg    | 10s +-1 |
+            | x    | h  | xh    | 14s +-1 |
+
+    Scenario: Basic travel time, 1km scale
+        Given a grid size of 1000 meters
+        Given the node map
+            | h | a | b |
+            | g | x | c |
+            | f | e | d |
+
+        And the ways
+            | nodes | highway |
+            | xa    | primary |
+            | xb    | primary |
+            | xc    | primary |
+            | xd    | primary |
+            | xe    | primary |
+            | xf    | primary |
+            | xg    | primary |
+            | xh    | primary |
+
+        When I route I should get
+            | from | to | route | time     |
+            | x    | a  | xa    | 100s +-1 |
+            | x    | b  | xb    | 141s +-1 |
+            | x    | c  | xc    | 100s +-1 |
+            | x    | d  | xd    | 141s +-1 |
+            | x    | e  | xe    | 100s +-1 |
+            | x    | f  | xf    | 141s +-1 |
+            | x    | g  | xg    | 100s +-1 |
+            | x    | h  | xh    | 141s +-1 |
+
+    Scenario: Basic travel time, 10km scale
+        Given a grid size of 10000 meters
+        Given the node map
+            | h | a | b |
+            | g | x | c |
+            | f | e | d |
+
+        And the ways
+            | nodes | highway |
+            | xa    | primary |
+            | xb    | primary |
+            | xc    | primary |
+            | xd    | primary |
+            | xe    | primary |
+            | xf    | primary |
+            | xg    | primary |
+            | xh    | primary |
+
+        When I route I should get
+            | from | to | route | time      |
+            | x    | a  | xa    | 1000s +-1 |
+            | x    | b  | xb    | 1414s +-1 |
+            | x    | c  | xc    | 1000s +-1 |
+            | x    | d  | xd    | 1414s +-1 |
+            | x    | e  | xe    | 1000s +-1 |
+            | x    | f  | xf    | 1414s +-1 |
+            | x    | g  | xg    | 1000s +-1 |
+            | x    | h  | xh    | 1414s +-1 |
+
+    Scenario: Time of travel depending on way type
+        Given the node map
+            | a | b |
+            | c | d |
+            | e | f |
+
+        And the ways
+            | nodes | highway   |
+            | ab    | primary   |
+            | cd    | secondary |
+            | ef    | tertiary  |
+            | ace   | something |
+
+        When I route I should get
+            | from | to | route | time    |
+            | a    | b  | ab    | 10s +-1 |
+            | c    | d  | cd    | 20s +-1 |
+            | e    | f  | ef    | 30s +-1 |
+
+    Scenario: Time of travel on a series of ways
+        Given the node map
+            | a | b |   |
+            |   | c | d |
+
+        And the ways
+            | nodes | highway |
+            | ab    | primary |
+            | bc    | primary |
+            | cd    | primary |
+
+        When I route I should get
+            | from | to | route    | time    |
+            | a    | b  | ab       | 10s +-1 |
+            | a    | c  | ab,bc    | 20s +-1 |
+            | a    | d  | ab,bc,cd | 30s +-1 |
+
+    Scenario: Time of travel on a winding way
+        Given the node map
+            | a |   | i | h |
+            | b | c |   | g |
+            |   | d | e | f |
+
+        And the ways
+            | nodes     | highway |
+            | abcdefghi | primary |
+
+        When I route I should get
+            | from | to | route     | time    |
+            | a    | b  | abcdefghi | 10s +-1 |
+            | a    | e  | abcdefghi | 40s +-1 |
+            | a    | i  | abcdefghi | 80s +-1 |
+
+    Scenario: Time of travel on combination of road types
+        Given the node map
+            | a | b | c |
+            |   |   | d |
+            |   |   | e |
+
+        And the ways
+            | nodes | highway  |
+            | abc   | primary  |
+            | cde   | tertiary |
+
+        When I route I should get
+            | from | to | route   | time    |
+            | b    | c  | abc     | 10s +-1 |
+            | c    | e  | cde     | 60s +-1 |
+            | b    | d  | abc,cde | 40s +-1 |
+            | a    | e  | abc,cde | 80s +-1 |
+
+    Scenario: Time of travel on part of a way
+        Given the node map
+            | a | 1 |
+            |   | 2 |
+            |   | 3 |
+            | b | 4 |
+
+        And the ways
+            | nodes | highway |
+            | ab    | primary |
+
+        When I route I should get
+            | from | to | route | time    |
+            | 1    | 2  | ab    | 10s +-1 |
+            | 1    | 3  | ab    | 20s +-1 |
+            | 1    | 4  | ab    | 30s +-1 |
+            | 4    | 3  | ab    | 10s +-1 |
+            | 4    | 2  | ab    | 20s +-1 |
+            | 4    | 1  | ab    | 30s +-1 |
+
+    Scenario: Total travel time should match sum of times of individual ways
+        Given a grid size of 1000 meters
+        And the node map
+            | a | b |  |  |   |
+            |   |   |  |  |   |
+            |   | c |  |  | d |
+
+        And the ways
+            | nodes | highway |
+            | ab    | primary |
+            | bc    | primary |
+            | cd    | primary |
+
+        When I route I should get
+            | from | to | route    | distances             | distance  | times              | time     |
+            | a    | b  | ab       | 1000m +-1             | 1000m +-1 | 100s +-1           | 100s +-1 |
+            | b    | c  | bc       | 2000m +-1             | 2000m +-1 | 200s +-1           | 200s +-1 |
+            | c    | d  | cd       | 3000m +-1             | 3000m +-1 | 300s +-1           | 300s +-1 |
+            | a    | c  | ab,bc    | 1000m,2000m +-1       | 3000m +-1 | 100s,200s +-1      | 300s +-1 |
+            | b    | d  | bc,cd    | 2000m,3000m +-1       | 5000m +-1 | 200s,300s +-1      | 500s +-1 |
+            | a    | d  | ab,bc,cd | 1000m,2000m,3000m +-1 | 6000m +-1 | 100s,200s,300s +-1 | 600s +-1 |
diff --git a/features/testbot/turns.feature b/features/testbot/turns.feature
index 5a14c9e..87bf21f 100644
--- a/features/testbot/turns.feature
+++ b/features/testbot/turns.feature
@@ -1,123 +1,123 @@
 @routing @turns
 Feature: Turn directions/codes
-	
-	Background:
-		Given the profile "testbot"
-	
-	Scenario: Turn directions
-		Given the node map
-		 | o | p | a | b | c |
-		 | n |   |   |   | d |
-		 | m |   | x |   | e |
-		 | l |   |   |   | f |
-		 | k | j | i | h | g |
 
-		And the ways
-		 | nodes |
-		 | xa    |
-		 | xb    |
-		 | xc    |
-		 | xd    |
-		 | xe    |
-		 | xf    |
-		 | xg    |
-		 | xh    |
-		 | xi    |
-		 | xj    |
-		 | xk    |
-		 | xl    |
-		 | xm    |
-		 | xn    |
-		 | xo    |
-		 | xp    |
+    Background:
+        Given the profile "testbot"
 
-		When I route I should get
-		 | from | to | route | turns                         |
-		 | i    | k  | xi,xk | head,sharp_left,destination   |
-		 | i    | m  | xi,xm | head,left,destination         |
-		 | i    | o  | xi,xo | head,slight_left,destination  |
-		 | i    | a  | xi,xa | head,straight,destination     |
-		 | i    | c  | xi,xc | head,slight_right,destination |
-		 | i    | e  | xi,xe | head,right,destination        |
-		 | i    | g  | xi,xg | head,sharp_right,destination  |
+    Scenario: Turn directions
+        Given the node map
+            | o | p | a | b | c |
+            | n |   |   |   | d |
+            | m |   | x |   | e |
+            | l |   |   |   | f |
+            | k | j | i | h | g |
 
-		 | k | m | xk,xm | head,sharp_left,destination   |
-		 | k | o | xk,xo | head,left,destination         |
-		 | k | a | xk,xa | head,slight_left,destination  |
-		 | k | c | xk,xc | head,straight,destination     |
-		 | k | e | xk,xe | head,slight_right,destination |
-		 | k | g | xk,xg | head,right,destination        |
-		 | k | i | xk,xi | head,sharp_right,destination  |
+        And the ways
+            | nodes |
+            | xa    |
+            | xb    |
+            | xc    |
+            | xd    |
+            | xe    |
+            | xf    |
+            | xg    |
+            | xh    |
+            | xi    |
+            | xj    |
+            | xk    |
+            | xl    |
+            | xm    |
+            | xn    |
+            | xo    |
+            | xp    |
 
-		 | m | o | xm,xo | head,sharp_left,destination   |
-		 | m | a | xm,xa | head,left,destination         |
-		 | m | c | xm,xc | head,slight_left,destination  |
-		 | m | e | xm,xe | head,straight,destination     |
-		 | m | g | xm,xg | head,slight_right,destination |
-		 | m | i | xm,xi | head,right,destination        |
-		 | m | k | xm,xk | head,sharp_right,destination  |
+        When I route I should get
+            | from | to | route | turns                         |
+            | i    | k  | xi,xk | head,sharp_left,destination   |
+            | i    | m  | xi,xm | head,left,destination         |
+            | i    | o  | xi,xo | head,slight_left,destination  |
+            | i    | a  | xi,xa | head,straight,destination     |
+            | i    | c  | xi,xc | head,slight_right,destination |
+            | i    | e  | xi,xe | head,right,destination        |
+            | i    | g  | xi,xg | head,sharp_right,destination  |
 
-		 | o | a | xo,xa | head,sharp_left,destination   |
-		 | o | c | xo,xc | head,left,destination         |
-		 | o | e | xo,xe | head,slight_left,destination  |
-		 | o | g | xo,xg | head,straight,destination     |
-		 | o | i | xo,xi | head,slight_right,destination |
-		 | o | k | xo,xk | head,right,destination        |
-		 | o | m | xo,xm | head,sharp_right,destination  |
+            | k | m | xk,xm | head,sharp_left,destination   |
+            | k | o | xk,xo | head,left,destination         |
+            | k | a | xk,xa | head,slight_left,destination  |
+            | k | c | xk,xc | head,straight,destination     |
+            | k | e | xk,xe | head,slight_right,destination |
+            | k | g | xk,xg | head,right,destination        |
+            | k | i | xk,xi | head,sharp_right,destination  |
 
-		 | a | c | xa,xc | head,sharp_left,destination   |
-		 | a | e | xa,xe | head,left,destination         |
-		 | a | g | xa,xg | head,slight_left,destination  |
-		 | a | i | xa,xi | head,straight,destination     |
-		 | a | k | xa,xk | head,slight_right,destination |
-		 | a | m | xa,xm | head,right,destination        |
-		 | a | o | xa,xo | head,sharp_right,destination  |
+            | m | o | xm,xo | head,sharp_left,destination   |
+            | m | a | xm,xa | head,left,destination         |
+            | m | c | xm,xc | head,slight_left,destination  |
+            | m | e | xm,xe | head,straight,destination     |
+            | m | g | xm,xg | head,slight_right,destination |
+            | m | i | xm,xi | head,right,destination        |
+            | m | k | xm,xk | head,sharp_right,destination  |
 
-		 | c | e | xc,xe | head,sharp_left,destination   |
-		 | c | g | xc,xg | head,left,destination         |
-		 | c | i | xc,xi | head,slight_left,destination  |
-		 | c | k | xc,xk | head,straight,destination     |
-		 | c | m | xc,xm | head,slight_right,destination |
-		 | c | o | xc,xo | head,right,destination        |
-		 | c | a | xc,xa | head,sharp_right,destination  |
+            | o | a | xo,xa | head,sharp_left,destination   |
+            | o | c | xo,xc | head,left,destination         |
+            | o | e | xo,xe | head,slight_left,destination  |
+            | o | g | xo,xg | head,straight,destination     |
+            | o | i | xo,xi | head,slight_right,destination |
+            | o | k | xo,xk | head,right,destination        |
+            | o | m | xo,xm | head,sharp_right,destination  |
 
-		 | e | g | xe,xg | head,sharp_left,destination   |
-		 | e | i | xe,xi | head,left,destination         |
-		 | e | k | xe,xk | head,slight_left,destination  |
-		 | e | m | xe,xm | head,straight,destination     |
-		 | e | o | xe,xo | head,slight_right,destination |
-		 | e | a | xe,xa | head,right,destination        |
-		 | e | c | xe,xc | head,sharp_right,destination  |
+            | a | c | xa,xc | head,sharp_left,destination   |
+            | a | e | xa,xe | head,left,destination         |
+            | a | g | xa,xg | head,slight_left,destination  |
+            | a | i | xa,xi | head,straight,destination     |
+            | a | k | xa,xk | head,slight_right,destination |
+            | a | m | xa,xm | head,right,destination        |
+            | a | o | xa,xo | head,sharp_right,destination  |
 
-		 | g | i | xg,xi | head,sharp_left,destination   |
-		 | g | k | xg,xk | head,left,destination         |
-		 | g | m | xg,xm | head,slight_left,destination  |
-		 | g | o | xg,xo | head,straight,destination     |
-		 | g | a | xg,xa | head,slight_right,destination |
-		 | g | c | xg,xc | head,right,destination        |
-		 | g | e | xg,xe | head,sharp_right,destination  |
-	
-	Scenario: Turn instructions at high latitude
-	https://github.com/DennisOSRM/Project-OSRM/issues/532
-		Given the node locations
-		 | node | lat      | lon      |
-		 | a    | 55.68740 | 12.52430 |
-		 | b    | 55.68745 | 12.52409 |
-		 | c    | 55.68711 | 12.52383 |
-		 | x    | -55.68740 | 12.52430 |
-		 | y    | -55.68745 | 12.52409 |
-		 | z    | -55.68711 | 12.52383 |
+            | c | e | xc,xe | head,sharp_left,destination   |
+            | c | g | xc,xg | head,left,destination         |
+            | c | i | xc,xi | head,slight_left,destination  |
+            | c | k | xc,xk | head,straight,destination     |
+            | c | m | xc,xm | head,slight_right,destination |
+            | c | o | xc,xo | head,right,destination        |
+            | c | a | xc,xa | head,sharp_right,destination  |
 
-		And the ways
-		 | nodes |
-		 | ab    |
-		 | bc    |
-		 | xy    |
-		 | yz    |
+            | e | g | xe,xg | head,sharp_left,destination   |
+            | e | i | xe,xi | head,left,destination         |
+            | e | k | xe,xk | head,slight_left,destination  |
+            | e | m | xe,xm | head,straight,destination     |
+            | e | o | xe,xo | head,slight_right,destination |
+            | e | a | xe,xa | head,right,destination        |
+            | e | c | xe,xc | head,sharp_right,destination  |
 
-		When I route I should get
-		 | from | to | route | turns                  |
-		 | a    | c  | ab,bc | head,left,destination  |
-		 | c    | a  | bc,ab | head,right,destination |
-		 | x    | z  | xy,yz | head,right,destination  |
-		 | z    | x  | yz,xy | head,left,destination |
+            | g | i | xg,xi | head,sharp_left,destination   |
+            | g | k | xg,xk | head,left,destination         |
+            | g | m | xg,xm | head,slight_left,destination  |
+            | g | o | xg,xo | head,straight,destination     |
+            | g | a | xg,xa | head,slight_right,destination |
+            | g | c | xg,xc | head,right,destination        |
+            | g | e | xg,xe | head,sharp_right,destination  |
+
+    Scenario: Turn instructions at high latitude
+    # https://github.com/DennisOSRM/Project-OSRM/issues/532
+        Given the node locations
+            | node | lat       | lon      |
+            | a    | 55.68740  | 12.52430 |
+            | b    | 55.68745  | 12.52409 |
+            | c    | 55.68711  | 12.52383 |
+            | x    | -55.68740 | 12.52430 |
+            | y    | -55.68745 | 12.52409 |
+            | z    | -55.68711 | 12.52383 |
+
+        And the ways
+            | nodes |
+            | ab    |
+            | bc    |
+            | xy    |
+            | yz    |
+
+        When I route I should get
+            | from | to | route | turns                  |
+            | a    | c  | ab,bc | head,left,destination  |
+            | c    | a  | bc,ab | head,right,destination |
+            | x    | z  | xy,yz | head,right,destination |
+            | z    | x  | yz,xy | head,left,destination  |
diff --git a/features/testbot/utf.feature b/features/testbot/utf.feature
index 784bd4c..e9d324c 100644
--- a/features/testbot/utf.feature
+++ b/features/testbot/utf.feature
@@ -1,21 +1,21 @@
 @routing @utf
 Feature: Handling of UTF characters
-	
-	Background:
-		Given the profile "testbot"
-	
-	Scenario: Streetnames with UTF characters
-		Given the node map
-		 | a | b | c | d |
 
-		And the ways
-		 | nodes | name                   |
-		 | ab    | Scandinavian København |
-		 | bc    | Japanese 東京            |
-		 | cd    | Cyrillic Москва        |
+    Background:
+        Given the profile "testbot"
 
-		When I route I should get
-		 | from | to | route                  |
-		 | a    | b  | Scandinavian København |
-		 | b    | c  | Japanese 東京            |
-		 | c    | d  | Cyrillic Москва        |
+    Scenario: Streetnames with UTF characters
+        Given the node map
+            | a | b | c | d |
+
+        And the ways
+            | nodes | name                   |
+            | ab    | Scandinavian København |
+            | bc    | Japanese 東京            |
+            | cd    | Cyrillic Москва        |
+
+        When I route I should get
+            | from | to | route                  |
+            | a    | b  | Scandinavian København |
+            | b    | c  | Japanese 東京            |
+            | c    | d  | Cyrillic Москва        |
diff --git a/features/testbot/via.feature b/features/testbot/via.feature
index 5ba8bac..79fe540 100644
--- a/features/testbot/via.feature
+++ b/features/testbot/via.feature
@@ -4,49 +4,99 @@ Feature: Via points
     Background:
         Given the profile "testbot"
 
-        Scenario: Simple via point
-            Given the node map
-             | a | b | c |
+    Scenario: Simple via point
+        Given the node map
+            | a | b | c |
 
-            And the ways
-             | nodes |
-             | abc   |
+        And the ways
+            | nodes |
+            | abc   |
 
-            When I route I should get
-             | waypoints | route |
-             | a,b,c     | abc   |
-             | c,b,a     | abc   |
+        When I route I should get
+            | waypoints | route |
+            | a,b,c     | abc   |
+            | c,b,a     | abc   |
 
     Scenario: Via point at a dead end
         Given the node map
-         | a | b | c |
-         |   | d |   |
+            | a | b | c |
+            |   | d |   |
+
+        And the ways
+            | nodes |
+            | abc   |
+            | bd    |
+
+        When I route I should get
+            | waypoints | route         |
+            | a,d,c     | abc,bd,bd,abc |
+            | c,d,a     | abc,bd,bd,abc |
+
+    Scenario: Multiple via points
+        Given the node map
+            | a |   |   |   | e | f | g |   |
+            |   | b | c | d |   |   |   | h |
+
+        And the ways
+            | nodes |
+            | ae    |
+            | ab    |
+            | bcd   |
+            | de    |
+            | efg   |
+            | gh    |
+            | dh    |
+
+        When I route I should get
+            | waypoints | route            |
+            | a,c,f     | ab,bcd,de,efg    |
+            | a,c,f,h   | ab,bcd,de,efg,gh |
+
+    Scenario: Via points on ring of oneways
+    # xa it to avoid only having a single ring, which cna trigger edge cases
+        Given the node map
+            | x |   |   |   |   |   |   |
+            | a | 1 | b | 2 | c | 3 | d |
+            | f |   |   |   |   |   | e |
+
+        And the ways
+            | nodes | oneway |
+            | xa    |        |
+            | ab    | yes    |
+            | bc    | yes    |
+            | cd    | yes    |
+            | de    | yes    |
+            | ef    | yes    |
+            | fa    | yes    |
+
+        When I route I should get
+            | waypoints | route                      | distance  | turns                                                               |
+            | 1,3       | ab,bc,cd                   |  400m +-1 | head,straight,straight,destination                                  |
+            | 3,1       | cd,de,ef,fa,ab             | 1000m +-1 | head,right,right,right,right,destination                            |
+            | 1,2,3     | ab,bc,cd                   |  400m +-1 | head,straight,straight,destination                                  |
+            | 1,3,2     | ab,bc,cd,de,ef,fa,ab,bc    | 1600m +-1 | head,straight,straight,right,right,right,right,straight,destination |
+            | 3,2,1     | cd,de,ef,fa,ab,bc,cd,de,ef,fa,ab | 2400m +-1 | head,right,right,right,right,straight,straight,right,right,right,right,destination |
+
+    @bug
+    Scenario: Via points on ring on the same oneway
+    # xa it to avoid only having a single ring, which cna trigger edge cases
+        Given the node map
+            | x |   |   |   |   |
+            | a | 1 | 2 | 3 | b |
+            | d |   |   |   | c |
 
         And the ways
-         | nodes |
-         | abc   |
-         | bd    |
+            | nodes | oneway |
+            | xa    |        |
+            | ab    | yes    |
+            | bc    | yes    |
+            | cd    | yes    |
+            | da    | yes    |
 
         When I route I should get
-         | waypoints | route         |
-         | a,d,c     | abc,bd,bd,abc |
-         | c,d,a     | abc,bd,bd,abc |
-
-     Scenario: Multiple via points
-         Given the node map
-          | a |   |   |   | e | f | g |   |
-          |   | b | c | d |   |   |   | h |
-
-         And the ways
-          | nodes |
-          | ae    |
-          | ab    |
-          | bcd   |
-          | de    |
-          | efg   |
-          | gh    |
-          | dh    |
-
-         When I route I should get
-          | waypoints   | route     |
-          | a,c,f,h | ab,bcd,de,efg,gh |
+            | waypoints | route                      | distance  | turns                                                            |
+            | 1,3       | ab                         | 200m +-1  | head,destination                                                 |
+            | 3,1       | ab,bc,cd,da,ab             | 800m +-1  | head,right,right,right,right,destination                         |
+            | 1,2,3     | ab                         | 200m +-1  | head,destination                                                 |
+            | 1,3,2     | ab,bc,cd,da,ab             | 1100m +-1 | head,right,right,right,right,destination                         |
+            | 3,2,1     | ab,bc,cd,da,ab,bc,cd,da,ab | 1600m +-1 | head,right,right,right,right,right,right,right,right,destination |
diff --git a/features/timestamp/timestamp.feature b/features/timestamp/timestamp.feature
index 7886bad..70ef91c 100644
--- a/features/timestamp/timestamp.feature
+++ b/features/timestamp/timestamp.feature
@@ -1,12 +1,11 @@
 @timestamp
 Feature: Timestamp
-	
-	Scenario: Request timestamp
-    	Given the node map
-    	 | a | b |
-    	And the ways
-    	 | nodes |
-    	 | ab    |
- 		When I request /timestamp
- 		Then I should get a valid timestamp
- 		
+
+    Scenario: Request timestamp
+        Given the node map
+            | a | b |
+        And the ways
+            | nodes |
+            | ab    |
+        When I request /timestamp
+        Then I should get a valid timestamp
diff --git a/prepare.cpp b/prepare.cpp
new file mode 100644
index 0000000..bb0dab4
--- /dev/null
+++ b/prepare.cpp
@@ -0,0 +1,523 @@
+/*
+
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "Algorithms/IteratorBasedCRC32.h"
+#include "Contractor/Contractor.h"
+#include "Contractor/EdgeBasedGraphFactory.h"
+#include "DataStructures/BinaryHeap.h"
+#include "DataStructures/DeallocatingVector.h"
+#include "DataStructures/QueryEdge.h"
+#include "DataStructures/StaticGraph.h"
+#include "DataStructures/StaticRTree.h"
+#include "DataStructures/RestrictionMap.h"
+#include "Util/GitDescription.h"
+#include "Util/GraphLoader.h"
+#include "Util/LuaUtil.h"
+#include "Util/OSRMException.h"
+
+#include "Util/SimpleLogger.h"
+#include "Util/StringUtil.h"
+#include "Util/TimingUtil.h"
+#include "typedefs.h"
+
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+#include <luabind/luabind.hpp>
+
+#include <thread>
+#include <chrono>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <tbb/task_scheduler_init.h>
+#include <tbb/parallel_sort.h>
+
+typedef QueryEdge::EdgeData EdgeData;
+typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
+typedef StaticGraph<EdgeData>::InputEdge StaticEdge;
+
+std::vector<NodeInfo> internal_to_external_node_map;
+std::vector<TurnRestriction> restriction_list;
+std::vector<NodeID> barrier_node_list;
+std::vector<NodeID> traffic_light_list;
+std::vector<ImportEdge> edge_list;
+
+int main(int argc, char *argv[])
+{
+    try
+    {
+        LogPolicy::GetInstance().Unmute();
+        TIMER_START(preparing);
+        TIMER_START(expansion);
+
+        boost::filesystem::path config_file_path, input_path, restrictions_path, profile_path;
+        unsigned int requested_num_threads;
+
+        // declare a group of options that will be allowed only on command line
+        boost::program_options::options_description generic_options("Options");
+        generic_options.add_options()("version,v", "Show version")("help,h",
+                                                                   "Show this help message")(
+            "config,c",
+            boost::program_options::value<boost::filesystem::path>(&config_file_path)
+                ->default_value("contractor.ini"),
+            "Path to a configuration file.");
+
+        // declare a group of options that will be allowed both on command line and in config file
+        boost::program_options::options_description config_options("Configuration");
+        config_options.add_options()(
+            "restrictions,r",
+            boost::program_options::value<boost::filesystem::path>(&restrictions_path),
+            "Restrictions file in .osrm.restrictions format")(
+            "profile,p",
+            boost::program_options::value<boost::filesystem::path>(&profile_path)
+                ->default_value("profile.lua"),
+            "Path to LUA routing profile")(
+            "threads,t",
+            boost::program_options::value<unsigned int>(&requested_num_threads)->default_value(tbb::task_scheduler_init::default_num_threads()),
+            "Number of threads to use");
+
+        // hidden options, will be allowed both on command line and in config file, but will not be
+        // shown to the user
+        boost::program_options::options_description hidden_options("Hidden options");
+        hidden_options.add_options()(
+            "input,i",
+            boost::program_options::value<boost::filesystem::path>(&input_path),
+            "Input file in .osm, .osm.bz2 or .osm.pbf format");
+
+        // positional option
+        boost::program_options::positional_options_description positional_options;
+        positional_options.add("input", 1);
+
+        // combine above options for parsing
+        boost::program_options::options_description cmdline_options;
+        cmdline_options.add(generic_options).add(config_options).add(hidden_options);
+
+        boost::program_options::options_description config_file_options;
+        config_file_options.add(config_options).add(hidden_options);
+
+        boost::program_options::options_description visible_options(
+            "Usage: " + boost::filesystem::basename(argv[0]) + " <input.osrm> [options]");
+        visible_options.add(generic_options).add(config_options);
+
+        // parse command line options
+        boost::program_options::variables_map option_variables;
+        boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
+                                          .options(cmdline_options)
+                                          .positional(positional_options)
+                                          .run(),
+                                      option_variables);
+
+        if (option_variables.count("version"))
+        {
+            SimpleLogger().Write() << g_GIT_DESCRIPTION;
+            return 0;
+        }
+
+        if (option_variables.count("help"))
+        {
+            SimpleLogger().Write() << "\n" << visible_options;
+            return 0;
+        }
+
+        boost::program_options::notify(option_variables);
+
+        if (!option_variables.count("restrictions"))
+        {
+            restrictions_path = std::string(input_path.string() + ".restrictions");
+        }
+
+        if (!option_variables.count("input"))
+        {
+            SimpleLogger().Write() << "\n" << visible_options;
+            return 0;
+        }
+
+        if (!boost::filesystem::is_regular_file(input_path))
+        {
+            SimpleLogger().Write(logWARNING) << "Input file " << input_path.string()
+                                             << " not found!";
+            return 1;
+        }
+
+        if (!boost::filesystem::is_regular_file(profile_path))
+        {
+            SimpleLogger().Write(logWARNING) << "Profile " << profile_path.string()
+                                             << " not found!";
+            return 1;
+        }
+
+        if (1 > requested_num_threads)
+        {
+            SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
+            return 1;
+        }
+
+        const unsigned recommended_num_threads = tbb::task_scheduler_init::default_num_threads();
+
+        SimpleLogger().Write() << "Input file: " << input_path.filename().string();
+        SimpleLogger().Write() << "Restrictions file: " << restrictions_path.filename().string();
+        SimpleLogger().Write() << "Profile: " << profile_path.filename().string();
+        SimpleLogger().Write() << "Threads: " << requested_num_threads;
+        if (recommended_num_threads != requested_num_threads)
+        {
+            SimpleLogger().Write(logWARNING) << "The recommended number of threads is "
+                                             << recommended_num_threads
+                                             << "! This setting may have performance side-effects.";
+        }
+
+        tbb::task_scheduler_init init(requested_num_threads);
+
+        LogPolicy::GetInstance().Unmute();
+        boost::filesystem::ifstream restriction_stream(restrictions_path, std::ios::binary);
+        TurnRestriction restriction;
+        FingerPrint fingerprint_loaded, fingerprint_orig;
+        unsigned number_of_usable_restrictions = 0;
+        restriction_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
+        if (!fingerprint_loaded.TestPrepare(fingerprint_orig))
+        {
+            SimpleLogger().Write(logWARNING) << ".restrictions was prepared with different build.\n"
+                                                "Reprocess to get rid of this warning.";
+        }
+
+        restriction_stream.read((char *)&number_of_usable_restrictions, sizeof(unsigned));
+        restriction_list.resize(number_of_usable_restrictions);
+        if (number_of_usable_restrictions > 0)
+        {
+            restriction_stream.read((char *)&(restriction_list[0]),
+                                number_of_usable_restrictions * sizeof(TurnRestriction));
+        }
+        restriction_stream.close();
+
+        boost::filesystem::ifstream in;
+        in.open(input_path, std::ios::in | std::ios::binary);
+
+        const std::string node_filename = input_path.string() + ".nodes";
+        const std::string edge_out = input_path.string() + ".edges";
+        const std::string geometry_filename = input_path.string() + ".geometry";
+        const std::string graphOut = input_path.string() + ".hsgr";
+        const std::string rtree_nodes_path = input_path.string() + ".ramIndex";
+        const std::string rtree_leafs_path = input_path.string() + ".fileIndex";
+
+        /*** Setup Scripting Environment ***/
+
+        // Create a new lua state
+        lua_State *lua_state = luaL_newstate();
+
+        // Connect LuaBind to this lua state
+        luabind::open(lua_state);
+
+        // open utility libraries string library;
+        luaL_openlibs(lua_state);
+
+        // adjust lua load path
+        luaAddScriptFolderToLoadPath(lua_state, profile_path.string().c_str());
+
+        // Now call our function in a lua script
+        if (0 != luaL_dofile(lua_state, profile_path.string().c_str()))
+        {
+            std::cerr << lua_tostring(lua_state, -1) << " occured in scripting block" << std::endl;
+            return 1;
+        }
+
+        EdgeBasedGraphFactory::SpeedProfileProperties speed_profile;
+
+        if (0 != luaL_dostring(lua_state, "return traffic_signal_penalty\n"))
+        {
+            std::cerr << lua_tostring(lua_state, -1) << " occured in scripting block" << std::endl;
+            return 1;
+        }
+        speed_profile.trafficSignalPenalty = 10 * lua_tointeger(lua_state, -1);
+        SimpleLogger().Write(logDEBUG)
+            << "traffic_signal_penalty: " << speed_profile.trafficSignalPenalty;
+
+        if (0 != luaL_dostring(lua_state, "return u_turn_penalty\n"))
+        {
+            std::cerr << lua_tostring(lua_state, -1) << " occured in scripting block" << std::endl;
+            return 1;
+        }
+        speed_profile.uTurnPenalty = 10 * lua_tointeger(lua_state, -1);
+
+        speed_profile.has_turn_penalty_function = lua_function_exists(lua_state, "turn_function");
+
+        #ifdef WIN32
+        #pragma message ("Memory consumption on Windows can be higher due to memory alignment")
+        #else
+        static_assert(sizeof(ImportEdge) == 20,
+                      "changing ImportEdge type has influence on memory consumption!");
+        #endif
+        std::vector<ImportEdge> edge_list;
+        NodeID number_of_node_based_nodes =
+            readBinaryOSRMGraphFromStream(in,
+                                          edge_list,
+                                          barrier_node_list,
+                                          traffic_light_list,
+                                          &internal_to_external_node_map,
+                                          restriction_list);
+        in.close();
+
+        if (edge_list.empty())
+        {
+            SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
+            return 1;
+        }
+
+        SimpleLogger().Write() << restriction_list.size() << " restrictions, "
+                               << barrier_node_list.size() << " bollard nodes, "
+                               << traffic_light_list.size() << " traffic lights";
+
+        /***
+         * Building an edge-expanded graph from node-based input and turn restrictions
+         */
+
+        SimpleLogger().Write() << "Generating edge-expanded graph representation";
+        std::shared_ptr<NodeBasedDynamicGraph> node_based_graph =
+            NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list);
+        std::unique_ptr<RestrictionMap> restriction_map =
+            std::unique_ptr<RestrictionMap>(new RestrictionMap(node_based_graph, restriction_list));
+        EdgeBasedGraphFactory *edge_based_graph_factor =
+            new EdgeBasedGraphFactory(node_based_graph,
+                                      std::move(restriction_map),
+                                      barrier_node_list,
+                                      traffic_light_list,
+                                      internal_to_external_node_map,
+                                      speed_profile);
+        edge_list.clear();
+        edge_list.shrink_to_fit();
+
+        edge_based_graph_factor->Run(edge_out, geometry_filename, lua_state);
+
+        restriction_list.clear();
+        restriction_list.shrink_to_fit();
+        barrier_node_list.clear();
+        barrier_node_list.shrink_to_fit();
+        traffic_light_list.clear();
+        traffic_light_list.shrink_to_fit();
+
+        unsigned number_of_edge_based_nodes = edge_based_graph_factor->GetNumberOfEdgeBasedNodes();
+        BOOST_ASSERT(number_of_edge_based_nodes != std::numeric_limits<unsigned>::max());
+        DeallocatingVector<EdgeBasedEdge> edgeBasedEdgeList;
+        #ifndef WIN32
+        static_assert(sizeof(EdgeBasedEdge) == 16,
+                      "changing ImportEdge type has influence on memory consumption!");
+        #endif
+
+        edge_based_graph_factor->GetEdgeBasedEdges(edgeBasedEdgeList);
+        std::vector<EdgeBasedNode> node_based_edge_list;
+        edge_based_graph_factor->GetEdgeBasedNodes(node_based_edge_list);
+        delete edge_based_graph_factor;
+
+        // TODO actually use scoping: Split this up in subfunctions
+        node_based_graph.reset();
+
+        TIMER_STOP(expansion);
+
+        // Building grid-like nearest-neighbor data structure
+        SimpleLogger().Write() << "building r-tree ...";
+        StaticRTree<EdgeBasedNode> *rtree =
+            new StaticRTree<EdgeBasedNode>(node_based_edge_list,
+                                           rtree_nodes_path.c_str(),
+                                           rtree_leafs_path.c_str(),
+                                           internal_to_external_node_map);
+        delete rtree;
+        IteratorbasedCRC32<std::vector<EdgeBasedNode>> crc32;
+        unsigned node_based_edge_list_CRC32 =
+            crc32(node_based_edge_list.begin(), node_based_edge_list.end());
+        node_based_edge_list.clear();
+        node_based_edge_list.shrink_to_fit();
+        SimpleLogger().Write() << "CRC32: " << node_based_edge_list_CRC32;
+
+        /***
+         * Writing info on original (node-based) nodes
+         */
+
+        SimpleLogger().Write() << "writing node map ...";
+        boost::filesystem::ofstream node_stream(node_filename, std::ios::binary);
+        const unsigned size_of_mapping = internal_to_external_node_map.size();
+        node_stream.write((char *)&size_of_mapping, sizeof(unsigned));
+        if (size_of_mapping > 0)
+        {
+            node_stream.write((char *)&(internal_to_external_node_map[0]),
+                          size_of_mapping * sizeof(NodeInfo));
+        }
+        node_stream.close();
+        internal_to_external_node_map.clear();
+        internal_to_external_node_map.shrink_to_fit();
+
+        /***
+         * Contracting the edge-expanded graph
+         */
+
+        SimpleLogger().Write() << "initializing contractor";
+        Contractor *contractor = new Contractor(number_of_edge_based_nodes, edgeBasedEdgeList);
+
+        TIMER_START(contraction);
+        contractor->Run();
+        TIMER_STOP(contraction);
+
+        SimpleLogger().Write() << "Contraction took " << TIMER_SEC(contraction) << " sec";
+
+        DeallocatingVector<QueryEdge> contracted_edge_list;
+        contractor->GetEdges(contracted_edge_list);
+        delete contractor;
+
+        /***
+         * Sorting contracted edges in a way that the static query graph can read some in in-place.
+         */
+
+        std::sort(contracted_edge_list.begin(), contracted_edge_list.end());
+        unsigned max_used_node_id = 0;
+        unsigned contracted_edge_count = contracted_edge_list.size();
+        SimpleLogger().Write() << "Serializing compacted graph of " << contracted_edge_count
+                               << " edges";
+
+        boost::filesystem::ofstream hsgr_output_stream(graphOut, std::ios::binary);
+        hsgr_output_stream.write((char *)&fingerprint_orig, sizeof(FingerPrint));
+        for (const QueryEdge &edge : contracted_edge_list)
+        {
+            BOOST_ASSERT(UINT_MAX != edge.source);
+            BOOST_ASSERT(UINT_MAX != edge.target);
+
+            max_used_node_id = std::max(max_used_node_id, edge.source);
+            max_used_node_id = std::max(max_used_node_id, edge.target);
+        }
+        SimpleLogger().Write(logDEBUG) << "input graph has " << number_of_edge_based_nodes
+                                       << " nodes";
+        SimpleLogger().Write(logDEBUG) << "contracted graph has " << max_used_node_id << " nodes";
+        max_used_node_id += 1;
+
+        std::vector<StaticGraph<EdgeData>::NodeArrayEntry> node_array;
+        node_array.resize(number_of_edge_based_nodes + 1);
+
+        SimpleLogger().Write() << "Building node array";
+        StaticGraph<EdgeData>::EdgeIterator edge = 0;
+        StaticGraph<EdgeData>::EdgeIterator position = 0;
+        StaticGraph<EdgeData>::EdgeIterator last_edge = edge;
+
+        for (StaticGraph<EdgeData>::NodeIterator node = 0; node < max_used_node_id; ++node)
+        {
+            last_edge = edge;
+            while ((edge < contracted_edge_count) && (contracted_edge_list[edge].source == node))
+            {
+                ++edge;
+            }
+            node_array[node].first_edge = position; //=edge
+            position += edge - last_edge;           // remove
+        }
+
+        for (unsigned sentinel_counter = max_used_node_id; sentinel_counter != node_array.size();
+             ++sentinel_counter)
+        {
+            // sentinel element, guarded against underflow
+            node_array[sentinel_counter].first_edge = contracted_edge_count;
+        }
+
+        unsigned node_array_size = node_array.size();
+        // serialize crc32, aka checksum
+        hsgr_output_stream.write((char *)&node_based_edge_list_CRC32, sizeof(unsigned));
+        // serialize number of nodes
+        hsgr_output_stream.write((char *)&node_array_size, sizeof(unsigned));
+        // serialize number of edges
+        hsgr_output_stream.write((char *)&contracted_edge_count, sizeof(unsigned));
+        // serialize all nodes
+        if (node_array_size > 0)
+        {
+            hsgr_output_stream.write((char *)&node_array[0],
+                                 sizeof(StaticGraph<EdgeData>::NodeArrayEntry) * node_array_size);
+        }
+        // serialize all edges
+
+        SimpleLogger().Write() << "Building edge array";
+        edge = 0;
+        int number_of_used_edges = 0;
+
+        StaticGraph<EdgeData>::EdgeArrayEntry current_edge;
+        for (unsigned edge = 0; edge < contracted_edge_list.size(); ++edge)
+        {
+            // no eigen loops
+            BOOST_ASSERT(contracted_edge_list[edge].source != contracted_edge_list[edge].target);
+            current_edge.target = contracted_edge_list[edge].target;
+            current_edge.data = contracted_edge_list[edge].data;
+
+            // every target needs to be valid
+            BOOST_ASSERT(current_edge.target < max_used_node_id);
+#ifndef NDEBUG
+            if (current_edge.data.distance <= 0)
+            {
+                SimpleLogger().Write(logWARNING)
+                    << "Edge: " << edge << ",source: " << contracted_edge_list[edge].source
+                    << ", target: " << contracted_edge_list[edge].target
+                    << ", dist: " << current_edge.data.distance;
+
+                SimpleLogger().Write(logWARNING) << "Failed at adjacency list of node "
+                                                 << contracted_edge_list[edge].source << "/"
+                                                 << node_array.size() - 1;
+                return 1;
+            }
+#endif
+            hsgr_output_stream.write((char *)&current_edge,
+                                     sizeof(StaticGraph<EdgeData>::EdgeArrayEntry));
+            ++number_of_used_edges;
+        }
+        hsgr_output_stream.close();
+
+        TIMER_STOP(preparing);
+
+        SimpleLogger().Write() << "Preprocessing : " << TIMER_SEC(preparing) << " seconds";
+        SimpleLogger().Write() << "Expansion  : "
+                               << (number_of_node_based_nodes / TIMER_SEC(expansion))
+                               << " nodes/sec and "
+                               << (number_of_edge_based_nodes / TIMER_SEC(expansion))
+                               << " edges/sec";
+
+        SimpleLogger().Write() << "Contraction: "
+                               << (number_of_edge_based_nodes / TIMER_SEC(contraction))
+                               << " nodes/sec and "
+                               << number_of_used_edges / TIMER_SEC(contraction)
+                               << " edges/sec";
+
+        node_array.clear();
+        SimpleLogger().Write() << "finished preprocessing";
+    }
+    catch (boost::program_options::too_many_positional_options_error &)
+    {
+        SimpleLogger().Write(logWARNING) << "Only one file can be specified";
+        return 1;
+    }
+    catch (boost::program_options::error &e)
+    {
+        SimpleLogger().Write(logWARNING) << e.what();
+        return 1;
+    }
+    catch (const std::exception &e)
+    {
+        SimpleLogger().Write(logWARNING) << "Exception occured: " << e.what() << std::endl;
+        return 1;
+    }
+    return 0;
+}
diff --git a/profile.lua b/profile.lua
new file mode 120000
index 0000000..bad7e6b
--- /dev/null
+++ b/profile.lua
@@ -0,0 +1 @@
+profiles/car.lua
\ No newline at end of file
diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua
index 98d03c8..3efa3d0 100644
--- a/profiles/bicycle.lua
+++ b/profiles/bicycle.lua
@@ -1,8 +1,8 @@
 require("lib/access")
 
 -- Begin of globals
-barrier_whitelist = { [""] = true, ["cycle_barrier"] = true, ["bollard"] = true, ["entrance"] = true, ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true}
-access_tag_whitelist = { ["yes"] = true, ["permissive"] = true, ["designated"] = true	}
+barrier_whitelist = { [""] = true, ["cycle_barrier"] = true, ["bollard"] = true, ["entrance"] = true, ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true }
+access_tag_whitelist = { ["yes"] = true, ["permissive"] = true, ["designated"] = true }
 access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestery"] = true }
 access_tag_restricted = { ["destination"] = true, ["delivery"] = true }
 access_tags_hierachy = { "bicycle", "vehicle", "access" }
@@ -14,103 +14,120 @@ default_speed = 15
 
 walking_speed = 6
 
-bicycle_speeds = { 
-	["cycleway"] = default_speed,
-	["primary"] = default_speed,
-	["primary_link"] = default_speed,
-	["secondary"] = default_speed,
-	["secondary_link"] = default_speed,
-	["tertiary"] = default_speed,
-	["tertiary_link"] = default_speed,
-	["residential"] = default_speed,
-	["unclassified"] = default_speed,
-	["living_street"] = default_speed,
-	["road"] = default_speed,
-	["service"] = default_speed,
-	["track"] = 12,
-	["path"] = 12
-	--["footway"] = 12,
-	--["pedestrian"] = 12,
+bicycle_speeds = {
+  ["cycleway"] = default_speed,
+  ["primary"] = default_speed,
+  ["primary_link"] = default_speed,
+  ["secondary"] = default_speed,
+  ["secondary_link"] = default_speed,
+  ["tertiary"] = default_speed,
+  ["tertiary_link"] = default_speed,
+  ["residential"] = default_speed,
+  ["unclassified"] = default_speed,
+  ["living_street"] = default_speed,
+  ["road"] = default_speed,
+  ["service"] = default_speed,
+  ["track"] = 12,
+  ["path"] = 12
+  --["footway"] = 12,
+  --["pedestrian"] = 12,
 }
 
-pedestrian_speeds = { 
-	["footway"] = walking_speed,
-	["pedestrian"] = walking_speed,
-	["steps"] = 2
+pedestrian_speeds = {
+  ["footway"] = walking_speed,
+  ["pedestrian"] = walking_speed,
+  ["steps"] = 2
 }
 
-railway_speeds = { 
-	["train"] = 10,
-	["railway"] = 10,
-	["subway"] = 10,
-	["light_rail"] = 10,
-	["monorail"] = 10,
-	["tram"] = 10
+railway_speeds = {
+  ["train"] = 10,
+  ["railway"] = 10,
+  ["subway"] = 10,
+  ["light_rail"] = 10,
+  ["monorail"] = 10,
+  ["tram"] = 10
 }
 
-platform_speeds = { 
-	["platform"] = walking_speed
+platform_speeds = {
+  ["platform"] = walking_speed
 }
 
-amenity_speeds = { 
-	["parking"] = 10,
-	["parking_entrance"] = 10
+amenity_speeds = {
+  ["parking"] = 10,
+  ["parking_entrance"] = 10
 }
 
-man_made_speeds = { 
-	["pier"] = walking_speed
+man_made_speeds = {
+  ["pier"] = walking_speed
 }
 
-route_speeds = { 
-	["ferry"] = 5
+route_speeds = {
+  ["ferry"] = 5
 }
 
-surface_speeds = { 
-	["cobblestone:flattened"] = 10,
-	["paving_stones"] = 10,
-	["compacted"] = 10,
-	["cobblestone"] = 6,
-	["unpaved"] = 6,
-	["fine_gravel"] = 6,
-	["gravel"] = 6,
-	["fine_gravel"] = 6,
-	["pebbelstone"] = 6,
-	["ground"] = 6,
-	["dirt"] = 6,
-	["earth"] = 6,
-	["grass"] = 6,
-	["mud"] = 3,
-	["sand"] = 3	
+surface_speeds = {
+  ["asphalt"] = default_speed,
+  ["cobblestone:flattened"] = 10,
+  ["paving_stones"] = 10,
+  ["compacted"] = 10,
+  ["cobblestone"] = 6,
+  ["unpaved"] = 6,
+  ["fine_gravel"] = 6,
+  ["gravel"] = 6,
+  ["fine_gravel"] = 6,
+  ["pebbelstone"] = 6,
+  ["ground"] = 6,
+  ["dirt"] = 6,
+  ["earth"] = 6,
+  ["grass"] = 6,
+  ["mud"] = 3,
+  ["sand"] = 3
 }
 
-take_minimum_of_speeds 	= true
-obey_oneway 			= true
-obey_bollards 			= false
-use_restrictions 		= true
-ignore_areas 			= true -- future feature
-traffic_signal_penalty 	= 5
-u_turn_penalty 			= 20
+take_minimum_of_speeds  = true
+obey_oneway       = true
+obey_bollards       = false
+use_restrictions    = true
+ignore_areas      = true    -- future feature
+traffic_signal_penalty  = 5
+u_turn_penalty      = 20
 use_turn_restrictions   = false
-turn_penalty 			= 60
-turn_bias               = 1.4
+turn_penalty      = 60
+turn_bias         = 1.4
 -- End of globals
 
+
+local function parse_maxspeed(source)
+    if not source then
+        return 0
+    end
+    local n = tonumber(source:match("%d*"))
+    if not n then
+        n = 0
+    end
+    if string.match(source, "mph") or string.match(source, "mp/h") then
+        n = (n*1609)/1000;
+    end
+    return n
+end
+
+
 function get_exceptions(vector)
-	for i,v in ipairs(restriction_exception_tags) do 
-		vector:Add(v)
-	end
+  for i,v in ipairs(restriction_exception_tags) do
+    vector:Add(v)
+  end
 end
 
 function node_function (node)
-	local barrier = node.tags:Find ("barrier")
-	local access = Access.find_access_tag(node, access_tags_hierachy)
-	local traffic_signal = node.tags:Find("highway")
-	
-	-- flag node if it carries a traffic light	
+  local barrier = node.tags:Find ("barrier")
+  local access = Access.find_access_tag(node, access_tags_hierachy)
+  local traffic_signal = node.tags:Find("highway")
+
+	-- flag node if it carries a traffic light
 	if traffic_signal == "traffic_signals" then
 		node.traffic_light = true
 	end
-	
+
 	-- parse access and barrier tags
 	if access and access ~= "" then
 		if access_tag_blacklist[access] then
@@ -125,229 +142,235 @@ function node_function (node)
 			node.bollard = true
 		end
 	end
-	
-	return 1
+
+	-- return 1
 end
 
 function way_function (way)
-	-- initial routability check, filters out buildings, boundaries, etc
-	local highway = way.tags:Find("highway")
-	local route = way.tags:Find("route")
-	local man_made = way.tags:Find("man_made")
-	local railway = way.tags:Find("railway")
-	local amenity = way.tags:Find("amenity")
-	local public_transport = way.tags:Find("public_transport")
-    if (not highway or highway == '') and 
-		(not route or route == '') and 
-		(not railway or railway=='') and 
-		(not amenity or amenity=='') and
-		(not man_made or man_made=='') and
-    	(not public_transport or public_transport=='')
-    	then
-    	return 0
+  -- initial routability check, filters out buildings, boundaries, etc
+  local highway = way.tags:Find("highway")
+  local route = way.tags:Find("route")
+  local man_made = way.tags:Find("man_made")
+  local railway = way.tags:Find("railway")
+  local amenity = way.tags:Find("amenity")
+  local public_transport = way.tags:Find("public_transport")
+  if (not highway or highway == '') and
+  (not route or route == '') and
+  (not railway or railway=='') and
+  (not amenity or amenity=='') and
+  (not man_made or man_made=='') and
+  (not public_transport or public_transport=='')
+  then
+    return 0
+  end
+
+  -- don't route on ways or railways that are still under construction
+  if highway=='construction' or railway=='construction' then
+    return 0
+  end
+
+  -- access
+  local access = Access.find_access_tag(way, access_tags_hierachy)
+  if access_tag_blacklist[access] then
+    return 0
+  end
+
+  -- other tags
+  local name = way.tags:Find("name")
+  local ref = way.tags:Find("ref")
+  local junction = way.tags:Find("junction")
+  local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") )
+  local maxspeed_forward = parse_maxspeed(way.tags:Find( "maxspeed:forward"))
+  local maxspeed_backward = parse_maxspeed(way.tags:Find( "maxspeed:backward"))
+  local barrier = way.tags:Find("barrier")
+  local oneway = way.tags:Find("oneway")
+  local onewayClass = way.tags:Find("oneway:bicycle")
+  local cycleway = way.tags:Find("cycleway")
+  local cycleway_left = way.tags:Find("cycleway:left")
+  local cycleway_right = way.tags:Find("cycleway:right")
+  local duration = way.tags:Find("duration")
+  local service = way.tags:Find("service")
+  local area = way.tags:Find("area")
+  local foot = way.tags:Find("foot")
+  local surface = way.tags:Find("surface")
+
+  -- name
+  if "" ~= ref and "" ~= name then
+    way.name = name .. ' / ' .. ref
+  elseif "" ~= ref then
+    way.name = ref
+  elseif "" ~= name then
+    way.name = name
+  else
+    -- if no name exists, use way type
+    -- this encoding scheme is excepted to be a temporary solution
+    way.name = "{highway:"..highway.."}"
+  end
+
+  -- roundabout handling
+  if "roundabout" == junction then
+    way.roundabout = true;
+  end
+
+  -- speed
+  if route_speeds[route] then
+    -- ferries (doesn't cover routes tagged using relations)
+    way.direction = Way.bidirectional
+    way.ignore_in_grid = true
+    if durationIsValid(duration) then
+      way.duration = math.max( 1, parseDuration(duration) )
+    else
+       way.speed = route_speeds[route]
     end
-    
-    -- don't route on ways or railways that are still under construction
-    if highway=='construction' or railway=='construction' then
-        return 0
+  elseif railway and platform_speeds[railway] then
+    -- railway platforms (old tagging scheme)
+    way.speed = platform_speeds[railway]
+  elseif platform_speeds[public_transport] then
+    -- public_transport platforms (new tagging platform)
+    way.speed = platform_speeds[public_transport]
+    elseif railway and railway_speeds[railway] then
+     -- railways
+    if access and access_tag_whitelist[access] then
+      way.speed = railway_speeds[railway]
+      way.direction = Way.bidirectional
     end
-    
-	-- access
- 	local access = Access.find_access_tag(way, access_tags_hierachy)
-    if access_tag_blacklist[access] then
-		return 0
+  elseif amenity and amenity_speeds[amenity] then
+    -- parking areas
+    way.speed = amenity_speeds[amenity]
+  elseif bicycle_speeds[highway] then
+    -- regular ways
+    way.speed = bicycle_speeds[highway]
+  elseif access and access_tag_whitelist[access] then
+    -- unknown way, but valid access tag
+    way.speed = default_speed
+  else
+    -- biking not allowed, maybe we can push our bike?
+    -- essentially requires pedestrian profiling, for example foot=no mean we can't push a bike
+    -- TODO: if we can push, the way should be marked as pedestrion mode, but there's no way to do it yet from lua..
+    if foot ~= 'no' then
+      if pedestrian_speeds[highway] then
+        -- pedestrian-only ways and areas
+        way.speed = pedestrian_speeds[highway]
+      elseif man_made and man_made_speeds[man_made] then
+        -- man made structures
+        way.speed = man_made_speeds[man_made]
+      elseif foot == 'yes' then
+        way.speed = walking_speed
+      end
     end
+  end
 
+  -- direction
+  way.direction = Way.bidirectional
+  local impliedOneway = false
+  if junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then
+    way.direction = Way.oneway
+    impliedOneway = true
+  end
 
-	-- other tags
-	local name = way.tags:Find("name")
-	local ref = way.tags:Find("ref")
-	local junction = way.tags:Find("junction")
-	local maxspeed = parseMaxspeed(way.tags:Find ( "maxspeed") )
-	local maxspeed_forward = parseMaxspeed(way.tags:Find( "maxspeed:forward"))
-	local maxspeed_backward = parseMaxspeed(way.tags:Find( "maxspeed:backward"))
-	local barrier = way.tags:Find("barrier")
-	local oneway = way.tags:Find("oneway")
-	local onewayClass = way.tags:Find("oneway:bicycle")
-	local cycleway = way.tags:Find("cycleway")
-	local cycleway_left = way.tags:Find("cycleway:left")
-	local cycleway_right = way.tags:Find("cycleway:right")
-	local duration	= way.tags:Find("duration")
-	local service	= way.tags:Find("service")
-	local area = way.tags:Find("area")
-	local foot = way.tags:Find("foot")
-	local surface = way.tags:Find("surface")
-
-	-- name	
-	if "" ~= ref and "" ~= name then
-		way.name = name .. ' / ' .. ref
-    elseif "" ~= ref then
-    	way.name = ref
-	elseif "" ~= name then
-		way.name = name
-	else
-		way.name = "{highway:"..highway.."}"	-- if no name exists, use way type
-		                                        -- this encoding scheme is excepted to be a temporary solution
-	end
-		
-	-- speed
-    if route_speeds[route] then
-		-- ferries (doesn't cover routes tagged using relations)
-		way.direction = Way.bidirectional
-		way.ignore_in_grid = true
-		if durationIsValid(duration) then
-			way.duration = math.max( 1, parseDuration(duration) )
-		else
-		 	way.speed = route_speeds[route]
-		end
-	elseif railway and platform_speeds[railway] then
-		-- railway platforms (old tagging scheme)
-		way.speed = platform_speeds[railway]
-	elseif platform_speeds[public_transport] then
-		-- public_transport platforms (new tagging platform)
-		way.speed = platform_speeds[public_transport]
-    elseif railway and railway_speeds[railway] then
-	 	-- railways
-		if access and access_tag_whitelist[access] then
-			way.speed = railway_speeds[railway]		
-			way.direction = Way.bidirectional
-		end
-	elseif amenity and amenity_speeds[amenity] then
-		-- parking areas
-		way.speed = amenity_speeds[amenity]
-	elseif bicycle_speeds[highway] then
-		-- regular ways
-      	way.speed = bicycle_speeds[highway]
-	elseif access and access_tag_whitelist[access] then
-	    -- unknown way, but valid access tag
-		way.speed = default_speed
-	else
-	    -- biking not allowed, maybe we can push our bike?
-	    -- essentially requires pedestrian profiling, for example foot=no mean we can't push a bike
-        -- TODO: if we can push, the way should be marked as pedestrion mode, but there's no way to do it yet from lua..
-        if foot ~= 'no' then
-	        if pedestrian_speeds[highway] then
-	            -- pedestrian-only ways and areas
-        		way.speed = pedestrian_speeds[highway]
-        	elseif man_made and man_made_speeds[man_made] then
-            	-- man made structures
-            	way.speed = man_made_speeds[man_made]
-            elseif foot == 'yes' then
-                way.speed = walking_speed
-            end
-        end
+  if onewayClass == "yes" or onewayClass == "1" or onewayClass == "true" then
+    way.direction = Way.oneway
+  elseif onewayClass == "no" or onewayClass == "0" or onewayClass == "false" then
+    way.direction = Way.bidirectional
+  elseif onewayClass == "-1" then
+    way.direction = Way.opposite
+  elseif oneway == "no" or oneway == "0" or oneway == "false" then
+    way.direction = Way.bidirectional
+  elseif cycleway and string.find(cycleway, "opposite") == 1 then
+    if impliedOneway then
+      way.direction = Way.opposite
+    else
+      way.direction = Way.bidirectional
     end
-		
-	-- direction
-	way.direction = Way.bidirectional
-	local impliedOneway = false
-	if junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then
-		way.direction = Way.oneway
-		impliedOneway = true
-	end
-	
-	if onewayClass == "yes" or onewayClass == "1" or onewayClass == "true" then
-		way.direction = Way.oneway
-	elseif onewayClass == "no" or onewayClass == "0" or onewayClass == "false" then
-		way.direction = Way.bidirectional
-	elseif onewayClass == "-1" then
-		way.direction = Way.opposite
-	elseif oneway == "no" or oneway == "0" or oneway == "false" then
-		way.direction = Way.bidirectional
-	elseif cycleway and string.find(cycleway, "opposite") == 1 then
-		if impliedOneway then
-			way.direction = Way.opposite
-		else
-			way.direction = Way.bidirectional
-		end
-	elseif cycleway_left and cycleway_tags[cycleway_left] and cycleway_right and cycleway_tags[cycleway_right] then
-		way.direction = Way.bidirectional
-	elseif cycleway_left and cycleway_tags[cycleway_left] then
-		if impliedOneway then
-			way.direction = Way.opposite
-		else
-			way.direction = Way.bidirectional
-		end
-	elseif cycleway_right and cycleway_tags[cycleway_right] then
-		if impliedOneway then
-			way.direction = Way.oneway
-		else
-			way.direction = Way.bidirectional
-		end
-	elseif oneway == "-1" then
-		way.direction = Way.opposite
-	elseif oneway == "yes" or oneway == "1" or oneway == "true" then
-		way.direction = Way.oneway
-	end
-	
-	-- pushing bikes
-	if bicycle_speeds[highway] or pedestrian_speeds[highway] then
-	    if foot ~= 'no' then
-	        if junction ~= "roundabout" then
-            	if way.direction == Way.oneway then
-            	    way.backward_speed = walking_speed
-                elseif way.direction == Way.opposite then
-                    way.backward_speed = walking_speed
-                    way.speed = way.speed
-            	end
-            end
-        end
-        if way.backward_speed == way.speed then
-            -- TODO: no way yet to mark a way as pedestrian mode if forward/backward speeds are equal
-            way.direction = Way.bidirectional
-        end
+  elseif cycleway_left and cycleway_tags[cycleway_left] and cycleway_right and cycleway_tags[cycleway_right] then
+    way.direction = Way.bidirectional
+  elseif cycleway_left and cycleway_tags[cycleway_left] then
+    if impliedOneway then
+      way.direction = Way.opposite
+    else
+      way.direction = Way.bidirectional
     end
+  elseif cycleway_right and cycleway_tags[cycleway_right] then
+    if impliedOneway then
+      way.direction = Way.oneway
+    else
+      way.direction = Way.bidirectional
+    end
+  elseif oneway == "-1" then
+    way.direction = Way.opposite
+  elseif oneway == "yes" or oneway == "1" or oneway == "true" then
+    way.direction = Way.oneway
+  end
 
-	
-	-- cycleways
-	if cycleway and cycleway_tags[cycleway] then
-		way.speed = bicycle_speeds["cycleway"]
-	elseif cycleway_left and cycleway_tags[cycleway_left] then
-		way.speed = bicycle_speeds["cycleway"]
-	elseif cycleway_right and cycleway_tags[cycleway_right] then
-		way.speed = bicycle_speeds["cycleway"]
-	end
-    
-    -- surfaces
-    if surface then
-        surface_speed = surface_speeds[surface]
-        if surface_speed then
-            way.speed = math.min(way.speed, surface_speed)
-            way.backward_speed  = math.min(way.backward_speed, surface_speed)
+  -- pushing bikes
+  if bicycle_speeds[highway] or pedestrian_speeds[highway] then
+    if foot ~= 'no' then
+      if junction ~= "roundabout" then
+        if way.direction == Way.oneway then
+          way.backward_speed = walking_speed
+        elseif way.direction == Way.opposite then
+          way.backward_speed = walking_speed
+          way.speed = way.speed
         end
+      end
+    end
+    if way.backward_speed == way.speed then
+      -- TODO: no way yet to mark a way as pedestrian mode if forward/backward speeds are equal
+      way.direction = Way.bidirectional
     end
+  end
 
-	-- maxspeed
-	-- TODO: maxspeed of backward direction
-	if take_minimum_of_speeds then
-		if maxspeed and maxspeed>0 then
-			way.speed = math.min(way.speed, maxspeed)
-		end
-	end
+  -- cycleways
+  if cycleway and cycleway_tags[cycleway] then
+    way.speed = bicycle_speeds["cycleway"]
+  elseif cycleway_left and cycleway_tags[cycleway_left] then
+    way.speed = bicycle_speeds["cycleway"]
+  elseif cycleway_right and cycleway_tags[cycleway_right] then
+    way.speed = bicycle_speeds["cycleway"]
+  end
 
-  -- Override speed settings if explicit forward/backward maxspeeds are given
-    if maxspeed_forward ~= nil and maxspeed_forward > 0 then
-	if Way.bidirectional == way.direction then
-          way.backward_speed = way.speed
-        end
-        way.speed = maxspeed_forward
+  -- surfaces
+  if surface then
+    surface_speed = surface_speeds[surface]
+    if surface_speed then
+      if way.speed > 0 then
+        way.speed = surface_speed
+      end
+      if way.backward_speed > 0 then
+        way.backward_speed  = surface_speed
+      end
     end
-    if maxspeed_backward ~= nil and maxspeed_backward > 0 then
-      way.backward_speed = maxspeed_backward
+  end
+
+  -- maxspeed
+  -- TODO: maxspeed of backward direction
+  if take_minimum_of_speeds then
+    if maxspeed and maxspeed>0 then
+      way.speed = math.min(way.speed, maxspeed)
     end
+  end
 
+  -- Override speed settings if explicit forward/backward maxspeeds are given
+  if way.speed > 0 and maxspeed_forward ~= nil and maxspeed_forward > 0 then
+    if Way.bidirectional == way.direction then
+      way.backward_speed = way.speed
+    end
+    way.speed = maxspeed_forward
+  end
+  if maxspeed_backward ~= nil and maxspeed_backward > 0 then
+    way.backward_speed = maxspeed_backward
+  end
 
-	
-	way.type = 1
-	return 1
+  way.type = 1
+  return 1
 end
 
 function turn_function (angle)
-    -- compute turn penalty as angle^2, with a left/right bias
-    k = turn_penalty/(90.0*90.0)
-	if angle>=0 then
-	    return angle*angle*k/turn_bias
-	else
-	    return angle*angle*k*turn_bias
-    end
+  -- compute turn penalty as angle^2, with a left/right bias
+  k = turn_penalty/(90.0*90.0)
+  if angle>=0 then
+    return angle*angle*k/turn_bias
+  else
+    return angle*angle*k*turn_bias
+  end
 end
diff --git a/profiles/car.lua b/profiles/car.lua
index ff7c379..9c65852 100644
--- a/profiles/car.lua
+++ b/profiles/car.lua
@@ -1,9 +1,9 @@
 -- Begin of globals
-require("lib/access")
+--require("lib/access") --function temporarily inlined
 
-barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true}
-access_tag_whitelist = { ["yes"] = true, ["motorcar"] = true, ["motor_vehicle"] = true, ["vehicle"] = true, ["permissive"] = true, ["designated"] = true  }
-access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true }
+barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true, ["entrance"] = true }
+access_tag_whitelist = { ["yes"] = true, ["motorcar"] = true, ["motor_vehicle"] = true, ["vehicle"] = true, ["permissive"] = true, ["designated"] = true }
+access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true, ["emergency"] = true }
 access_tag_restricted = { ["destination"] = true, ["delivery"] = true }
 access_tags = { "motorcar", "motor_vehicle", "vehicle" }
 access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" }
@@ -29,145 +29,193 @@ speed_profile = {
 --  ["track"] = 5,
   ["ferry"] = 5,
   ["shuttle_train"] = 10,
-  ["default"] = 50
+  ["default"] = 10
 }
 
-take_minimum_of_speeds 	= false
-obey_oneway 			= true
-obey_bollards 			= true
-use_restrictions 		= true
-ignore_areas 			= true -- future feature
-traffic_signal_penalty 	= 2
-u_turn_penalty 			= 20
+traffic_signal_penalty          = 2
 
 -- End of globals
+local take_minimum_of_speeds    = false
+local obey_oneway               = true
+local obey_bollards             = true
+local use_turn_restrictions     = true
+local ignore_areas              = true     -- future feature
+local u_turn_penalty            = 20
+
+local abs = math.abs
+local min = math.min
+local max = math.max
+
+local speed_reduction = 0.8
+
+local function find_access_tag(source,access_tags_hierachy)
+  for i,v in ipairs(access_tags_hierachy) do
+    local has_tag = source.tags:Holds(v)
+    if has_tag then
+      return source.tags:Find(v)
+    end
+  end
+  return nil
+end
 
 function get_exceptions(vector)
-	for i,v in ipairs(restriction_exception_tags) do
-		vector:Add(v)
-	end
+  for i,v in ipairs(restriction_exception_tags) do
+    vector:Add(v)
+  end
 end
 
 local function parse_maxspeed(source)
-	if source == nil then
-		return 0
-	end
-	local n = tonumber(source:match("%d*"))
-	if n == nil then
-		n = 0
-	end
-	if string.match(source, "mph") or string.match(source, "mp/h") then
-		n = (n*1609)/1000;
-	end
-	return math.abs(n)
+  if not source then
+    return 0
+  end
+  local n = tonumber(source:match("%d*"))
+  if not n then
+    n = 0
+  end
+  if string.match(source, "mph") or string.match(source, "mp/h") then
+    n = (n*1609)/1000;
+  end
+  return n
 end
 
+-- function turn_function (angle)
+--   -- print ("called at angle " .. angle )
+--   local index = math.abs(math.floor(angle/10+0.5))+1 -- +1 'coz LUA starts as idx 1
+--   local penalty = turn_cost_table[index]
+--   -- print ("index: " .. index .. ", bias: " .. penalty )
+--   return penalty
+-- end
+
 function node_function (node)
-  local barrier = node.tags:Find ("barrier")
-  local access = Access.find_access_tag(node, access_tags_hierachy)
-  local traffic_signal = node.tags:Find("highway")
+  local access = find_access_tag(node, access_tags_hierachy)
 
   --flag node if it carries a traffic light
+  if node.tags:Holds("highway") then
+    if node.tags:Find("highway") == "traffic_signals" then
+      node.traffic_light = true;
+    end
+  end
 
-  if traffic_signal == "traffic_signals" then
-    node.traffic_light = true;
-  end
-
-	-- parse access and barrier tags
-	if access  and access ~= "" then
-		if access_tag_blacklist[access] then
-			node.bollard = true
-		end
-	elseif barrier and barrier ~= "" then
-		if barrier_whitelist[barrier] then
-			return
-		else
-			node.bollard = true
-		end
-	end
-	return 1
+  -- parse access and barrier tags
+  if access and access ~= "" then
+    if access_tag_blacklist[access] then
+      node.bollard = true
+    end
+  elseif node.tags:Holds("barrier") then
+    local barrier = node.tags:Find("barrier")
+    if barrier_whitelist[barrier] then
+      return
+    else
+      node.bollard = true
+    end
+  end
 end
 
-
 function way_function (way)
   -- we dont route over areas
-  local area = way.tags:Find("area")
-  if ignore_areas and ("yes" == area) then
-    return 0
+  local is_area = way.tags:Holds("area")
+  if ignore_areas and is_area then
+    local area = way.tags:Find("area")
+    if "yes" == area then
+      return
+    end
   end
 
   -- check if oneway tag is unsupported
   local oneway = way.tags:Find("oneway")
   if "reversible" == oneway then
-    return 0
+    return
+  end
+
+  local is_impassable = way.tags:Holds("impassable")
+  if is_impassable then
+    local impassable = way.tags:Find("impassable")
+    if "yes" == impassable then
+      return
+    end
+  end
+
+  local is_status = way.tags:Holds("status")
+  if is_status then
+    local status = way.tags:Find("status")
+    if "impassable" == status then
+      return
+    end
   end
 
   -- Check if we are allowed to access the way
-  local access = Access.find_access_tag(way, access_tags_hierachy)
+  local access = find_access_tag(way, access_tags_hierachy)
   if access_tag_blacklist[access] then
-    return 0
+    return
   end
 
   -- Second, parse the way according to these properties
   local highway = way.tags:Find("highway")
-  local name = way.tags:Find("name")
-  local ref = way.tags:Find("ref")
-  local junction = way.tags:Find("junction")
   local route = way.tags:Find("route")
-  local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") )
-  local maxspeed_forward = parse_maxspeed(way.tags:Find( "maxspeed:forward"))
-  local maxspeed_backward = parse_maxspeed(way.tags:Find( "maxspeed:backward"))
-  local barrier = way.tags:Find("barrier")
-  local cycleway = way.tags:Find("cycleway")
-  local duration  = way.tags:Find("duration")
-  local service  = way.tags:Find("service")
-
-
-  -- Set the name that will be used for instructions
-	if "" ~= ref then
-	  way.name = ref
-	elseif "" ~= name then
-	  way.name = name
---	else
---      way.name = highway		-- if no name exists, use way type
-	end
-
-	if "roundabout" == junction then
-	  way.roundabout = true;
-	end
 
   -- Handling ferries and piers
-  if (speed_profile[route] ~= nil and speed_profile[route] > 0) then
+  local route_speed = speed_profile[route]
+  if(route_speed and route_speed > 0) then
+    highway = route;
+    local duration  = way.tags:Find("duration")
     if durationIsValid(duration) then
-      way.duration = math.max( parseDuration(duration), 1 );
+      way.duration = max( parseDuration(duration), 1 );
     end
     way.direction = Way.bidirectional
-    if speed_profile[route] ~= nil then
-      highway = route;
-    end
-    if tonumber(way.duration) < 0 then
-      way.speed = speed_profile[highway]
-    end
+    way.speed = route_speed
+  end
+
+  -- leave early of this way is not accessible
+  if "" == highway then
+    return
   end
 
-  -- Set the avg speed on the way if it is accessible by road class
-  if (speed_profile[highway] ~= nil and way.speed == -1 ) then
-    if maxspeed > speed_profile[highway] then
-      way.speed = maxspeed
+  if way.speed == -1 then
+    local highway_speed = speed_profile[highway]
+    local max_speed = parse_maxspeed( way.tags:Find("maxspeed") )
+    -- Set the avg speed on the way if it is accessible by road class
+    if highway_speed then
+      if max_speed > highway_speed then
+        way.speed = max_speed
+        -- max_speed = math.huge
+      else
+        way.speed = highway_speed
+      end
     else
-      if 0 == maxspeed then
-        maxspeed = math.huge
+      -- Set the avg speed on ways that are marked accessible
+      if access_tag_whitelist[access] then
+        way.speed = speed_profile["default"]
       end
-      way.speed = math.min(speed_profile[highway], maxspeed)
     end
+    if 0 == max_speed then
+      max_speed = math.huge
+    end
+    way.speed = min(way.speed, max_speed)
   end
 
-  -- Set the avg speed on ways that are marked accessible
-  if "" ~= highway and access_tag_whitelist[access] and way.speed == -1 then
-    if 0 == maxspeed then
-      maxspeed = math.huge
-    end
-    way.speed = math.min(speed_profile["default"], maxspeed)
+  if -1 == way.speed then
+    return
+  end
+
+  -- parse the remaining tags
+  local name = way.tags:Find("name")
+  local ref = way.tags:Find("ref")
+  local junction = way.tags:Find("junction")
+  -- local barrier = way.tags:Find("barrier")
+  -- local cycleway = way.tags:Find("cycleway")
+  local service  = way.tags:Find("service")
+
+  -- Set the name that will be used for instructions
+  if "" ~= ref then
+    way.name = ref
+  elseif "" ~= name then
+    way.name = name
+--  else
+      --    way.name = highway  -- if no name exists, use way type
+  end
+
+  if "roundabout" == junction then
+    way.roundabout = true;
   end
 
   -- Set access restriction flag if access is allowed under certain restrictions only
@@ -177,43 +225,54 @@ function way_function (way)
 
   -- Set access restriction flag if service is allowed under certain restrictions only
   if service ~= "" and service_tag_restricted[service] then
-	  way.is_access_restricted = true
+    way.is_access_restricted = true
   end
 
   -- Set direction according to tags on way
   way.direction = Way.bidirectional
-  if obey_oneway then
-	  if oneway == "-1" then
-	    way.direction = Way.opposite
-    elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then
-	    way.direction = Way.oneway
+  if obey_oneway  then
+    if oneway == "-1" then
+      way.direction = Way.opposite
+    elseif oneway == "yes" or
+    oneway == "1" or
+    oneway == "true" or
+    junction == "roundabout" or
+    (highway == "motorway_link" and oneway ~="no") or
+    (highway == "motorway" and oneway ~= "no") then
+      way.direction = Way.oneway
     end
   end
 
   -- Override speed settings if explicit forward/backward maxspeeds are given
-  if maxspeed_forward ~= nil and maxspeed_forward > 0 then
+  local maxspeed_forward = parse_maxspeed(way.tags:Find( "maxspeed:forward"))
+  local maxspeed_backward = parse_maxspeed(way.tags:Find( "maxspeed:backward"))
+  if maxspeed_forward > 0 then
     if Way.bidirectional == way.direction then
       way.backward_speed = way.speed
     end
     way.speed = maxspeed_forward
   end
-  if maxspeed_backward ~= nil and maxspeed_backward > 0 then
+  if maxspeed_backward > 0 then
     way.backward_speed = maxspeed_backward
   end
 
   -- Override general direction settings of there is a specific one for our mode of travel
-  if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then
-		way.ignore_in_grid = true
-	end
+  if ignore_in_grid[highway] then
+    way.ignore_in_grid = true
+  end
+  way.type = 1
 
-	way.type = 1
-  return 1
+  -- scale speeds to get better avg driving times
+  way.speed = way.speed * speed_reduction
+  if maxspeed_backward > 0 then
+    way.backward_speed = way.backward_speed*speed_reduction
+  end
+  return
 end
 
 -- These are wrappers to parse vectors of nodes and ways and thus to speed up any tracing JIT
-
 function node_vector_function(vector)
- for v in vector.nodes do
-  node_function(v)
- end
+  for v in vector.nodes do
+    node_function(v)
+  end
 end
diff --git a/profiles/examples/postgis.lua b/profiles/examples/postgis.lua
new file mode 100644
index 0000000..b101a27
--- /dev/null
+++ b/profiles/examples/postgis.lua
@@ -0,0 +1,82 @@
+
+-- This example shows how to query external data stored in PostGIS when processing ways.
+
+-- This profile assumes that OSM data has been imported to PostGIS using imposm to a db
+-- with the name 'imposm', the default user and no password. It assumes  areas with
+-- landusage=* was imported to the table osm_landusages, containting the columns type and area.
+-- Seee http://imposm.org/ for more info on imposm.
+-- Other tools for importing OSM data to PostGIS include osm2pgsql and osmosis.
+
+-- It uses the PostGIS function ST_DWithin() to find areas tagged with landuse=industrial
+-- that are within 100 meters of the way.
+-- It then slows down the routing depending on the number and size of the industrial area.
+
+-- The end result is that routes will tend to avoid industrial area. Passing through
+-- industrial areas is still possible, it's just slower, and thus avoided if a reasonable
+-- alternative is found.
+
+-- We use the osm id as the key when querying PostGIS. Be sure to add an index to the colunn
+-- containing the osm id (osm_id in this case), otherwise you will suffer form very
+-- bad performance. You should also have spatial indexes on the relevant gemoetry columns.
+
+-- More info about using SQL form LUA can be found at http://www.keplerproject.org/luasql/
+
+-- Happy routing!
+
+
+-- Open PostGIS connection
+lua_sql = require "luasql.postgres"           -- we will connect to a postgresql database
+sql_env = assert( lua_sql.postgres() )
+sql_con = assert( sql_env:connect("imposm") ) -- you can add db user/password here if needed
+print("PostGIS connection opened")
+
+-- these settings are read directly by osrm
+take_minimum_of_speeds   = true
+obey_oneway             = true
+obey_bollards           = true
+use_restrictions         = true
+ignore_areas             = true  -- future feature
+traffic_signal_penalty   = 7      -- seconds
+u_turn_penalty           = 20
+
+-- nodes processing, called from OSRM
+function node_function(node)
+  return 1
+end
+
+-- ways processing, called from OSRM
+function way_function (way)
+  -- only route on ways with highway=*
+  local highway = way.tags:Find("highway")
+  if (not highway or highway=='') then
+    return 0
+  end
+
+  -- Query PostGIS for industrial areas close to the way, then group by way and sum the areas.
+  -- We take the square root of the area to get a estimate of the length of the side of the area, 
+  -- and thus a rough guess of how far we might be travelling along the area. 
+
+  local sql_query = " " ..
+    "SELECT SUM(SQRT(area.area)) AS val " ..
+    "FROM osm_ways way " ..
+    "LEFT JOIN osm_landusages area ON ST_DWithin(way.geometry, area.geometry, 100) " ..
+    "WHERE area.type IN ('industrial') AND way.osm_id=" .. way.id .. " " ..
+    "GROUP BY way.id"
+
+  local cursor = assert( sql_con:execute(sql_query) )   -- execute querty
+  local row = cursor:fetch( {}, "a" )                   -- fetch first (and only) row
+  way.speed = 20.0                                      -- default speed
+  if row then
+    local val = tonumber(row.val)                       -- read 'val' from row 
+    if val > 10 then
+      way.speed = way.speed / math.log10( val )         -- reduce speed by amount of industry close by 
+    end
+  end
+  cursor:close()                                        -- done with this query
+
+  -- set other required info for this way
+  way.name = way.tags:Find("name")
+  way.direction = Way.bidirectional 
+  way.type = 1
+  return 1
+end
diff --git a/profiles/foot.lua b/profiles/foot.lua
index 6a15fb2..ae0dd60 100644
--- a/profiles/foot.lua
+++ b/profiles/foot.lua
@@ -1,193 +1,205 @@
 -- Foot profile
 
--- Begin of globals
+require("lib/access")
 
-bollards_whitelist = { [""] = true, ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true}
+barrier_whitelist = { [""] = true, ["cycle_barrier"] = true, ["bollard"] = true, ["entrance"] = true, ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true}
 access_tag_whitelist = { ["yes"] = true, ["foot"] = true, ["permissive"] = true, ["designated"] = true  }
 access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestery"] = true }
 access_tag_restricted = { ["destination"] = true, ["delivery"] = true }
-access_tags = { "foot" }
+access_tags_hierachy = { "foot", "access" }
 service_tag_restricted = { ["parking_aisle"] = true }
 ignore_in_grid = { ["ferry"] = true }
 restriction_exception_tags = { "foot" }
 
-speed_profile = { 
-  ["primary"] = 5,
-  ["primary_link"] = 5,
-  ["secondary"] = 5,
-  ["secondary_link"] = 5,
-  ["tertiary"] = 5,
-  ["tertiary_link"] = 5,
-  ["unclassified"] = 5,
-  ["residential"] = 5,
-  ["road"] = 5,
-  ["living_street"] = 5,
-  ["service"] = 5,
-  ["track"] = 5,
-  ["path"] = 5,
-  ["steps"] = 5,
-  ["ferry"] = 5,
-  ["pedestrian"] = 5,
-  ["footway"] = 5,
-  ["pier"] = 5,
-  ["default"] = 5
+walking_speed = 5
+
+speeds = {
+  ["primary"] = walking_speed,
+  ["primary_link"] = walking_speed,
+  ["secondary"] = walking_speed,
+  ["secondary_link"] = walking_speed,
+  ["tertiary"] = walking_speed,
+  ["tertiary_link"] = walking_speed,
+  ["unclassified"] = walking_speed,
+  ["residential"] = walking_speed,
+  ["road"] = walking_speed,
+  ["living_street"] = walking_speed,
+  ["service"] = walking_speed,
+  ["track"] = walking_speed,
+  ["path"] = walking_speed,
+  ["steps"] = walking_speed,
+  ["pedestrian"] = walking_speed,
+  ["footway"] = walking_speed,
+  ["pier"] = walking_speed,
+  ["default"] = walking_speed
+}
+
+route_speeds = {
+	["ferry"] = 5
 }
 
+platform_speeds = {
+	["platform"] = walking_speed
+}
+
+amenity_speeds = {
+	["parking"] = walking_speed,
+	["parking_entrance"] = walking_speed
+}
+
+man_made_speeds = {
+	["pier"] = walking_speed
+}
+
+surface_speeds = {
+	["fine_gravel"] =   walking_speed*0.75,
+	["gravel"] =        walking_speed*0.75,
+	["pebbelstone"] =   walking_speed*0.75,
+	["mud"] =           walking_speed*0.5,
+	["sand"] =          walking_speed*0.5
+}
 
-take_minimum_of_speeds 	= true
-obey_oneway 			= true
-obey_bollards 			= false
-use_restrictions 		= false
-ignore_areas 			= true -- future feature
 traffic_signal_penalty 	= 2
 u_turn_penalty 			= 2
 use_turn_restrictions   = false
--- End of globals
 
 function get_exceptions(vector)
-	for i,v in ipairs(restriction_exception_tags) do 
+	for i,v in ipairs(restriction_exception_tags) do
 		vector:Add(v)
 	end
 end
 
 function node_function (node)
-  local barrier = node.tags:Find ("barrier")
-  local access = node.tags:Find ("access")
-  local traffic_signal = node.tags:Find("highway")
-  
-  --flag node if it carries a traffic light
-  
-  if traffic_signal == "traffic_signals" then
-	node.traffic_light = true;
-  end
-  
-  if obey_bollards then
-	  --flag node as unpassable if it black listed as unpassable
-	  if access_tag_blacklist[barrier] then
-		node.bollard = true;
-	  end
-	  
-	  --reverse the previous flag if there is an access tag specifying entrance
-	  if node.bollard and not bollards_whitelist[barrier] and not access_tag_whitelist[barrier] then
-		node.bollard = false;
-	  end
-  end
-  return 1
+	local barrier = node.tags:Find ("barrier")
+	local access = Access.find_access_tag(node, access_tags_hierachy)
+	local traffic_signal = node.tags:Find("highway")
+
+	-- flag node if it carries a traffic light
+	if traffic_signal == "traffic_signals" then
+		node.traffic_light = true
+	end
+
+	-- parse access and barrier tags
+	if access and access ~= "" then
+		if access_tag_blacklist[access] then
+			node.bollard = true
+		else
+			node.bollard = false
+		end
+	elseif barrier and barrier ~= "" then
+		if barrier_whitelist[barrier] then
+			node.bollard = false
+		else
+			node.bollard = true
+		end
+	end
+
+	return 1
 end
 
 function way_function (way)
+ 	-- initial routability check, filters out buildings, boundaries, etc
+	local highway = way.tags:Find("highway")
+	local route = way.tags:Find("route")
+	local man_made = way.tags:Find("man_made")
+	local railway = way.tags:Find("railway")
+	local amenity = way.tags:Find("amenity")
+	local public_transport = way.tags:Find("public_transport")
+    if (not highway or highway == '') and
+		(not route or route == '') and
+		(not railway or railway=='') and
+		(not amenity or amenity=='') and
+		(not man_made or man_made=='') and
+    	(not public_transport or public_transport=='')
+    	then
+    	return 0
+    end
 
-  -- First, get the properties of each way that we come across
-    local highway = way.tags:Find("highway")
-    local name = way.tags:Find("name")
-    local ref = way.tags:Find("ref")
-    local junction = way.tags:Find("junction")
-    local route = way.tags:Find("route")
-    local maxspeed = parseMaxspeed(way.tags:Find ( "maxspeed") )
-    local man_made = way.tags:Find("man_made")
-    local barrier = way.tags:Find("barrier")
-    local oneway = way.tags:Find("oneway")
-	local onewayClass = way.tags:Find("oneway:foot")
-    local duration  = way.tags:Find("duration")
-    local service  = way.tags:Find("service")
-    local area = way.tags:Find("area")
-    local access = way.tags:Find("access")
-
-  -- Second parse the way according to these properties
+    -- don't route on ways that are still under construction
+    if highway=='construction' then
+        return 0
+    end
 
-	if ignore_areas and ("yes" == area) then
+	-- access
+    local access = Access.find_access_tag(way, access_tags_hierachy)
+    if access_tag_blacklist[access] then
 		return 0
-	end
-		
-  -- Check if we are allowed to access the way
-    if access_tag_blacklist[access] ~=nil and access_tag_blacklist[access] then
-		return 0;
     end
-    
-  -- Check if our vehicle types are forbidden
-    for i,v in ipairs(access_tags) do 
-      local mode_value = way.tags:Find(v)
-      if nil ~= mode_value and "no" == mode_value then
-	    return 0;
-      end
-    end
-  
-    
-  -- Set the name that will be used for instructions  
-	if "" ~= ref then
-	  way.name = ref
+
+	local name = way.tags:Find("name")
+	local ref = way.tags:Find("ref")
+	local junction = way.tags:Find("junction")
+	local onewayClass = way.tags:Find("oneway:foot")
+	local duration	= way.tags:Find("duration")
+	local service	= way.tags:Find("service")
+	local area = way.tags:Find("area")
+	local foot = way.tags:Find("foot")
+	local surface = way.tags:Find("surface")
+
+ 	-- name
+	if "" ~= ref and "" ~= name then
+		way.name = name .. ' / ' .. ref
+    elseif "" ~= ref then
+    	way.name = ref
 	elseif "" ~= name then
-	  way.name = name
+		way.name = name
+	else
+		way.name = "{highway:"..highway.."}"	-- if no name exists, use way type
+		                                        -- this encoding scheme is excepted to be a temporary solution
 	end
-	
+
+    -- roundabouts
 	if "roundabout" == junction then
 	  way.roundabout = true;
 	end
 
-  -- Handling ferries and piers
-
-    if (speed_profile[route] ~= nil and speed_profile[route] > 0) or
-       (speed_profile[man_made] ~= nil and speed_profile[man_made] > 0) 
-    then
-      if durationIsValid(duration) then
-	    way.speed = parseDuration(duration) / math.max(1, numberOfNodesInWay-1);
-        way.is_duration_set = true;
-      end
-      way.direction = Way.bidirectional;
-      if speed_profile[route] ~= nil then
-         highway = route;
-      elseif speed_profile[man_made] ~= nil then
-         highway = man_made;
-      end
-      if not way.is_duration_set then
-        way.speed = speed_profile[highway]
-      end
-      
-    end
-    
-  -- Set the avg speed on the way if it is accessible by road class
-    if (speed_profile[highway] ~= nil and way.speed == -1 ) then 
-      way.speed = speed_profile[highway]
-    end
-    
-  -- Set the avg speed on ways that are marked accessible
-    if access_tag_whitelist[access]  and way.speed == -1 then
-      if (0 < maxspeed and not take_minimum_of_speeds) or maxspeed == 0 then
-        maxspeed = math.huge
-      end
-      way.speed = math.min(speed_profile["default"], maxspeed)
+    -- speed
+    if route_speeds[route] then
+		-- ferries (doesn't cover routes tagged using relations)
+		way.direction = Way.bidirectional
+		way.ignore_in_grid = true
+		if durationIsValid(duration) then
+			way.duration = math.max( 1, parseDuration(duration) )
+		else
+		 	way.speed = route_speeds[route]
+		end
+	elseif railway and platform_speeds[railway] then
+		-- railway platforms (old tagging scheme)
+		way.speed = platform_speeds[railway]
+	elseif platform_speeds[public_transport] then
+		-- public_transport platforms (new tagging platform)
+		way.speed = platform_speeds[public_transport]
+	elseif amenity and amenity_speeds[amenity] then
+		-- parking areas
+		way.speed = amenity_speeds[amenity]
+	elseif speeds[highway] then
+		-- regular ways
+      	way.speed = speeds[highway]
+	elseif access and access_tag_whitelist[access] then
+	    -- unknown way, but valid access tag
+		way.speed = walking_speed
     end
 
-  -- Set access restriction flag if access is allowed under certain restrictions only
-    if access ~= "" and access_tag_restricted[access] then
-	  way.is_access_restricted = true
+	-- oneway
+	if onewayClass == "yes" or onewayClass == "1" or onewayClass == "true" then
+		way.direction = Way.oneway
+	elseif onewayClass == "no" or onewayClass == "0" or onewayClass == "false" then
+		way.direction = Way.bidirectional
+	elseif onewayClass == "-1" then
+		way.direction = Way.opposite
+	else
+      way.direction = Way.bidirectional
     end
 
-  -- Set access restriction flag if service is allowed under certain restrictions only
-    if service ~= "" and service_tag_restricted[service] then
-	  way.is_access_restricted = true
-    end
-    
-  -- Set direction according to tags on way
-    if obey_oneway then
-		if onewayClass == "yes" or onewayClass == "1" or onewayClass == "true" then
-			way.direction = Way.oneway
-		elseif onewayClass == "no" or onewayClass == "0" or onewayClass == "false" then
-			way.direction = Way.bidirectional
-		elseif onewayClass == "-1" then
-			way.direction = Way.opposite
-		else
-			way.direction = Way.bidirectional
-		end
-    else
-      way.direction = Way.bidirectional
+    -- surfaces
+    if surface then
+        surface_speed = surface_speeds[surface]
+        if surface_speed then
+            way.speed = math.min(way.speed, surface_speed)
+            way.backward_speed  = math.min(way.backward_speed, surface_speed)
+        end
     end
-    
-  -- Override general direction settings of there is a specific one for our mode of travel
-  
-    if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then
-		way.ignore_in_grid = true
-  	end
+
   	way.type = 1
-  return 1
+    return 1
 end
diff --git a/profiles/testbot.lua b/profiles/testbot.lua
index f934fea..66d6599 100644
--- a/profiles/testbot.lua
+++ b/profiles/testbot.lua
@@ -2,106 +2,111 @@
 
 -- Moves at fixed, well-known speeds, practical for testing speed and travel times:
 
--- Primary road:	36km/h = 36000m/3600s = 100m/10s
--- Secondary road:	18km/h = 18000m/3600s = 100m/20s
--- Tertiary road:	12km/h = 12000m/3600s = 100m/30s
-
-speed_profile = { 
-	["primary"] = 36,
-	["secondary"] = 18,
-	["tertiary"] = 12,
-	["default"] = 24
+-- Primary road:  36km/h = 36000m/3600s = 100m/10s
+-- Secondary road:  18km/h = 18000m/3600s = 100m/20s
+-- Tertiary road:  12km/h = 12000m/3600s = 100m/30s
+
+speed_profile = {
+  ["primary"] = 36,
+  ["secondary"] = 18,
+  ["tertiary"] = 12,
+  ["default"] = 24
 }
 
 -- these settings are read directly by osrm
 
-take_minimum_of_speeds 	= true
-obey_oneway 			= true
-obey_bollards 			= true
-use_restrictions 		= true
-ignore_areas 			= true	-- future feature
-traffic_signal_penalty 	= 7		-- seconds
-u_turn_penalty 			= 20
+take_minimum_of_speeds  = true
+obey_oneway             = true
+obey_barriers           = true
+use_turn_restrictions   = true
+ignore_areas            = true  -- future feature
+traffic_signal_penalty  = 7     -- seconds
+u_turn_penalty          = 20
 
 function limit_speed(speed, limits)
-    -- don't use ipairs(), since it stops at the first nil value
-    for i=1, #limits do
-        limit = limits[i]
-        if limit ~= nil and limit > 0 then
-            if limit < speed then
-                return limit        -- stop at first speedlimit that's smaller than speed
-            end
-        end
+  -- don't use ipairs(), since it stops at the first nil value
+  for i=1, #limits do
+    limit = limits[i]
+    if limit ~= nil and limit > 0 then
+      if limit < speed then
+        return limit        -- stop at first speedlimit that's smaller than speed
+      end
     end
-    return speed
+  end
+  return speed
 end
 
 function node_function (node)
-	local traffic_signal = node.tags:Find("highway")
+  local traffic_signal = node.tags:Find("highway")
 
-	if traffic_signal == "traffic_signals" then
-		node.traffic_light = true;
-		-- TODO: a way to set the penalty value
-	end
-	return 1
+  if traffic_signal == "traffic_signals" then
+    node.traffic_light = true;
+    -- TODO: a way to set the penalty value
+  end
+  return 1
 end
 
 function way_function (way)
-	local highway = way.tags:Find("highway")
-	local name = way.tags:Find("name")
-	local oneway = way.tags:Find("oneway")
-	local route = way.tags:Find("route")
-	local duration = way.tags:Find("duration")
-    local maxspeed = tonumber(way.tags:Find ( "maxspeed"))
-    local maxspeed_forward = tonumber(way.tags:Find( "maxspeed:forward"))
-    local maxspeed_backward = tonumber(way.tags:Find( "maxspeed:backward"))
-	
-	way.name = name
-
-  	if route ~= nil and durationIsValid(duration) then
-		way.duration = math.max( 1, parseDuration(duration) )
-	else
-	    local speed_forw = speed_profile[highway] or speed_profile['default']
-	    local speed_back = speed_forw
-
-    	if highway == "river" then
-    		local temp_speed = speed_forw;
-    		speed_forw = temp_speed*1.5
-    		speed_back = temp_speed/1.5
-   	end
-            	
-        if maxspeed_forward ~= nil and maxspeed_forward > 0 then
-			speed_forw = maxspeed_forward
-		else
-			if maxspeed ~= nil and maxspeed > 0 and speed_forw > maxspeed then
-				speed_forw = maxspeed
-			end
-		end
-		
-		if maxspeed_backward ~= nil and maxspeed_backward > 0 then
-			speed_back = maxspeed_backward
-		else
-			if maxspeed ~=nil and maxspeed > 0 and speed_back > maxspeed then
-				speed_back = maxspeed
-			end
-		end
-        
-        way.speed = speed_forw
-        if speed_back ~= way_forw then
-            way.backward_speed = speed_back
-        end
-	end
-	
-	if oneway == "no" or oneway == "0" or oneway == "false" then
-		way.direction = Way.bidirectional
-	elseif oneway == "-1" then
-		way.direction = Way.opposite
-	elseif oneway == "yes" or oneway == "1" or oneway == "true" then
-		way.direction = Way.oneway
-	else
-		way.direction = Way.bidirectional
-	end
-	
-	way.type = 1
-	return 1
+  local highway = way.tags:Find("highway")
+  local name = way.tags:Find("name")
+  local oneway = way.tags:Find("oneway")
+  local route = way.tags:Find("route")
+  local duration = way.tags:Find("duration")
+  local maxspeed = tonumber(way.tags:Find ( "maxspeed"))
+  local maxspeed_forward = tonumber(way.tags:Find( "maxspeed:forward"))
+  local maxspeed_backward = tonumber(way.tags:Find( "maxspeed:backward"))
+  local junction = way.tags:Find("junction")
+
+  way.name = name
+
+  if route ~= nil and durationIsValid(duration) then
+    way.duration = math.max( 1, parseDuration(duration) )
+  else
+    local speed_forw = speed_profile[highway] or speed_profile['default']
+    local speed_back = speed_forw
+
+    if highway == "river" then
+      local temp_speed = speed_forw;
+      speed_forw = temp_speed*1.5
+      speed_back = temp_speed/1.5
+    end
+
+    if maxspeed_forward ~= nil and maxspeed_forward > 0 then
+      speed_forw = maxspeed_forward
+    else
+      if maxspeed ~= nil and maxspeed > 0 and speed_forw > maxspeed then
+        speed_forw = maxspeed
+      end
+    end
+
+    if maxspeed_backward ~= nil and maxspeed_backward > 0 then
+      speed_back = maxspeed_backward
+    else
+      if maxspeed ~=nil and maxspeed > 0 and speed_back > maxspeed then
+        speed_back = maxspeed
+      end
+    end
+
+    way.speed = speed_forw
+    if speed_back ~= way_forw then
+      way.backward_speed = speed_back
+    end
+  end
+
+  if oneway == "no" or oneway == "0" or oneway == "false" then
+    way.direction = Way.bidirectional
+  elseif oneway == "-1" then
+    way.direction = Way.opposite
+  elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" then
+    way.direction = Way.oneway
+  else
+    way.direction = Way.bidirectional
+  end
+
+  if junction == 'roundabout' then
+    way.roundabout = true
+  end
+
+  way.type = 1
+  return 1
 end
diff --git a/routed.cpp b/routed.cpp
index e097bd7..adf2e2d 100644
--- a/routed.cpp
+++ b/routed.cpp
@@ -1,90 +1,127 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
-
-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.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
-#ifdef __linux__
-#include <sys/mman.h>
-#endif
-#include <iostream>
-#include <signal.h>
 
-#include <boost/bind.hpp>
-#include <boost/date_time.hpp>
-#include <boost/thread.hpp>
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-#include "Server/DataStructures/QueryObjectsStorage.h"
-#include "Server/ServerConfiguration.h"
-#include "Server/ServerFactory.h"
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-#include "Plugins/HelloWorldPlugin.h"
-#include "Plugins/LocatePlugin.h"
-#include "Plugins/NearestPlugin.h"
-#include "Plugins/TimestampPlugin.h"
-#include "Plugins/ViaRoutePlugin.h"
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#include "Util/InputFileUtil.h"
-#include "Util/OpenMPWrapper.h"
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#ifndef _WIN32
-#include "Util/LinuxStackTrace.h"
+*/
+
+#include "Library/OSRM.h"
+#include "Server/ServerFactory.h"
+#include "Util/GitDescription.h"
+#include "Util/ProgramOptions.h"
+#include "Util/SimpleLogger.h"
+#include "Util/FingerPrint.h"
+
+#ifdef __linux__
+#include <sys/mman.h>
 #endif
 
-typedef http::RequestHandler RequestHandler;
+#include <cstdlib>
+
+#include <signal.h>
+
+#include <chrono>
+#include <functional>
+#include <future>
+#include <iostream>
+#include <thread>
 
 #ifdef _WIN32
 boost::function0<void> console_ctrl_function;
 
 BOOL WINAPI console_ctrl_handler(DWORD ctrl_type)
 {
-  switch (ctrl_type)
-  {
-  case CTRL_C_EVENT:
-  case CTRL_BREAK_EVENT:
-  case CTRL_CLOSE_EVENT:
-  case CTRL_SHUTDOWN_EVENT:
-    console_ctrl_function();
-    return TRUE;
-  default:
-    return FALSE;
-  }
+    switch (ctrl_type)
+    {
+    case CTRL_C_EVENT:
+    case CTRL_BREAK_EVENT:
+    case CTRL_CLOSE_EVENT:
+    case CTRL_SHUTDOWN_EVENT:
+        console_ctrl_function();
+        return TRUE;
+    default:
+        return FALSE;
+    }
 }
 #endif
 
-int main (int argc, char * argv[]) {
-#ifdef __linux__
-    if(!mlockall(MCL_CURRENT | MCL_FUTURE))
-        WARN("Process " << argv[0] << "could not be locked to RAM");
-#endif
-#ifndef _WIN32
+int main(int argc, const char *argv[])
+{
+    try
+    {
+        LogPolicy::GetInstance().Unmute();
+
+        bool use_shared_memory = false, trial_run = false;
+        std::string ip_address;
+        int ip_port, requested_thread_num;
+
+        ServerPaths server_paths;
+
+        const unsigned init_result = GenerateServerProgramOptions(argc,
+                                                                  argv,
+                                                                  server_paths,
+                                                                  ip_address,
+                                                                  ip_port,
+                                                                  requested_thread_num,
+                                                                  use_shared_memory,
+                                                                  trial_run);
+        if (init_result == INIT_OK_DO_NOT_START_ENGINE)
+        {
+            return 0;
+        }
+        if (init_result == INIT_FAILED)
+        {
+            return 1;
+        }
 
-    installCrashHandler(argv[0]);
+#ifdef __linux__
+        const int lock_flags = MCL_CURRENT | MCL_FUTURE;
+        if (-1 == mlockall(lock_flags))
+        {
+            SimpleLogger().Write(logWARNING) << argv[0] << " could not be locked to RAM";
+        }
 #endif
+        SimpleLogger().Write() << "starting up engines, " << g_GIT_DESCRIPTION << ", "
+                               << "compiled at " << __DATE__ << ", " __TIME__;
 
-	// Bug - testing not necessary.  testDataFiles also tries to open the first
-	// argv, which is the name of exec file
-    //if(testDataFiles(argc, argv)==false) {
-        //std::cerr << "[error] at least one data file name seems to be bogus!" << std::endl;
-        //exit(-1);
-    //}
-
-    try {
-        std::cout << std::endl << "[server] starting up engines, saved at " << __TIMESTAMP__ << std::endl;
-
+        if (use_shared_memory)
+        {
+            SimpleLogger().Write(logDEBUG) << "Loading from shared memory";
+        }
+        else
+        {
+            SimpleLogger().Write() << "HSGR file:\t" << server_paths["hsgrdata"];
+            SimpleLogger().Write(logDEBUG) << "Nodes file:\t" << server_paths["nodesdata"];
+            SimpleLogger().Write(logDEBUG) << "Edges file:\t" << server_paths["edgesdata"];
+            SimpleLogger().Write(logDEBUG) << "Geometry file:\t" << server_paths["geometries"];
+            SimpleLogger().Write(logDEBUG) << "RAM file:\t" << server_paths["ramindex"];
+            SimpleLogger().Write(logDEBUG) << "Index file:\t" << server_paths["fileindex"];
+            SimpleLogger().Write(logDEBUG) << "Names file:\t" << server_paths["namesdata"];
+            SimpleLogger().Write(logDEBUG) << "Timestamp file:\t" << server_paths["timestamp"];
+            SimpleLogger().Write(logDEBUG) << "Threads:\t" << requested_thread_num;
+            SimpleLogger().Write(logDEBUG) << "IP address:\t" << ip_address;
+            SimpleLogger().Write(logDEBUG) << "IP port:\t" << ip_port;
+        }
 #ifndef _WIN32
         int sig = 0;
         sigset_t new_mask;
@@ -93,63 +130,64 @@ int main (int argc, char * argv[]) {
         pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask);
 #endif
 
-        ServerConfiguration serverConfig((argc > 1 ? argv[1] : "server.ini"));
-        Server * s = ServerFactory::CreateServer(serverConfig);
-        RequestHandler & h = s->GetRequestHandlerPtr();
+        OSRM osrm_lib(server_paths, use_shared_memory);
+        Server *routing_server =
+            ServerFactory::CreateServer(ip_address, ip_port, requested_thread_num);
 
-        QueryObjectsStorage * objects = new QueryObjectsStorage(serverConfig.GetParameter("hsgrData"),
-                serverConfig.GetParameter("ramIndex"),
-                serverConfig.GetParameter("fileIndex"),
-                serverConfig.GetParameter("nodesData"),
-                serverConfig.GetParameter("edgesData"),
-                serverConfig.GetParameter("namesData"),
-                serverConfig.GetParameter("timestamp")
-                );
+        routing_server->GetRequestHandlerPtr().RegisterRoutingMachine(&osrm_lib);
 
-        h.RegisterPlugin(new HelloWorldPlugin());
-
-        h.RegisterPlugin(new LocatePlugin(objects));
-
-        h.RegisterPlugin(new NearestPlugin(objects));
-
-        h.RegisterPlugin(new TimestampPlugin(objects));
-
-        h.RegisterPlugin(new ViaRoutePlugin(objects));
-
-        boost::thread t(boost::bind(&Server::Run, s));
+        if (trial_run)
+        {
+            SimpleLogger().Write() << "trial run, quitting after successful initialization";
+        }
+        else
+        {
+            std::packaged_task<int()> server_task([&]()->int{ routing_server->Run(); return 0; });
+            auto future = server_task.get_future();
+            std::thread server_thread(std::move(server_task));
 
 #ifndef _WIN32
-        sigset_t wait_mask;
-        pthread_sigmask(SIG_SETMASK, &old_mask, 0);
-        sigemptyset(&wait_mask);
-        sigaddset(&wait_mask, SIGINT);
-        sigaddset(&wait_mask, SIGQUIT);
-        sigaddset(&wait_mask, SIGTERM);
-        pthread_sigmask(SIG_BLOCK, &wait_mask, 0);
-        std::cout << "[server] running and waiting for requests" << std::endl;
-        sigwait(&wait_mask, &sig);
+            sigset_t wait_mask;
+            pthread_sigmask(SIG_SETMASK, &old_mask, 0);
+            sigemptyset(&wait_mask);
+            sigaddset(&wait_mask, SIGINT);
+            sigaddset(&wait_mask, SIGQUIT);
+            sigaddset(&wait_mask, SIGTERM);
+            pthread_sigmask(SIG_BLOCK, &wait_mask, 0);
+            SimpleLogger().Write() << "running and waiting for requests";
+            sigwait(&wait_mask, &sig);
 #else
-        // Set console control handler to allow server to be stopped.
-        console_ctrl_function = boost::bind(&Server::Stop, s);
-        SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
-        std::cout << "[server] running and waiting for requests" << std::endl;
-        s->Run();
+            // Set console control handler to allow server to be stopped.
+            console_ctrl_function = std::bind(&Server::Stop, routing_server);
+            SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
+            SimpleLogger().Write() << "running and waiting for requests";
+            routing_server->Run();
 #endif
-
-        std::cout << "[server] initiating shutdown" << std::endl;
-        s->Stop();
-        std::cout << "[server] stopping threads" << std::endl;
-
-        if(!t.timed_join(boost::posix_time::seconds(2))) {
-//        	INFO("Threads did not finish within 2 seconds. Hard abort!");
+            SimpleLogger().Write() << "initiating shutdown";
+            routing_server->Stop();
+            SimpleLogger().Write() << "stopping threads";
+
+            auto status = future.wait_for(std::chrono::seconds(2));
+
+            if (status != std::future_status::ready)
+            {
+                SimpleLogger().Write(logWARNING) << "Didn't exit within 2 seconds. Hard abort!";
+                server_task.reset(); // just kill it
+            }
+            else
+            {
+                server_thread.join();
+            }
         }
 
-        std::cout << "[server] freeing objects" << std::endl;
-        delete s;
-        delete objects;
-        std::cout << "[server] shutdown completed" << std::endl;
-    } catch (std::exception& e) {
-        std::cerr << "[fatal error] exception: " << e.what() << std::endl;
+        SimpleLogger().Write() << "freeing objects";
+        delete routing_server;
+        SimpleLogger().Write() << "shutdown completed";
+    }
+    catch (const std::exception &e)
+    {
+        SimpleLogger().Write(logWARNING) << "exception: " << e.what();
+        return 1;
     }
 #ifdef __linux__
     munlockall();
diff --git a/server.ini b/server.ini
deleted file mode 100644
index 3fe844a..0000000
--- a/server.ini
+++ /dev/null
@@ -1,11 +0,0 @@
-Threads = 8
-IP = 0.0.0.0
-Port = 5000
-
-hsgrData=/opt/osm/berlin.osrm.hsgr
-nodesData=/opt/osm/berlin.osrm.nodes
-edgesData=/opt/osm/berlin.osrm.edges
-ramIndex=/opt/osm/berlin.osrm.ramIndex
-fileIndex=/opt/osm/berlin.osrm.fileIndex
-namesData=/opt/osm/berlin.osrm.names
-timestamp=/opt/osm/berlin.osrm.timestamp
diff --git a/test/contractor.ini b/test/contractor.ini
deleted file mode 100644
index 4da33c7..0000000
--- a/test/contractor.ini
+++ /dev/null
@@ -1 +0,0 @@
-Threads = 4
diff --git a/test/extractor.ini b/test/extractor.ini
deleted file mode 100644
index eca8b17..0000000
--- a/test/extractor.ini
+++ /dev/null
@@ -1 +0,0 @@
-Memory = 1
diff --git a/typedefs.h b/typedefs.h
index a962598..ff1d2a1 100644
--- a/typedefs.h
+++ b/typedefs.h
@@ -1,68 +1,50 @@
 /*
-    open source routing machine
-    Copyright (C) Dennis Luxen, 2010
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU AFFERO General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-any later version.
+Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+All rights reserved.
 
-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.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-You should have received a copy of the GNU Affero General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-or see http://www.gnu.org/licenses/agpl.txt.
- */
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
 
-#ifndef TYPEDEFS_H_
-#define TYPEDEFS_H_
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <cmath>
-#include <climits>
-#include <cstdlib>
+*/
 
-// To fix long and long long woes
-#include <boost/integer.hpp>
-#include <boost/integer_traits.hpp>
+#ifndef TYPEDEFS_H
+#define TYPEDEFS_H
 
-#ifdef __APPLE__
-#include <signal.h>
-#endif
-
-#include <iostream>
-
-#define INFO(x) do {std::cout << "[i " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl;} while(0);
-#define ERR(x) do {std::cerr << "[! " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl; std::exit(-1);} while(0);
-#define WARN(x) do {std::cerr << "[? " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl;} while(0);
-
-#ifdef NDEBUG
-#define DEBUG(x)
-#else
-#define DEBUG(x) do {std::cout << "[d " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl;} while(0);
-#endif
+#include <limits>
 
+// Necessary workaround for Windows as VS doesn't implement C99
+#ifdef _MSC_VER
 #ifndef M_PI
 #define M_PI 3.14159265358979323846
 #endif
-
-// Necessary workaround for Windows as VS doesn't implement C99
-#ifdef _MSC_VER
-template<typename digitT>
-digitT round(digitT x) {
-    return std::floor(x + 0.5);
-}
+#define constexpr const static
 #endif
 
-
 typedef unsigned int NodeID;
 typedef unsigned int EdgeID;
-typedef unsigned int EdgeWeight;
+typedef int EdgeWeight;
 
-static const NodeID SPECIAL_NODEID = boost::integer_traits<uint32_t>::const_max;
-static const EdgeID SPECIAL_EDGEID = boost::integer_traits<uint32_t>::const_max;
+constexpr NodeID SPECIAL_NODEID = std::numeric_limits<unsigned>::max();
+constexpr EdgeID SPECIAL_EDGEID = std::numeric_limits<unsigned>::max();
+constexpr unsigned INVALID_NAMEID = std::numeric_limits<unsigned>::max();
+constexpr EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<int>::max();
 
-#endif /* TYPEDEFS_H_ */
+#endif /* TYPEDEFS_H */
diff --git a/win/createHierarchy.vcproj b/win/createHierarchy.vcproj
deleted file mode 100644
index 428c56c..0000000
--- a/win/createHierarchy.vcproj
+++ /dev/null
@@ -1,459 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="9.00"
-	Name="createHierarchy"
-	ProjectGUID="{38C3EEAC-032B-4BEA-BECB-C694A47AA7E2}"
-	RootNamespace="createHierarchy"
-	Keyword="Win32Proj"
-	TargetFrameworkVersion="196613"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="$(SolutionDir)bin-debug"
-			IntermediateDirectory="$(SolutionDir)bin-debug"
-			ConfigurationType="1"
-			InheritedPropertySheets=".\osrm.vsprops"
-			CharacterSet="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				AdditionalOptions="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_RTLDLL -DBOOST_LIB_DIAGNOSTIC -DSTXXL_BOOST_TIMESTAMP -DSTXXL_BOOST_CONFIG -DSTXXL_BOOST_FILESYSTEM -DSTXXL_BOOST_THREADS -DSTXXL_BOOST_RANDOM /EHsc /EHs /wd4820 /wd4217 /wd4668 /wd4619 /wd4625 /wd4626 /wd4355 /wd4996 -D_SCL_SECURE_NO_DEPRECATE /F 16777216 /nologo "
-				Optimization="0"
-				AdditionalIncludeDirectories=""$(BoostPath)";"$(StxxlPath)\include";"$(LibXml2Path)\include";"$(IconvPath)\include";"$(SparsehashPath)\src\";"$(SparsehashPath)\src\windows";"$(Bzip2Path)\include";"$(ZlibPath)\include";..\;"$(ProtobufPath)\include";"$(SolutionDir)""
-				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="3"
-				OpenMP="true"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				DebugInformationFormat="4"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions="/STACK:16777216 /NOLOGO /OPT:REF"
-				AdditionalDependencies="libbz2.lib libxml2.lib zlibd.lib libprotobuf-debug.lib libstxxl-debug.lib"
-				LinkIncremental="2"
-				AdditionalLibraryDirectories=""$(BoostPath)\lib";"$(StxxlPath)\lib";"$(LibXml2Path)\lib";"$(IconvPath)\lib";"$(Bzip2Path)\lib";"$(ZlibPath)\lib";"$(ProtobufPath)\lib""
-				GenerateDebugInformation="true"
-				SubSystem="1"
-				RandomizedBaseAddress="1"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-				CommandLine="xcopy "$(SolutionDir)..\contractor.ini" "$(OutDir)\" /f /y"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="$(SolutionDir)bin"
-			IntermediateDirectory="$(SolutionDir)bin"
-			ConfigurationType="1"
-			InheritedPropertySheets=".\osrm.vsprops"
-			CharacterSet="1"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				AdditionalOptions="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_RTLDLL -DBOOST_LIB_DIAGNOSTIC -DSTXXL_BOOST_TIMESTAMP -DSTXXL_BOOST_CONFIG -DSTXXL_BOOST_FILESYSTEM -DSTXXL_BOOST_THREADS -DSTXXL_BOOST_RANDOM /EHsc /EHs /wd4820 /wd4217 /wd4668 /wd4619 /wd4625 /wd4626 /wd4355 /wd4996 -D_SCL_SECURE_NO_DEPRECATE /F 16777216 /nologo "
-				Optimization="2"
-				EnableIntrinsicFunctions="true"
-				AdditionalIncludeDirectories=""$(BoostPath)";"$(StxxlPath)\include";"$(LibXml2Path)\include";"$(IconvPath)\include";"$(SparsehashPath)\src\";"$(SparsehashPath)\src\windows";"$(Bzip2Path)\include";"$(ZlibPath)\include";..\;"$(ProtobufPath)\include""
-				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
-				RuntimeLibrary="2"
-				EnableFunctionLevelLinking="true"
-				OpenMP="true"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				DebugInformationFormat="0"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions="/STACK:16777216 /NOLOGO /OPT:REF"
-				AdditionalDependencies="libbz2.lib libxml2.lib zlib.lib libprotobuf.lib libstxxl.lib"
-				LinkIncremental="1"
-				AdditionalLibraryDirectories=""$(BoostPath)\lib";"$(StxxlPath)\lib";"$(LibXml2Path)\lib";"$(IconvPath)\lib";"$(Bzip2Path)\lib";"$(ZlibPath)\lib";"$(ProtobufPath)\lib""
-				GenerateDebugInformation="false"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				RandomizedBaseAddress="1"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-				CommandLine="xcopy "$(SolutionDir)..\contractor.ini" "$(OutDir)\" /f /y"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Source Files"
-			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
-			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
-			>
-			<File
-				RelativePath="..\createHierarchy.cpp"
-				>
-			</File>
-		</Filter>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl;inc;xsd"
-			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
-			>
-			<File
-				RelativePath="getopt.h"
-				>
-			</File>
-			<File
-				RelativePath="..\typedefs.h"
-				>
-			</File>
-			<File
-				RelativePath="unistd.h"
-				>
-			</File>
-			<Filter
-				Name="Contractor"
-				>
-				<File
-					RelativePath="..\Contractor\ContractionCleanup.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Contractor\Contractor.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="DataStructures"
-				>
-				<File
-					RelativePath="..\DataStructures\BaseParser.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\BinaryHeap.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\DynamicGraph.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\ExtractorCallBacks.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\ExtractorStructs.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\GridEdge.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\HashTable.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\ImportEdge.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\InputReaderFactory.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\LevelInformation.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\LRUCache.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\NNGrid.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\NodeCoords.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\NodeInformationHelpDesk.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\PBFParser.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\Percent.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\PhantomNodes.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\PolylineCompressor.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\SearchEngine.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\StaticGraph.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\StaticKDTree.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\Util.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\XMLParser.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="Plugins"
-				>
-				<File
-					RelativePath="..\Plugins\BaseDescriptor.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\BasePlugin.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\GPXDescriptor.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\HelloWorldPlugin.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\JSONDescriptor.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\KMLDescriptor.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\LocatePlugin.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\NearestPlugin.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\ObjectForPluginStruct.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\PluginMapFactory.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\RawRouteData.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\RouteParameters.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\RoutePlugin.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\ViaRoutePlugin.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="Server"
-				>
-				<File
-					RelativePath="..\Server\BasicDatastructures.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\Connection.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\RequestHandler.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\RequestParser.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\Server.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\ServerConfiguration.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\ServerFactory.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="Util"
-				>
-				<File
-					RelativePath="..\Util\BaseConfiguration.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Util\GraphLoader.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Util\InputFileUtil.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Util\LinuxStackTrace.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Util\MachineInfo.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Util\StringUtil.h"
-					>
-				</File>
-			</Filter>
-		</Filter>
-		<Filter
-			Name="Resource Files"
-			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
-			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
-			>
-		</Filter>
-		<File
-			RelativePath="..\DataStructures\pbf-proto\fileformat.proto"
-			>
-		</File>
-		<File
-			RelativePath="..\DataStructures\pbf-proto\osmformat.proto"
-			>
-		</File>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/win/extractor.vcproj b/win/extractor.vcproj
deleted file mode 100644
index 2821f87..0000000
--- a/win/extractor.vcproj
+++ /dev/null
@@ -1,532 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="9.00"
-	Name="extractor"
-	ProjectGUID="{F630F025-637A-43DF-9258-2860AE9E6740}"
-	RootNamespace="extractor"
-	Keyword="Win32Proj"
-	TargetFrameworkVersion="196613"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="$(SolutionDir)bin-debug"
-			IntermediateDirectory="$(SolutionDir)bin-debug"
-			ConfigurationType="1"
-			InheritedPropertySheets=".\osrm.vsprops"
-			CharacterSet="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-				CommandLine=""
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				AdditionalOptions="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_RTLDLL -DBOOST_LIB_DIAGNOSTIC -DSTXXL_BOOST_TIMESTAMP -DSTXXL_BOOST_CONFIG -DSTXXL_BOOST_FILESYSTEM -DSTXXL_BOOST_THREADS -DSTXXL_BOOST_RANDOM /EHsc /EHs /wd4820 /wd4217 /wd4668 /wd4619 /wd4625 /wd4626 /wd4355 /wd4996 -D_SCL_SECURE_NO_DEPRECATE /F 16777216 /nologo "
-				Optimization="0"
-				AdditionalIncludeDirectories=""$(BoostPath)";"$(StxxlPath)\include";"$(LibXml2Path)\include";"$(IconvPath)\include";"$(SparsehashPath)\src\";"$(SparsehashPath)\src\windows";"$(Bzip2Path)\include";"$(ZlibPath)\include";..\;"$(ProtobufPath)\include";"$(SolutionDir)""
-				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="3"
-				OpenMP="true"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				DebugInformationFormat="4"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions="/STACK:16777216 /NOLOGO /OPT:REF"
-				AdditionalDependencies="libbz2.lib libxml2.lib zlibd.lib libprotobuf-debug.lib libstxxl-debug.lib"
-				LinkIncremental="2"
-				AdditionalLibraryDirectories=""$(BoostPath)\lib";"$(StxxlPath)\lib";"$(LibXml2Path)\lib";"$(IconvPath)\lib";"$(Bzip2Path)\lib";"$(ZlibPath)\lib";"$(ProtobufPath)\lib""
-				GenerateDebugInformation="true"
-				SubSystem="1"
-				RandomizedBaseAddress="1"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-				CommandLine="xcopy "$(SolutionDir)..\.stxxl" "$(OutDir)\" /f /y&#x0D;&#x0A;xcopy "$(SolutionDir)..\extractor.ini" "$(OutDir)\" /f /y&#x0D;&#x0A;xcopy "$(SolutionDir)..\speedprofile.ini" "$(OutDir)\" /f /y&#x0D;&#x0A;xcopy "$(Bzip2Path)\bin\libbz2.dll" "$(OutDir)\" /f /y&#x0D;&#x0A;"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="$(SolutionDir)bin"
-			IntermediateDirectory="$(SolutionDir)bin"
-			ConfigurationType="1"
-			InheritedPropertySheets=".\osrm.vsprops"
-			CharacterSet="1"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				AdditionalOptions="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_RTLDLL -DBOOST_LIB_DIAGNOSTIC -DSTXXL_BOOST_TIMESTAMP -DSTXXL_BOOST_CONFIG -DSTXXL_BOOST_FILESYSTEM -DSTXXL_BOOST_THREADS -DSTXXL_BOOST_RANDOM /EHsc /EHs /wd4820 /wd4217 /wd4668 /wd4619 /wd4625 /wd4626 /wd4355 /wd4996 -D_SCL_SECURE_NO_DEPRECATE /F 16777216 /nologo "
-				Optimization="2"
-				EnableIntrinsicFunctions="true"
-				AdditionalIncludeDirectories=""$(BoostPath)";"$(StxxlPath)\include";"$(LibXml2Path)\include";"$(IconvPath)\include";"$(SparsehashPath)\src\";"$(SparsehashPath)\src\windows";"$(Bzip2Path)\include";"$(ZlibPath)\include";..\;"$(ProtobufPath)\include""
-				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
-				RuntimeLibrary="2"
-				EnableFunctionLevelLinking="true"
-				OpenMP="true"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				DebugInformationFormat="0"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions="/STACK:16777216 /NOLOGO /OPT:REF"
-				AdditionalDependencies="libbz2.lib libxml2.lib zlib.lib libprotobuf.lib libstxxl.lib"
-				LinkIncremental="1"
-				AdditionalLibraryDirectories=""$(BoostPath)\lib";"$(StxxlPath)\lib";"$(LibXml2Path)\lib";"$(IconvPath)\lib";"$(Bzip2Path)\lib";"$(ZlibPath)\lib";"$(ProtobufPath)\lib""
-				GenerateDebugInformation="false"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				RandomizedBaseAddress="1"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-				CommandLine="xcopy "$(SolutionDir)..\.stxxl" "$(OutDir)\" /f /y&#x0D;&#x0A;xcopy "$(SolutionDir)..\extractor.ini" "$(OutDir)\" /f /y&#x0D;&#x0A;xcopy "$(SolutionDir)..\speedprofile.ini" "$(OutDir)\" /f /y&#x0D;&#x0A;xcopy "$(Bzip2Path)\bin\libbz2.dll" "$(OutDir)\" /f /y&#x0D;&#x0A;"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Source Files"
-			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
-			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
-			>
-			<File
-				RelativePath="..\extractor.cpp"
-				>
-			</File>
-			<Filter
-				Name="DataStructures"
-				>
-				<Filter
-					Name="pbf-proto"
-					>
-					<File
-						RelativePath="..\DataStructures\pbf-proto\fileformat.pb.cc"
-						>
-					</File>
-					<File
-						RelativePath="..\DataStructures\pbf-proto\osmformat.pb.cc"
-						>
-					</File>
-				</Filter>
-			</Filter>
-		</Filter>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl;inc;xsd"
-			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
-			>
-			<File
-				RelativePath="getopt.h"
-				>
-			</File>
-			<File
-				RelativePath="..\typedefs.h"
-				>
-			</File>
-			<File
-				RelativePath="unistd.h"
-				>
-			</File>
-			<Filter
-				Name="Contractor"
-				>
-				<File
-					RelativePath="..\Contractor\ContractionCleanup.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Contractor\Contractor.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="DataStructures"
-				>
-				<File
-					RelativePath="..\DataStructures\BaseParser.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\BinaryHeap.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\ConcurrentQueue.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\DynamicGraph.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\ExtractorCallBacks.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\ExtractorStructs.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\GridEdge.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\HashTable.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\ImportEdge.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\InputReaderFactory.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\LevelInformation.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\LRUCache.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\NNGrid.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\NodeCoords.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\NodeInformationHelpDesk.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\PBFParser.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\Percent.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\PhantomNodes.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\PolylineCompressor.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\SearchEngine.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\StaticGraph.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\StaticKDTree.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\Util.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\XMLParser.h"
-					>
-				</File>
-				<Filter
-					Name="pbf-proto"
-					>
-					<File
-						RelativePath="..\DataStructures\pbf-proto\fileformat.pb.h"
-						>
-					</File>
-					<File
-						RelativePath="..\DataStructures\pbf-proto\osmformat.pb.h"
-						>
-					</File>
-				</Filter>
-			</Filter>
-			<Filter
-				Name="Plugins"
-				>
-				<File
-					RelativePath="..\Plugins\BaseDescriptor.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\BasePlugin.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\GPXDescriptor.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\HelloWorldPlugin.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\JSONDescriptor.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\KMLDescriptor.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\LocatePlugin.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\NearestPlugin.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\ObjectForPluginStruct.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\PluginMapFactory.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\RawRouteData.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\RouteParameters.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\RoutePlugin.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\ViaRoutePlugin.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="Server"
-				>
-				<File
-					RelativePath="..\Server\BasicDatastructures.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\Connection.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\RequestHandler.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\RequestParser.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\Server.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\ServerConfiguration.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\ServerFactory.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="Util"
-				>
-				<File
-					RelativePath="..\Util\BaseConfiguration.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Util\GraphLoader.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Util\InputFileUtil.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Util\LinuxStackTrace.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Util\MachineInfo.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Util\StringUtil.h"
-					>
-				</File>
-			</Filter>
-		</Filter>
-		<Filter
-			Name="Resource Files"
-			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
-			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
-			>
-		</Filter>
-		<File
-			RelativePath="..\DataStructures\pbf-proto\fileformat.proto"
-			>
-			<FileConfiguration
-				Name="Debug|Win32"
-				>
-				<Tool
-					Name="VCCustomBuildTool"
-					Description="Generating fileformat.pb.{h,cc}..."
-					CommandLine=""$(ProtobufPath)/bin/protoc" -I"$(SolutionDir).." --cpp_out=.. "$(SolutionDir)../DataStructures/pbf-proto/fileformat.proto"&#x0D;&#x0A;"
-					Outputs=""$(SolutionDir)../DataStructures/pbf-proto/fileformat.pb.h";"$(SolutionDir)../DataStructures/pbf-proto/fileformat.pb.cc""
-				/>
-			</FileConfiguration>
-			<FileConfiguration
-				Name="Release|Win32"
-				>
-				<Tool
-					Name="VCCustomBuildTool"
-					Description="Generating fileformat.pb.{h,cc}..."
-					CommandLine=""$(ProtobufPath)/bin/protoc" -I"$(SolutionDir).." --cpp_out=.. "$(SolutionDir)../DataStructures/pbf-proto/fileformat.proto"&#x0D;&#x0A;"
-					Outputs=""$(SolutionDir)../DataStructures/pbf-proto/fileformat.pb.h";"$(SolutionDir)../DataStructures/pbf-proto/fileformat.pb.cc""
-				/>
-			</FileConfiguration>
-		</File>
-		<File
-			RelativePath="..\DataStructures\pbf-proto\osmformat.proto"
-			>
-			<FileConfiguration
-				Name="Debug|Win32"
-				>
-				<Tool
-					Name="VCCustomBuildTool"
-					Description="Generating osmformat.pb.{h,cc}..."
-					CommandLine=""$(ProtobufPath)/bin/protoc" -I"$(SolutionDir).." --cpp_out=.. "$(SolutionDir)../DataStructures/pbf-proto/osmformat.proto"&#x0D;&#x0A;"
-					Outputs=""$(SolutionDir)../DataStructures/pbf-proto/osmformat.pb.h";"$(SolutionDir)../DataStructures/pbf-proto/osmformat.pb.cc""
-				/>
-			</FileConfiguration>
-			<FileConfiguration
-				Name="Release|Win32"
-				>
-				<Tool
-					Name="VCCustomBuildTool"
-					Description="Generating osmformat.pb.{h,cc}..."
-					CommandLine=""$(ProtobufPath)/bin/protoc" -I"$(SolutionDir).." --cpp_out=.. "$(SolutionDir)../DataStructures/pbf-proto/osmformat.proto"&#x0D;&#x0A;"
-					Outputs=""$(SolutionDir)../DataStructures/pbf-proto/osmformat.pb.h";"$(SolutionDir)../DataStructures/pbf-proto/osmformat.pb.cc""
-				/>
-			</FileConfiguration>
-		</File>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/win/getopt.c b/win/getopt.c
deleted file mode 100644
index d19c36f..0000000
--- a/win/getopt.c
+++ /dev/null
@@ -1,1260 +0,0 @@
-#ifdef _WIN32
-/* Getopt for GNU.
-   NOTE: getopt is now part of the C library, so if you don't know what
-   "Keep this file name-space clean" means, talk to drepper at gnu.org
-   before changing it!
-   Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001
-        Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
-   Ditto for AIX 3.2 and <stdlib.h>.  */
-#ifndef _NO_PROTO
-# define _NO_PROTO
-#endif
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if !defined __STDC__ || !__STDC__
-/* This is a separate conditional since some stdc systems
-   reject `defined (const)'.  */
-# ifndef const
-#  define const
-# endif
-#endif
-
-#include <stdio.h>
-
-/* Comment out all this code if we are using the GNU C Library, and are not
-   actually compiling the library itself.  This code is part of the GNU C
-   Library, but also included in many other GNU distributions.  Compiling
-   and linking in this code is a waste when using the GNU C library
-   (especially if it is a shared library).  Rather than having every GNU
-   program understand `configure --with-gnu-libc' and omit the object files,
-   it is simpler to just do this in the source for each such file.  */
-
-#define GETOPT_INTERFACE_VERSION 2
-#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
-# include <gnu-versions.h>
-# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
-#  define ELIDE_CODE
-# endif
-#endif
-
-#ifndef ELIDE_CODE
-
-
-/* This needs to come after some library #include
-   to get __GNU_LIBRARY__ defined.  */
-#ifdef  __GNU_LIBRARY__
-/* Don't include stdlib.h for non-GNU C libraries because some of them
-   contain conflicting prototypes for getopt.  */
-# include <stdlib.h>
-# include <unistd.h>
-#endif  /* GNU C library.  */
-
-#ifdef VMS
-# include <unixlib.h>
-# if HAVE_STRING_H - 0
-#  include <string.h>
-# endif
-#endif
-
-#ifndef _
-/* This is for other GNU distributions with internationalized messages.  */
-# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
-#  include <libintl.h>
-#  ifndef _
-#   define _(msgid)     gettext (msgid)
-#  endif
-# else
-#  define _(msgid)      (msgid)
-# endif
-# if defined _LIBC && defined USE_IN_LIBIO
-#  include <wchar.h>
-# endif
-#endif
-
-/* This version of `getopt' appears to the caller like standard Unix `getopt'
-   but it behaves differently for the user, since it allows the user
-   to intersperse the options with the other arguments.
-
-   As `getopt' works, it permutes the elements of ARGV so that,
-   when it is done, all the options precede everything else.  Thus
-   all application programs are extended to handle flexible argument order.
-
-   Setting the environment variable POSIXLY_CORRECT disables permutation.
-   Then the behavior is completely standard.
-
-   GNU application programs can use a third alternative mode in which
-   they can distinguish the relative order of options and other arguments.  */
-
-#include "getopt.h"
-
-/* For communication from `getopt' to the caller.
-   When `getopt' finds an option that takes an argument,
-   the argument value is returned here.
-   Also, when `ordering' is RETURN_IN_ORDER,
-   each non-option ARGV-element is returned here.  */
-
-char *optarg;
-
-/* Index in ARGV of the next element to be scanned.
-   This is used for communication to and from the caller
-   and for communication between successive calls to `getopt'.
-
-   On entry to `getopt', zero means this is the first call; initialize.
-
-   When `getopt' returns -1, this is the index of the first of the
-   non-option elements that the caller should itself scan.
-
-   Otherwise, `optind' communicates from one call to the next
-   how much of ARGV has been scanned so far.  */
-
-/* 1003.2 says this must be 1 before any call.  */
-int optind = 1;
-
-/* Formerly, initialization of getopt depended on optind==0, which
-   causes problems with re-calling getopt as programs generally don't
-   know that. */
-
-int __getopt_initialized;
-
-/* The next char to be scanned in the option-element
-   in which the last option character we returned was found.
-   This allows us to pick up the scan where we left off.
-
-   If this is zero, or a null string, it means resume the scan
-   by advancing to the next ARGV-element.  */
-
-static char *nextchar;
-
-/* Callers store zero here to inhibit the error message
-   for unrecognized options.  */
-
-int opterr = 1;
-
-/* Set to an option character which was unrecognized.
-   This must be initialized on some systems to avoid linking in the
-   system's own getopt implementation.  */
-
-int optopt = '?';
-
-/* Describe how to deal with options that follow non-option ARGV-elements.
-
-   If the caller did not specify anything,
-   the default is REQUIRE_ORDER if the environment variable
-   POSIXLY_CORRECT is defined, PERMUTE otherwise.
-
-   REQUIRE_ORDER means don't recognize them as options;
-   stop option processing when the first non-option is seen.
-   This is what Unix does.
-   This mode of operation is selected by either setting the environment
-   variable POSIXLY_CORRECT, or using `+' as the first character
-   of the list of option characters.
-
-   PERMUTE is the default.  We permute the contents of ARGV as we scan,
-   so that eventually all the non-options are at the end.  This allows options
-   to be given in any order, even with programs that were not written to
-   expect this.
-
-   RETURN_IN_ORDER is an option available to programs that were written
-   to expect options and other ARGV-elements in any order and that care about
-   the ordering of the two.  We describe each non-option ARGV-element
-   as if it were the argument of an option with character code 1.
-   Using `-' as the first character of the list of option characters
-   selects this mode of operation.
-
-   The special argument `--' forces an end of option-scanning regardless
-   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
-   `--' can cause `getopt' to return -1 with `optind' != ARGC.  */
-
-static enum
-{
-  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
-} ordering;
-
-/* Value of POSIXLY_CORRECT environment variable.  */
-static char *posixly_correct;
-
-#ifdef  __GNU_LIBRARY__
-/* We want to avoid inclusion of string.h with non-GNU libraries
-   because there are many ways it can cause trouble.
-   On some systems, it contains special magic macros that don't work
-   in GCC.  */
-# include <string.h>
-# define my_index       strchr
-#else
-
-# if HAVE_STRING_H || WIN32 /* Pete Wilson mod 7/28/02 */
-#  include <string.h>
-# else
-#  include <strings.h>
-# endif
-
-/* Avoid depending on library functions or files
-   whose names are inconsistent.  */
-
-#ifndef getenv
-extern char *getenv ();
-#endif
-
-static char *
-my_index (str, chr)
-     const char *str;
-     int chr;
-{
-  while (*str)
-    {
-      if (*str == chr)
-        return (char *) str;
-      str++;
-    }
-  return 0;
-}
-
-/* If using GCC, we can safely declare strlen this way.
-   If not using GCC, it is ok not to declare it.  */
-#ifdef __GNUC__
-/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
-   That was relevant to code that was here before.  */
-# if (!defined __STDC__ || !__STDC__) && !defined strlen
-/* gcc with -traditional declares the built-in strlen to return int,
-   and has done so at least since version 2.4.5. -- rms.  */
-extern int strlen (const char *);
-# endif /* not __STDC__ */
-#endif /* __GNUC__ */
-
-#endif /* not __GNU_LIBRARY__ */
-
-/* Handle permutation of arguments.  */
-
-/* Describe the part of ARGV that contains non-options that have
-   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
-   `last_nonopt' is the index after the last of them.  */
-
-static int first_nonopt;
-static int last_nonopt;
-
-#ifdef _LIBC
-/* Stored original parameters.
-   XXX This is no good solution.  We should rather copy the args so
-   that we can compare them later.  But we must not use malloc(3).  */
-extern int __libc_argc;
-extern char **__libc_argv;
-
-/* Bash 2.0 gives us an environment variable containing flags
-   indicating ARGV elements that should not be considered arguments.  */
-
-# ifdef USE_NONOPTION_FLAGS
-/* Defined in getopt_init.c  */
-extern char *__getopt_nonoption_flags;
-
-static int nonoption_flags_max_len;
-static int nonoption_flags_len;
-# endif
-
-# ifdef USE_NONOPTION_FLAGS
-#  define SWAP_FLAGS(ch1, ch2) \
-  if (nonoption_flags_len > 0)                                                \
-    {                                                                         \
-      char __tmp = __getopt_nonoption_flags[ch1];                             \
-      __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2];          \
-      __getopt_nonoption_flags[ch2] = __tmp;                                  \
-    }
-# else
-#  define SWAP_FLAGS(ch1, ch2)
-# endif
-#else   /* !_LIBC */
-# define SWAP_FLAGS(ch1, ch2)
-#endif  /* _LIBC */
-
-/* Exchange two adjacent subsequences of ARGV.
-   One subsequence is elements [first_nonopt,last_nonopt)
-   which contains all the non-options that have been skipped so far.
-   The other is elements [last_nonopt,optind), which contains all
-   the options processed since those non-options were skipped.
-
-   `first_nonopt' and `last_nonopt' are relocated so that they describe
-   the new indices of the non-options in ARGV after they are moved.  */
-
-#if defined __STDC__ && __STDC__
-static void exchange (char **);
-#endif
-
-static void
-exchange (argv)
-     char **argv;
-{
-  int bottom = first_nonopt;
-  int middle = last_nonopt;
-  int top = optind;
-  char *tem;
-
-  /* Exchange the shorter segment with the far end of the longer segment.
-     That puts the shorter segment into the right place.
-     It leaves the longer segment in the right place overall,
-     but it consists of two parts that need to be swapped next.  */
-
-#if defined _LIBC && defined USE_NONOPTION_FLAGS
-  /* First make sure the handling of the `__getopt_nonoption_flags'
-     string can work normally.  Our top argument must be in the range
-     of the string.  */
-  if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
-    {
-      /* We must extend the array.  The user plays games with us and
-         presents new arguments.  */
-      char *new_str = malloc (top + 1);
-      if (new_str == NULL)
-        nonoption_flags_len = nonoption_flags_max_len = 0;
-      else
-        {
-          memset (__mempcpy (new_str, __getopt_nonoption_flags,
-                             nonoption_flags_max_len),
-                  '\0', top + 1 - nonoption_flags_max_len);
-          nonoption_flags_max_len = top + 1;
-          __getopt_nonoption_flags = new_str;
-        }
-    }
-#endif
-
-  while (top > middle && middle > bottom)
-    {
-      if (top - middle > middle - bottom)
-        {
-          /* Bottom segment is the short one.  */
-          int len = middle - bottom;
-          register int i;
-
-          /* Swap it with the top part of the top segment.  */
-          for (i = 0; i < len; i++)
-            {
-              tem = argv[bottom + i];
-              argv[bottom + i] = argv[top - (middle - bottom) + i];
-              argv[top - (middle - bottom) + i] = tem;
-              SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
-            }
-          /* Exclude the moved bottom segment from further swapping.  */
-          top -= len;
-        }
-      else
-        {
-          /* Top segment is the short one.  */
-          int len = top - middle;
-          register int i;
-
-          /* Swap it with the bottom part of the bottom segment.  */
-          for (i = 0; i < len; i++)
-            {
-              tem = argv[bottom + i];
-              argv[bottom + i] = argv[middle + i];
-              argv[middle + i] = tem;
-              SWAP_FLAGS (bottom + i, middle + i);
-            }
-          /* Exclude the moved top segment from further swapping.  */
-          bottom += len;
-        }
-    }
-
-  /* Update records for the slots the non-options now occupy.  */
-
-  first_nonopt += (optind - last_nonopt);
-  last_nonopt = optind;
-}
-
-/* Initialize the internal data when the first call is made.  */
-
-#if defined __STDC__ && __STDC__
-static const char *_getopt_initialize (int, char *const *, const char *);
-#endif
-static const char *
-_getopt_initialize (argc, argv, optstring)
-     int argc;
-     char *const *argv;
-     const char *optstring;
-{
-  /* Start processing options with ARGV-element 1 (since ARGV-element 0
-     is the program name); the sequence of previously skipped
-     non-option ARGV-elements is empty.  */
-
-  first_nonopt = last_nonopt = optind;
-
-  nextchar = NULL;
-
-  posixly_correct = getenv ("POSIXLY_CORRECT");
-
-  /* Determine how to handle the ordering of options and nonoptions.  */
-
-  if (optstring[0] == '-')
-    {
-      ordering = RETURN_IN_ORDER;
-      ++optstring;
-    }
-  else if (optstring[0] == '+')
-    {
-      ordering = REQUIRE_ORDER;
-      ++optstring;
-    }
-  else if (posixly_correct != NULL)
-    ordering = REQUIRE_ORDER;
-  else
-    ordering = PERMUTE;
-
-#if defined _LIBC && defined USE_NONOPTION_FLAGS
-  if (posixly_correct == NULL
-      && argc == __libc_argc && argv == __libc_argv)
-    {
-      if (nonoption_flags_max_len == 0)
-        {
-          if (__getopt_nonoption_flags == NULL
-              || __getopt_nonoption_flags[0] == '\0')
-            nonoption_flags_max_len = -1;
-          else
-            {
-              const char *orig_str = __getopt_nonoption_flags;
-              int len = nonoption_flags_max_len = strlen (orig_str);
-              if (nonoption_flags_max_len < argc)
-                nonoption_flags_max_len = argc;
-              __getopt_nonoption_flags =
-                (char *) malloc (nonoption_flags_max_len);
-              if (__getopt_nonoption_flags == NULL)
-                nonoption_flags_max_len = -1;
-              else
-                memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
-                        '\0', nonoption_flags_max_len - len);
-            }
-        }
-      nonoption_flags_len = nonoption_flags_max_len;
-    }
-  else
-    nonoption_flags_len = 0;
-#endif
-
-  return optstring;
-}
-
-/* Scan elements of ARGV (whose length is ARGC) for option characters
-   given in OPTSTRING.
-
-   If an element of ARGV starts with '-', and is not exactly "-" or "--",
-   then it is an option element.  The characters of this element
-   (aside from the initial '-') are option characters.  If `getopt'
-   is called repeatedly, it returns successively each of the option characters
-   from each of the option elements.
-
-   If `getopt' finds another option character, it returns that character,
-   updating `optind' and `nextchar' so that the next call to `getopt' can
-   resume the scan with the following option character or ARGV-element.
-
-   If there are no more option characters, `getopt' returns -1.
-   Then `optind' is the index in ARGV of the first ARGV-element
-   that is not an option.  (The ARGV-elements have been permuted
-   so that those that are not options now come last.)
-
-   OPTSTRING is a string containing the legitimate option characters.
-   If an option character is seen that is not listed in OPTSTRING,
-   return '?' after printing an error message.  If you set `opterr' to
-   zero, the error message is suppressed but we still return '?'.
-
-   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
-   so the following text in the same ARGV-element, or the text of the following
-   ARGV-element, is returned in `optarg'.  Two colons mean an option that
-   wants an optional arg; if there is text in the current ARGV-element,
-   it is returned in `optarg', otherwise `optarg' is set to zero.
-
-   If OPTSTRING starts with `-' or `+', it requests different methods of
-   handling the non-option ARGV-elements.
-   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
-
-   Long-named options begin with `--' instead of `-'.
-   Their names may be abbreviated as long as the abbreviation is unique
-   or is an exact match for some defined option.  If they have an
-   argument, it follows the option name in the same ARGV-element, separated
-   from the option name by a `=', or else the in next ARGV-element.
-   When `getopt' finds a long-named option, it returns 0 if that option's
-   `flag' field is nonzero, the value of the option's `val' field
-   if the `flag' field is zero.
-
-   The elements of ARGV aren't really const, because we permute them.
-   But we pretend they're const in the prototype to be compatible
-   with other systems.
-
-   LONGOPTS is a vector of `struct option' terminated by an
-   element containing a name which is zero.
-
-   LONGIND returns the index in LONGOPT of the long-named option found.
-   It is only valid when a long-named option has been found by the most
-   recent call.
-
-   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
-   long-named options.  */
-
-int
-_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
-     int argc;
-     char *const *argv;
-     const char *optstring;
-     const struct option *longopts;
-     int *longind;
-     int long_only;
-{
-  int print_errors = opterr;
-  if (optstring[0] == ':')
-    print_errors = 0;
-
-  if (argc < 1)
-    return -1;
-
-  optarg = NULL;
-
-  if (optind == 0 || !__getopt_initialized)
-    {
-      if (optind == 0)
-        optind = 1;     /* Don't scan ARGV[0], the program name.  */
-      optstring = _getopt_initialize (argc, argv, optstring);
-      __getopt_initialized = 1;
-    }
-
-  /* Test whether ARGV[optind] points to a non-option argument.
-     Either it does not have option syntax, or there is an environment flag
-     from the shell indicating it is not an option.  The later information
-     is only used when the used in the GNU libc.  */
-#if defined _LIBC && defined USE_NONOPTION_FLAGS
-# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0'       \
-                      || (optind < nonoption_flags_len                        \
-                          && __getopt_nonoption_flags[optind] == '1'))
-#else
-# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
-#endif
-
-  if (nextchar == NULL || *nextchar == '\0')
-    {
-      /* Advance to the next ARGV-element.  */
-
-      /* Give FIRST_NONOPT and LAST_NONOPT rational values if OPTIND has been
-         moved back by the user (who may also have changed the arguments).  */
-      if (last_nonopt > optind)
-        last_nonopt = optind;
-      if (first_nonopt > optind)
-        first_nonopt = optind;
-
-      if (ordering == PERMUTE)
-        {
-          /* If we have just processed some options following some non-options,
-             exchange them so that the options come first.  */
-
-          if (first_nonopt != last_nonopt && last_nonopt != optind)
-            exchange ((char **) argv);
-          else if (last_nonopt != optind)
-            first_nonopt = optind;
-
-          /* Skip any additional non-options
-             and extend the range of non-options previously skipped.  */
-
-          while (optind < argc && NONOPTION_P)
-            optind++;
-          last_nonopt = optind;
-        }
-
-      /* The special ARGV-element `--' means premature end of options.
-         Skip it like a null option,
-         then exchange with previous non-options as if it were an option,
-         then skip everything else like a non-option.  */
-
-      if (optind != argc && !strcmp (argv[optind], "--"))
-        {
-          optind++;
-
-          if (first_nonopt != last_nonopt && last_nonopt != optind)
-            exchange ((char **) argv);
-          else if (first_nonopt == last_nonopt)
-            first_nonopt = optind;
-          last_nonopt = argc;
-
-          optind = argc;
-        }
-
-      /* If we have done all the ARGV-elements, stop the scan
-         and back over any non-options that we skipped and permuted.  */
-
-      if (optind == argc)
-        {
-          /* Set the next-arg-index to point at the non-options
-             that we previously skipped, so the caller will digest them.  */
-          if (first_nonopt != last_nonopt)
-            optind = first_nonopt;
-          return -1;
-        }
-
-      /* If we have come to a non-option and did not permute it,
-         either stop the scan or describe it to the caller and pass it by.  */
-
-      if (NONOPTION_P)
-        {
-          if (ordering == REQUIRE_ORDER)
-            return -1;
-          optarg = argv[optind++];
-          return 1;
-        }
-
-      /* We have found another option-ARGV-element.
-         Skip the initial punctuation.  */
-
-      nextchar = (argv[optind] + 1
-                  + (longopts != NULL && argv[optind][1] == '-'));
-    }
-
-  /* Decode the current option-ARGV-element.  */
-
-  /* Check whether the ARGV-element is a long option.
-
-     If long_only and the ARGV-element has the form "-f", where f is
-     a valid short option, don't consider it an abbreviated form of
-     a long option that starts with f.  Otherwise there would be no
-     way to give the -f short option.
-
-     On the other hand, if there's a long option "fubar" and
-     the ARGV-element is "-fu", do consider that an abbreviation of
-     the long option, just like "--fu", and not "-f" with arg "u".
-
-     This distinction seems to be the most useful approach.  */
-
-  if (longopts != NULL
-      && (argv[optind][1] == '-'
-          || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
-    {
-      char *nameend;
-      const struct option *p;
-      const struct option *pfound = NULL;
-      int exact = 0;
-      int ambig = 0;
-      int indfound = -1;
-      int option_index;
-
-      for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
-        /* Do nothing.  */ ;
-
-      /* Test all long options for either exact match
-         or abbreviated matches.  */
-      for (p = longopts, option_index = 0; p->name; p++, option_index++)
-        if (!strncmp (p->name, nextchar, nameend - nextchar))
-          {
-            if ((unsigned int) (nameend - nextchar)
-                == (unsigned int) strlen (p->name))
-              {
-                /* Exact match found.  */
-                pfound = p;
-                indfound = option_index;
-                exact = 1;
-                break;
-              }
-            else if (pfound == NULL)
-              {
-                /* First nonexact match found.  */
-                pfound = p;
-                indfound = option_index;
-              }
-            else if (long_only
-                     || pfound->has_arg != p->has_arg
-                     || pfound->flag != p->flag
-                     || pfound->val != p->val)
-              /* Second or later nonexact match found.  */
-              ambig = 1;
-          }
-
-      if (ambig && !exact)
-        {
-          if (print_errors)
-            {
-#if defined _LIBC && defined USE_IN_LIBIO
-              char *buf;
-
-              __asprintf (&buf, _("%s: option `%s' is ambiguous\n"),
-                          argv[0], argv[optind]);
-
-              if (_IO_fwide (stderr, 0) > 0)
-                __fwprintf (stderr, L"%s", buf);
-              else
-                fputs (buf, stderr);
-
-              free (buf);
-#else
-              fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
-                       argv[0], argv[optind]);
-#endif
-            }
-          nextchar += strlen (nextchar);
-          optind++;
-          optopt = 0;
-          return '?';
-        }
-
-      if (pfound != NULL)
-        {
-          option_index = indfound;
-          optind++;
-          if (*nameend)
-            {
-              /* Don't test has_arg with >, because some C compilers don't
-                 allow it to be used on enums.  */
-              if (pfound->has_arg)
-                optarg = nameend + 1;
-              else
-                {
-                  if (print_errors)
-                    {
-#if defined _LIBC && defined USE_IN_LIBIO
-                      char *buf;
-#endif
-
-                      if (argv[optind - 1][1] == '-')
-                        {
-                          /* --option */
-#if defined _LIBC && defined USE_IN_LIBIO
-                          __asprintf (&buf, _("\
-%s: option `--%s' doesn't allow an argument\n"),
-                                      argv[0], pfound->name);
-#else
-                          fprintf (stderr, _("\
-%s: option `--%s' doesn't allow an argument\n"),
-                                   argv[0], pfound->name);
-#endif
-                        }
-                      else
-                        {
-                          /* +option or -option */
-#if defined _LIBC && defined USE_IN_LIBIO
-                          __asprintf (&buf, _("\
-%s: option `%c%s' doesn't allow an argument\n"),
-                                      argv[0], argv[optind - 1][0],
-                                      pfound->name);
-#else
-                          fprintf (stderr, _("\
-%s: option `%c%s' doesn't allow an argument\n"),
-                                   argv[0], argv[optind - 1][0], pfound->name);
-#endif
-                        }
-
-#if defined _LIBC && defined USE_IN_LIBIO
-                      if (_IO_fwide (stderr, 0) > 0)
-                        __fwprintf (stderr, L"%s", buf);
-                      else
-                        fputs (buf, stderr);
-
-                      free (buf);
-#endif
-                    }
-
-                  nextchar += strlen (nextchar);
-
-                  optopt = pfound->val;
-                  return '?';
-                }
-            }
-          else if (pfound->has_arg == 1)
-            {
-              if (optind < argc)
-                optarg = argv[optind++];
-              else
-                {
-                  if (print_errors)
-                    {
-#if defined _LIBC && defined USE_IN_LIBIO
-                      char *buf;
-
-                      __asprintf (&buf,
-                                  _("%s: option `%s' requires an argument\n"),
-                                  argv[0], argv[optind - 1]);
-
-                      if (_IO_fwide (stderr, 0) > 0)
-                        __fwprintf (stderr, L"%s", buf);
-                      else
-                        fputs (buf, stderr);
-
-                      free (buf);
-#else
-                      fprintf (stderr,
-                               _("%s: option `%s' requires an argument\n"),
-                               argv[0], argv[optind - 1]);
-#endif
-                    }
-                  nextchar += strlen (nextchar);
-                  optopt = pfound->val;
-                  return optstring[0] == ':' ? ':' : '?';
-                }
-            }
-          nextchar += strlen (nextchar);
-          if (longind != NULL)
-            *longind = option_index;
-          if (pfound->flag)
-            {
-              *(pfound->flag) = pfound->val;
-              return 0;
-            }
-          return pfound->val;
-        }
-
-      /* Can't find it as a long option.  If this is not getopt_long_only,
-         or the option starts with '--' or is not a valid short
-         option, then it's an error.
-         Otherwise interpret it as a short option.  */
-      if (!long_only || argv[optind][1] == '-'
-          || my_index (optstring, *nextchar) == NULL)
-        {
-          if (print_errors)
-            {
-#if defined _LIBC && defined USE_IN_LIBIO
-              char *buf;
-#endif
-
-              if (argv[optind][1] == '-')
-                {
-                  /* --option */
-#if defined _LIBC && defined USE_IN_LIBIO
-                  __asprintf (&buf, _("%s: unrecognized option `--%s'\n"),
-                              argv[0], nextchar);
-#else
-                  fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
-                           argv[0], nextchar);
-#endif
-                }
-              else
-                {
-                  /* +option or -option */
-#if defined _LIBC && defined USE_IN_LIBIO
-                  __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"),
-                              argv[0], argv[optind][0], nextchar);
-#else
-                  fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
-                           argv[0], argv[optind][0], nextchar);
-#endif
-                }
-
-#if defined _LIBC && defined USE_IN_LIBIO
-              if (_IO_fwide (stderr, 0) > 0)
-                __fwprintf (stderr, L"%s", buf);
-              else
-                fputs (buf, stderr);
-
-              free (buf);
-#endif
-            }
-          nextchar = (char *) "";
-          optind++;
-          optopt = 0;
-          return '?';
-        }
-    }
-
-  /* Look at and handle the next short option-character.  */
-
-  {
-    char c = *nextchar++;
-    char *temp = my_index (optstring, c);
-
-    /* Increment `optind' when we start to process its last character.  */
-    if (*nextchar == '\0')
-      ++optind;
-
-    if (temp == NULL || c == ':')
-      {
-        if (print_errors)
-          {
-#if defined _LIBC && defined USE_IN_LIBIO
-              char *buf;
-#endif
-
-            if (posixly_correct)
-              {
-                /* 1003.2 specifies the format of this message.  */
-#if defined _LIBC && defined USE_IN_LIBIO
-                __asprintf (&buf, _("%s: illegal option -- %c\n"),
-                            argv[0], c);
-#else
-                fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c);
-#endif
-              }
-            else
-              {
-#if defined _LIBC && defined USE_IN_LIBIO
-                __asprintf (&buf, _("%s: invalid option -- %c\n"),
-                            argv[0], c);
-#else
-                fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c);
-#endif
-              }
-
-#if defined _LIBC && defined USE_IN_LIBIO
-            if (_IO_fwide (stderr, 0) > 0)
-              __fwprintf (stderr, L"%s", buf);
-            else
-              fputs (buf, stderr);
-
-            free (buf);
-#endif
-          }
-        optopt = c;
-        return '?';
-      }
-    /* Convenience. Treat POSIX -W foo same as long option --foo */
-    if (temp[0] == 'W' && temp[1] == ';')
-      {
-        char *nameend;
-        const struct option *p;
-        const struct option *pfound = NULL;
-        int exact = 0;
-        int ambig = 0;
-        int indfound = 0;
-        int option_index;
-
-        /* This is an option that requires an argument.  */
-        if (*nextchar != '\0')
-          {
-            optarg = nextchar;
-            /* If we end this ARGV-element by taking the rest as an arg,
-               we must advance to the next element now.  */
-            optind++;
-          }
-        else if (optind == argc)
-          {
-            if (print_errors)
-              {
-                /* 1003.2 specifies the format of this message.  */
-#if defined _LIBC && defined USE_IN_LIBIO
-                char *buf;
-
-                __asprintf (&buf, _("%s: option requires an argument -- %c\n"),
-                            argv[0], c);
-
-                if (_IO_fwide (stderr, 0) > 0)
-                  __fwprintf (stderr, L"%s", buf);
-                else
-                  fputs (buf, stderr);
-
-                free (buf);
-#else
-                fprintf (stderr, _("%s: option requires an argument -- %c\n"),
-                         argv[0], c);
-#endif
-              }
-            optopt = c;
-            if (optstring[0] == ':')
-              c = ':';
-            else
-              c = '?';
-            return c;
-          }
-        else
-          /* We already incremented `optind' once;
-             increment it again when taking next ARGV-elt as argument.  */
-          optarg = argv[optind++];
-
-        /* optarg is now the argument, see if it's in the
-           table of longopts.  */
-
-        for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
-          /* Do nothing.  */ ;
-
-        /* Test all long options for either exact match
-           or abbreviated matches.  */
-        for (p = longopts, option_index = 0; p->name; p++, option_index++)
-          if (!strncmp (p->name, nextchar, nameend - nextchar))
-            {
-              if ((unsigned int) (nameend - nextchar) == strlen (p->name))
-                {
-                  /* Exact match found.  */
-                  pfound = p;
-                  indfound = option_index;
-                  exact = 1;
-                  break;
-                }
-              else if (pfound == NULL)
-                {
-                  /* First nonexact match found.  */
-                  pfound = p;
-                  indfound = option_index;
-                }
-              else
-                /* Second or later nonexact match found.  */
-                ambig = 1;
-            }
-        if (ambig && !exact)
-          {
-            if (print_errors)
-              {
-#if defined _LIBC && defined USE_IN_LIBIO
-                char *buf;
-
-                __asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"),
-                            argv[0], argv[optind]);
-
-                if (_IO_fwide (stderr, 0) > 0)
-                  __fwprintf (stderr, L"%s", buf);
-                else
-                  fputs (buf, stderr);
-
-                free (buf);
-#else
-                fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
-                         argv[0], argv[optind]);
-#endif
-              }
-            nextchar += strlen (nextchar);
-            optind++;
-            return '?';
-          }
-        if (pfound != NULL)
-          {
-            option_index = indfound;
-            if (*nameend)
-              {
-                /* Don't test has_arg with >, because some C compilers don't
-                   allow it to be used on enums.  */
-                if (pfound->has_arg)
-                  optarg = nameend + 1;
-                else
-                  {
-                    if (print_errors)
-                      {
-#if defined _LIBC && defined USE_IN_LIBIO
-                        char *buf;
-
-                        __asprintf (&buf, _("\
-%s: option `-W %s' doesn't allow an argument\n"),
-                                    argv[0], pfound->name);
-
-                        if (_IO_fwide (stderr, 0) > 0)
-                          __fwprintf (stderr, L"%s", buf);
-                        else
-                          fputs (buf, stderr);
-
-                        free (buf);
-#else
-                        fprintf (stderr, _("\
-%s: option `-W %s' doesn't allow an argument\n"),
-                                 argv[0], pfound->name);
-#endif
-                      }
-
-                    nextchar += strlen (nextchar);
-                    return '?';
-                  }
-              }
-            else if (pfound->has_arg == 1)
-              {
-                if (optind < argc)
-                  optarg = argv[optind++];
-                else
-                  {
-                    if (print_errors)
-                      {
-#if defined _LIBC && defined USE_IN_LIBIO
-                        char *buf;
-
-                        __asprintf (&buf, _("\
-%s: option `%s' requires an argument\n"),
-                                    argv[0], argv[optind - 1]);
-
-                        if (_IO_fwide (stderr, 0) > 0)
-                          __fwprintf (stderr, L"%s", buf);
-                        else
-                          fputs (buf, stderr);
-
-                        free (buf);
-#else
-                        fprintf (stderr,
-                                 _("%s: option `%s' requires an argument\n"),
-                                 argv[0], argv[optind - 1]);
-#endif
-                      }
-                    nextchar += strlen (nextchar);
-                    return optstring[0] == ':' ? ':' : '?';
-                  }
-              }
-            nextchar += strlen (nextchar);
-            if (longind != NULL)
-              *longind = option_index;
-            if (pfound->flag)
-              {
-                *(pfound->flag) = pfound->val;
-                return 0;
-              }
-            return pfound->val;
-          }
-          nextchar = NULL;
-          return 'W';   /* Let the application handle it.   */
-      }
-    if (temp[1] == ':')
-      {
-        if (temp[2] == ':')
-          {
-            /* This is an option that accepts an argument optionally.  */
-            if (*nextchar != '\0')
-              {
-                optarg = nextchar;
-                optind++;
-              }
-            else
-              optarg = NULL;
-            nextchar = NULL;
-          }
-        else
-          {
-            /* This is an option that requires an argument.  */
-            if (*nextchar != '\0')
-              {
-                optarg = nextchar;
-                /* If we end this ARGV-element by taking the rest as an arg,
-                   we must advance to the next element now.  */
-                optind++;
-              }
-            else if (optind == argc)
-              {
-                if (print_errors)
-                  {
-                    /* 1003.2 specifies the format of this message.  */
-#if defined _LIBC && defined USE_IN_LIBIO
-                    char *buf;
-
-                    __asprintf (&buf,
-                                _("%s: option requires an argument -- %c\n"),
-                                argv[0], c);
-
-                    if (_IO_fwide (stderr, 0) > 0)
-                      __fwprintf (stderr, L"%s", buf);
-                    else
-                      fputs (buf, stderr);
-
-                    free (buf);
-#else
-                    fprintf (stderr,
-                             _("%s: option requires an argument -- %c\n"),
-                             argv[0], c);
-#endif
-                  }
-                optopt = c;
-                if (optstring[0] == ':')
-                  c = ':';
-                else
-                  c = '?';
-              }
-            else
-              /* We already incremented `optind' once;
-                 increment it again when taking next ARGV-elt as argument.  */
-              optarg = argv[optind++];
-            nextchar = NULL;
-          }
-      }
-    return c;
-  }
-}
-
-int
-getopt (argc, argv, optstring)
-     int argc;
-     char *const *argv;
-     const char *optstring;
-{
-  return _getopt_internal (argc, argv, optstring,
-                           (const struct option *) 0,
-                           (int *) 0,
-                           0);
-}
-
-#endif  /* Not ELIDE_CODE.  */
-
-
-/* Compile with -DTEST to make an executable for use in testing
-   the above definition of `getopt'.  */
-
-/* #define TEST */        /* Pete Wilson mod 7/28/02 */
-#ifdef TEST
-
-#ifndef exit         /* Pete Wilson mod 7/28/02 */
-  int exit(int);     /* Pete Wilson mod 7/28/02 */
-#endif               /* Pete Wilson mod 7/28/02 */
-
-int
-main (argc, argv)
-     int argc;
-     char **argv;
-{
-  int c;
-  int digit_optind = 0;
-
-  while (1)
-    {
-      int this_option_optind = optind ? optind : 1;
-
-      c = getopt (argc, argv, "abc:d:0123456789");
-      if (c == -1)
-        break;
-
-      switch (c)
-        {
-        case '0':
-        case '1':
-        case '2':
-        case '3':
-        case '4':
-        case '5':
-        case '6':
-        case '7':
-        case '8':
-        case '9':
-          if (digit_optind != 0 && digit_optind != this_option_optind)
-            printf ("digits occur in two different argv-elements.\n");
-          digit_optind = this_option_optind;
-          printf ("option %c\n", c);
-          break;
-
-        case 'a':
-          printf ("option a\n");
-          break;
-
-        case 'b':
-          printf ("option b\n");
-          break;
-
-        case 'c':
-          printf ("option c with value `%s'\n", optarg);
-          break;
-
-        case '?':
-          break;
-
-        default:
-          printf ("?? getopt returned character code 0%o ??\n", c);
-        }
-    }
-
-  if (optind < argc)
-    {
-      printf ("non-option ARGV-elements: ");
-      while (optind < argc)
-        printf ("%s ", argv[optind++]);
-      printf ("\n");
-    }
-
-  exit (0);
-}
-
-#endif /* TEST */
-#endif
diff --git a/win/getopt.h b/win/getopt.h
deleted file mode 100644
index 455d531..0000000
--- a/win/getopt.h
+++ /dev/null
@@ -1,189 +0,0 @@
-#ifdef _WIN32
-/* getopt.h */
-/* Declarations for getopt.
-   Copyright (C) 1989-1994, 1996-1999, 2001 Free Software 
-   Foundation, Inc. This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute 
-   it and/or modify it under the terms of the GNU Lesser 
-   General Public License as published by the Free Software 
-   Foundation; either version 2.1 of the License, or 
-   (at your option) any later version.
-
-   The GNU C Library 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 Lesser General Public 
-   License for more details.
-
-   You should have received a copy of the GNU Lesser General 
-   Public License along with the GNU C Library; if not, write 
-   to the Free Software Foundation, Inc., 59 Temple Place,
-   Suite 330, Boston, MA 02111-1307 USA.  */
-
-  
-  
-
-#ifndef _GETOPT_H
-
-#ifndef __need_getopt
-# define _GETOPT_H 1
-#endif
-
-/* If __GNU_LIBRARY__ is not already defined, either we are being used
-   standalone, or this is the first header included in the source file.
-   If we are being used with glibc, we need to include <features.h>, but
-   that does not exist if we are standalone.  So: if __GNU_LIBRARY__ is
-   not defined, include <ctype.h>, which will pull in <features.h> for us
-   if it's from glibc.  (Why ctype.h?  It's guaranteed to exist and it
-   doesn't flood the namespace with stuff the way some other headers do.)  */
-#if !defined __GNU_LIBRARY__
-# include <ctype.h>
-#endif
-
-#ifdef  __cplusplus
-extern "C" {
-#endif
-
-/* For communication from `getopt' to the caller.
-   When `getopt' finds an option that takes an argument,
-   the argument value is returned here.
-   Also, when `ordering' is RETURN_IN_ORDER,
-   each non-option ARGV-element is returned here.  */
-
-extern char *optarg;
-
-/* Index in ARGV of the next element to be scanned.
-   This is used for communication to and from the caller
-   and for communication between successive calls to `getopt'.
-
-   On entry to `getopt', zero means this is the first call; initialize.
-
-   When `getopt' returns -1, this is the index of the first of the
-   non-option elements that the caller should itself scan.
-
-   Otherwise, `optind' communicates from one call to the next
-   how much of ARGV has been scanned so far.  */
-
-extern int optind;
-
-/* Callers store zero here to inhibit the error message `getopt' prints
-   for unrecognized options.  */
-
-extern int opterr;
-
-/* Set to an option character which was unrecognized.  */
-
-extern int optopt;
-
-#ifndef __need_getopt
-/* Describe the long-named options requested by the application.
-   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
-   of `struct option' terminated by an element containing a name which is
-   zero.
-
-   The field `has_arg' is:
-   no_argument          (or 0) if the option does not take an argument,
-   required_argument    (or 1) if the option requires an argument,
-   optional_argument    (or 2) if the option takes an optional argument.
-
-   If the field `flag' is not NULL, it points to a variable that is set
-   to the value given in the field `val' when the option is found, but
-   left unchanged if the option is not found.
-
-   To have a long-named option do something other than set an `int' to
-   a compiled-in constant, such as set a value from `optarg', set the
-   option's `flag' field to zero and its `val' field to a nonzero
-   value (the equivalent single-letter option character, if there is
-   one).  For long options that have a zero `flag' field, `getopt'
-   returns the contents of the `val' field.  */
-
-struct option
-{
-# if (defined __STDC__ && __STDC__) || defined __cplusplus
-  const char *name;
-# else
-  char *name;
-# endif
-  /* has_arg can't be an enum because some compilers complain about
-     type mismatches in all the code that assumes it is an int.  */
-  int has_arg;
-  int *flag;
-  int val;
-};
-
-/* Names for the values of the `has_arg' field of `struct option'.  */
-
-# define no_argument            0
-# define required_argument      1
-# define optional_argument      2
-#endif  /* need getopt */
-
-
-/* Get definitions and prototypes for functions to process the
-   arguments in ARGV (ARGC of them, minus the program name) for
-   options given in OPTS.
-
-   Return the option character from OPTS just read.  Return -1 when
-   there are no more options.  For unrecognized options, or options
-   missing arguments, `optopt' is set to the option letter, and '?' is
-   returned.
-
-   The OPTS string is a list of characters which are recognized option
-   letters, optionally followed by colons, specifying that that letter
-   takes an argument, to be placed in `optarg'.
-
-   If a letter in OPTS is followed by two colons, its argument is
-   optional.  This behavior is specific to the GNU `getopt'.
-
-   The argument `--' causes premature termination of argument
-   scanning, explicitly telling `getopt' that there are no more
-   options.
-
-   If OPTS begins with `--', then non-option arguments are treated as
-   arguments to the option '\0'.  This behavior is specific to the GNU
-   `getopt'.  */
-
-#if (defined __STDC__ && __STDC__) || defined __cplusplus
-# ifdef __GNU_LIBRARY__
-/* Many other libraries have conflicting prototypes for getopt, with
-   differences in the consts, in stdlib.h.  To avoid compilation
-   errors, only prototype getopt for the GNU C library.  */
-extern int getopt (int ___argc, char *const *___argv, const char *__shortopts);
-# else /* not __GNU_LIBRARY__ */
-extern int getopt ();
-# endif /* __GNU_LIBRARY__ */
-
-# ifndef __need_getopt
-extern int getopt_long (int ___argc, char *const *___argv,
-                        const char *__shortopts,
-                        const struct option *__longopts, int *__longind);
-extern int getopt_long_only (int ___argc, char *const *___argv,
-                             const char *__shortopts,
-                             const struct option *__longopts, int *__longind);
-
-/* Internal only.  Users should not call this directly.  */
-extern int _getopt_internal (int ___argc, char *const *___argv,
-                             const char *__shortopts,
-                             const struct option *__longopts, int *__longind,
-                             int __long_only);
-# endif
-#else /* not __STDC__ */
-extern int getopt ();
-# ifndef __need_getopt
-extern int getopt_long ();
-extern int getopt_long_only ();
-
-extern int _getopt_internal ();
-# endif
-#endif /* __STDC__ */
-
-#ifdef  __cplusplus
-}
-#endif
-
-/* Make sure we later can get all the definitions and declarations.  */
-#undef __need_getopt
-
-#endif /* getopt.h */
-#endif
diff --git a/win/osrm.sln b/win/osrm.sln
deleted file mode 100644
index 62634fc..0000000
--- a/win/osrm.sln
+++ /dev/null
@@ -1,29 +0,0 @@
-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual Studio 2008
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "extractor", "extractor.vcproj", "{F630F025-637A-43DF-9258-2860AE9E6740}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "createHierarchy", "createHierarchy.vcproj", "{38C3EEAC-032B-4BEA-BECB-C694A47AA7E2}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "routed", "routed.vcproj", "{675D419D-E442-4A21-9030-B54B4C09439A}"
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Win32 = Debug|Win32
-		Release|Win32 = Release|Win32
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{F630F025-637A-43DF-9258-2860AE9E6740}.Debug|Win32.ActiveCfg = Debug|Win32
-		{F630F025-637A-43DF-9258-2860AE9E6740}.Debug|Win32.Build.0 = Debug|Win32
-		{F630F025-637A-43DF-9258-2860AE9E6740}.Release|Win32.ActiveCfg = Release|Win32
-		{F630F025-637A-43DF-9258-2860AE9E6740}.Release|Win32.Build.0 = Release|Win32
-		{38C3EEAC-032B-4BEA-BECB-C694A47AA7E2}.Debug|Win32.ActiveCfg = Debug|Win32
-		{38C3EEAC-032B-4BEA-BECB-C694A47AA7E2}.Release|Win32.ActiveCfg = Release|Win32
-		{38C3EEAC-032B-4BEA-BECB-C694A47AA7E2}.Release|Win32.Build.0 = Release|Win32
-		{675D419D-E442-4A21-9030-B54B4C09439A}.Debug|Win32.ActiveCfg = Debug|Win32
-		{675D419D-E442-4A21-9030-B54B4C09439A}.Release|Win32.ActiveCfg = Release|Win32
-		{675D419D-E442-4A21-9030-B54B4C09439A}.Release|Win32.Build.0 = Release|Win32
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-EndGlobal
diff --git a/win/osrm.vsprops b/win/osrm.vsprops
deleted file mode 100644
index 08d15be..0000000
--- a/win/osrm.vsprops
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioPropertySheet
-	ProjectType="Visual C++"
-	Version="8.00"
-	Name="osrm"
-	>
-	<UserMacro
-		Name="BoostPath"
-		Value="$(SolutionDir)lib\boost_1_47\"
-	/>
-	<UserMacro
-		Name="Bzip2Path"
-		Value="$(SolutionDir)lib\bzip2-1.0.6\"
-	/>
-	<UserMacro
-		Name="IconvPath"
-		Value="$(SolutionDir)lib\iconv-1.9.2.win32\"
-	/>
-	<UserMacro
-		Name="LibXml2Path"
-		Value="$(SolutionDir)lib\libxml2-2.7.8.win32\"
-	/>
-	<UserMacro
-		Name="ProtobufPath"
-		Value="$(SolutionDir)lib\protobuf-2.4.1\"
-	/>
-	<UserMacro
-		Name="SparsehashPath"
-		Value="$(SolutionDir)lib\sparsehash-1.11\"
-	/>
-	<UserMacro
-		Name="StxxlPath"
-		Value="$(SolutionDir)lib\stxxl-1.3.1\"
-	/>
-	<UserMacro
-		Name="ZlibPath"
-		Value="$(SolutionDir)lib\zlib-1.2.5\"
-	/>
-</VisualStudioPropertySheet>
diff --git a/win/routed.vcproj b/win/routed.vcproj
deleted file mode 100644
index 8f4c183..0000000
--- a/win/routed.vcproj
+++ /dev/null
@@ -1,459 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="9.00"
-	Name="routed"
-	ProjectGUID="{675D419D-E442-4A21-9030-B54B4C09439A}"
-	RootNamespace="routed"
-	Keyword="Win32Proj"
-	TargetFrameworkVersion="196613"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="$(SolutionDir)bin-debug"
-			IntermediateDirectory="$(SolutionDir)bin-debug"
-			ConfigurationType="1"
-			InheritedPropertySheets=".\osrm.vsprops"
-			CharacterSet="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				AdditionalOptions="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_RTLDLL -DBOOST_LIB_DIAGNOSTIC -DSTXXL_BOOST_TIMESTAMP -DSTXXL_BOOST_CONFIG -DSTXXL_BOOST_FILESYSTEM -DSTXXL_BOOST_THREADS -DSTXXL_BOOST_RANDOM /EHsc /EHs /wd4820 /wd4217 /wd4668 /wd4619 /wd4625 /wd4626 /wd4355 /wd4996 -D_SCL_SECURE_NO_DEPRECATE /F 16777216 /nologo "
-				Optimization="0"
-				AdditionalIncludeDirectories=""$(BoostPath)";"$(StxxlPath)\include";"$(LibXml2Path)\include";"$(IconvPath)\include";"$(SparsehashPath)\src\";"$(SparsehashPath)\src\windows";"$(Bzip2Path)\include";"$(ZlibPath)\include";..\;"$(ProtobufPath)\include";"$(SolutionDir)""
-				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="3"
-				OpenMP="true"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				DebugInformationFormat="4"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions="/STACK:16777216 /NOLOGO /OPT:REF"
-				AdditionalDependencies="libbz2.lib libxml2.lib zlibd.lib libprotobuf-debug.lib libstxxl-debug.lib"
-				LinkIncremental="2"
-				AdditionalLibraryDirectories=""$(BoostPath)\lib";"$(StxxlPath)\lib";"$(LibXml2Path)\lib";"$(IconvPath)\lib";"$(Bzip2Path)\lib";"$(ZlibPath)\lib";"$(ProtobufPath)\lib""
-				GenerateDebugInformation="true"
-				SubSystem="1"
-				RandomizedBaseAddress="1"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-				CommandLine="xcopy "$(SolutionDir)..\server.ini" "$(OutDir)\" /f /y"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="$(SolutionDir)bin"
-			IntermediateDirectory="$(SolutionDir)bin"
-			ConfigurationType="1"
-			InheritedPropertySheets=".\osrm.vsprops"
-			CharacterSet="1"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				AdditionalOptions="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_RTLDLL -DBOOST_LIB_DIAGNOSTIC -DSTXXL_BOOST_TIMESTAMP -DSTXXL_BOOST_CONFIG -DSTXXL_BOOST_FILESYSTEM -DSTXXL_BOOST_THREADS -DSTXXL_BOOST_RANDOM /EHsc /EHs /wd4820 /wd4217 /wd4668 /wd4619 /wd4625 /wd4626 /wd4355 /wd4996 -D_SCL_SECURE_NO_DEPRECATE /F 16777216 /nologo "
-				Optimization="2"
-				EnableIntrinsicFunctions="true"
-				AdditionalIncludeDirectories=""$(BoostPath)";"$(StxxlPath)\include";"$(LibXml2Path)\include";"$(IconvPath)\include";"$(SparsehashPath)\src\";"$(SparsehashPath)\src\windows";"$(Bzip2Path)\include";"$(ZlibPath)\include";..\;"$(ProtobufPath)\include""
-				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
-				RuntimeLibrary="2"
-				EnableFunctionLevelLinking="true"
-				OpenMP="true"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				DebugInformationFormat="0"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions="/STACK:16777216 /NOLOGO /OPT:REF"
-				AdditionalDependencies="libbz2.lib libxml2.lib zlib.lib libprotobuf.lib libstxxl.lib"
-				LinkIncremental="1"
-				AdditionalLibraryDirectories=""$(BoostPath)\lib";"$(StxxlPath)\lib";"$(LibXml2Path)\lib";"$(IconvPath)\lib";"$(Bzip2Path)\lib";"$(ZlibPath)\lib";"$(ProtobufPath)\lib""
-				GenerateDebugInformation="false"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				RandomizedBaseAddress="1"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-				CommandLine="xcopy "$(SolutionDir)..\server.ini" "$(OutDir)\" /f /y"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Source Files"
-			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
-			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
-			>
-			<File
-				RelativePath="..\routed.cpp"
-				>
-			</File>
-		</Filter>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl;inc;xsd"
-			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
-			>
-			<File
-				RelativePath="getopt.h"
-				>
-			</File>
-			<File
-				RelativePath="..\typedefs.h"
-				>
-			</File>
-			<File
-				RelativePath="unistd.h"
-				>
-			</File>
-			<Filter
-				Name="Contractor"
-				>
-				<File
-					RelativePath="..\Contractor\ContractionCleanup.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Contractor\Contractor.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="DataStructures"
-				>
-				<File
-					RelativePath="..\DataStructures\BaseParser.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\BinaryHeap.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\DynamicGraph.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\ExtractorCallBacks.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\ExtractorStructs.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\GridEdge.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\HashTable.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\ImportEdge.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\InputReaderFactory.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\LevelInformation.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\LRUCache.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\NNGrid.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\NodeCoords.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\NodeInformationHelpDesk.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\PBFParser.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\Percent.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\PhantomNodes.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\PolylineCompressor.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\SearchEngine.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\StaticGraph.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\StaticKDTree.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\Util.h"
-					>
-				</File>
-				<File
-					RelativePath="..\DataStructures\XMLParser.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="Plugins"
-				>
-				<File
-					RelativePath="..\Plugins\BaseDescriptor.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\BasePlugin.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\GPXDescriptor.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\HelloWorldPlugin.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\JSONDescriptor.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\KMLDescriptor.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\LocatePlugin.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\NearestPlugin.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\ObjectForPluginStruct.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\PluginMapFactory.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\RawRouteData.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\RouteParameters.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\RoutePlugin.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Plugins\ViaRoutePlugin.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="Server"
-				>
-				<File
-					RelativePath="..\Server\BasicDatastructures.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\Connection.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\RequestHandler.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\RequestParser.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\Server.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\ServerConfiguration.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Server\ServerFactory.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="Util"
-				>
-				<File
-					RelativePath="..\Util\BaseConfiguration.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Util\GraphLoader.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Util\InputFileUtil.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Util\LinuxStackTrace.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Util\MachineInfo.h"
-					>
-				</File>
-				<File
-					RelativePath="..\Util\StringUtil.h"
-					>
-				</File>
-			</Filter>
-		</Filter>
-		<Filter
-			Name="Resource Files"
-			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
-			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
-			>
-		</Filter>
-		<File
-			RelativePath="..\DataStructures\pbf-proto\fileformat.proto"
-			>
-		</File>
-		<File
-			RelativePath="..\DataStructures\pbf-proto\osmformat.proto"
-			>
-		</File>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/win/unistd.h b/win/unistd.h
deleted file mode 100644
index 442c158..0000000
--- a/win/unistd.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifdef _WIN32
-#ifndef _UNISTD_H
-#define _UNISTD_H    1
-
-/* This file intended to serve as a drop-in replacement for 
- *  unistd.h on Windows
- *  Please add functionality as neeeded 
- */
-
-#include <stdlib.h>
-#include <io.h>
-#include <getopt.h> /* getopt from: http://www.pwilson.net/sample.html. */
-
-#define srandom srand
-#define random rand
-
-const int W_OK = 2;
-const int R_OK = 4;
-
-#define access _access
-#define ftruncate _chsize
-
-#define ssize_t int
-
-#define STDIN_FILENO 0
-#define STDOUT_FILENO 1
-#define STDERR_FILENO 2
-
-#endif /* unistd.h  */
-#endif

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



More information about the Pkg-grass-devel mailing list