[osrm] 01/02: Imported Upstream version 0.3.4

Andreas Tille tille at debian.org
Thu Jul 10 14:39:07 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 733f53b86ddbebd14c1686da8aa49b4b4a0a9dc7
Author: Andreas Tille <tille at debian.org>
Date:   Thu Jul 10 16:34:57 2014 +0200

    Imported Upstream version 0.3.4
---
 .gitignore                                    |   82 ++
 .gitmodules                                   |    0
 AUTHORS.TXT                                   |   11 +
 Algorithms/Bresenham.h                        |   49 +
 Algorithms/CRC32.cpp                          |   85 ++
 Algorithms/CRC32.h                            |   45 +
 Algorithms/DouglasPeucker.h                   |  129 +++
 Algorithms/IteratorBasedCRC32.h               |  109 +++
 Algorithms/ObjectToBase64.h                   |   67 ++
 Algorithms/PolylineCompressor.h               |  134 +++
 Algorithms/StronglyConnectedComponents.h      |  373 ++++++++
 CMakeLists.txt                                |  111 +++
 Contractor/ContractionCleanup.h               |  261 +++++
 Contractor/Contractor.h                       |  783 +++++++++++++++
 Contractor/EdgeBasedGraphFactory.cpp          |  412 ++++++++
 Contractor/EdgeBasedGraphFactory.h            |  162 ++++
 Contractor/TemporaryStorage.cpp               |  144 +++
 Contractor/TemporaryStorage.h                 |  113 +++
 DataStructures/BinaryHeap.h                   |  267 ++++++
 DataStructures/ConcurrentQueue.h              |   83 ++
 DataStructures/Coordinate.h                   |  108 +++
 DataStructures/DeallocatingVector.h           |  318 +++++++
 DataStructures/DynamicGraph.h                 |  233 +++++
 DataStructures/GridEdge.h                     |   82 ++
 DataStructures/HashTable.h                    |   79 ++
 DataStructures/HilbertValue.h                 |   87 ++
 DataStructures/ImportEdge.h                   |  142 +++
 DataStructures/ImportNode.h                   |   54 ++
 DataStructures/InputReaderFactory.h           |   94 ++
 DataStructures/LRUCache.h                     |   82 ++
 DataStructures/MercatorUtil.h                 |   38 +
 DataStructures/NNGrid.h                       |  602 ++++++++++++
 DataStructures/NodeCoords.h                   |   69 ++
 DataStructures/NodeInformationHelpDesk.h      |  159 ++++
 DataStructures/Percent.h                      |   94 ++
 DataStructures/PhantomNodes.h                 |   94 ++
 DataStructures/QueryEdge.h                    |   76 ++
 DataStructures/Restriction.h                  |   97 ++
 DataStructures/SearchEngine.cpp               |   89 ++
 DataStructures/SearchEngine.h                 |   68 ++
 DataStructures/SearchEngineData.cpp           |   60 ++
 DataStructures/SearchEngineData.h             |   60 ++
 DataStructures/SegmentInformation.h           |   42 +
 DataStructures/SimpleStack.h                  |   71 ++
 DataStructures/StaticGraph.h                  |  188 ++++
 DataStructures/StaticKDTree.h                 |  223 +++++
 DataStructures/StaticRTree.h                  |  909 ++++++++++++++++++
 DataStructures/TimingUtil.h                   |   50 +
 DataStructures/TurnInstructions.h             |   90 ++
 DataStructures/XORFastHash.h                  |   95 ++
 DataStructures/XORFastHashStorage.h           |   80 ++
 Descriptors/BaseDescriptor.h                  |   55 ++
 Descriptors/DescriptionFactory.cpp            |  210 +++++
 Descriptors/DescriptionFactory.h              |   76 ++
 Descriptors/GPXDescriptor.h                   |   65 ++
 Descriptors/JSONDescriptor.h                  |  392 ++++++++
 Docs/webclient.txt                            |    3 +
 Extractor/BaseParser.cpp                      |  116 +++
 Extractor/BaseParser.h                        |   59 ++
 Extractor/ExtractionContainers.cpp            |  306 ++++++
 Extractor/ExtractionContainers.h              |   69 ++
 Extractor/ExtractionHelperFunctions.h         |   83 ++
 Extractor/ExtractorCallbacks.cpp              |  142 +++
 Extractor/ExtractorCallbacks.h                |   57 ++
 Extractor/ExtractorStructs.h                  |  222 +++++
 Extractor/PBFParser.cpp                       |  482 ++++++++++
 Extractor/PBFParser.h                         |  102 ++
 Extractor/ScriptingEnvironment.cpp            |  108 +++
 Extractor/ScriptingEnvironment.h              |   50 +
 Extractor/XMLParser.cpp                       |  276 ++++++
 Extractor/XMLParser.h                         |   42 +
 Gemfile                                       |    7 +
 Gemfile.lock                                  |   30 +
 LICENCE.TXT                                   |  661 +++++++++++++
 Plugins/BasePlugin.h                          |   41 +
 Plugins/HelloWorldPlugin.h                    |   50 +
 Plugins/LocatePlugin.h                        |  113 +++
 Plugins/NearestPlugin.h                       |  124 +++
 Plugins/PluginMapFactory.h                    |   34 +
 Plugins/RawRouteData.h                        |   45 +
 Plugins/RouteParameters.h                     |  107 +++
 Plugins/TimestampPlugin.h                     |   75 ++
 Plugins/ViaRoutePlugin.h                      |  224 +++++
 README.TXT                                    |   27 +
 Rakefile                                      |  211 +++++
 RoutingAlgorithms/AlternativePathRouting.h    |  535 +++++++++++
 RoutingAlgorithms/BasicRoutingInterface.h     |  225 +++++
 RoutingAlgorithms/ShortestPathRouting.h       |  201 ++++
 Server/APIGrammar.h                           |   63 ++
 Server/BasicDatastructures.h                  |  157 +++
 Server/Connection.h                           |  181 ++++
 Server/DataStructures/QueryObjectsStorage.cpp |  100 ++
 Server/DataStructures/QueryObjectsStorage.h   |   47 +
 Server/RequestHandler.h                       |  117 +++
 Server/RequestParser.h                        |  291 ++++++
 Server/Server.h                               |   88 ++
 Server/ServerConfiguration.h                  |   28 +
 Server/ServerFactory.h                        |   84 ++
 Tools/.gitignore                              |    1 +
 Tools/componentAnalysis.cpp                   |  102 ++
 Util/Azimuth.h                                |   52 +
 Util/BaseConfiguration.h                      |  107 +++
 Util/ContainerUtils.h                         |   34 +
 Util/GraphLoader.h                            |  377 ++++++++
 Util/InputFileUtil.h                          |   46 +
 Util/LinuxStackTrace.h                        |  156 +++
 Util/LuaUtil.h                                |   57 ++
 Util/MachineInfo.h                            |   86 ++
 Util/OpenMPWrapper.h                          |   34 +
 Util/StringUtil.h                             |  163 ++++
 cmake/FindLuabind.cmake                       |   75 ++
 cmake/FindOSMPBF.cmake                        |   54 ++
 cmake/FindSTXXL.cmake                         |   51 +
 cmake/GetGitRevisionDescription.cmake         |  123 +++
 config/cucumber.yml                           |    5 +
 contractor.ini                                |    1 +
 createHierarchy.cpp                           |  276 ++++++
 extractor.cpp                                 |  123 +++
 extractor.ini                                 |    2 +
 features/bicycle/access.feature               |  173 ++++
 features/bicycle/access_node.feature          |   64 ++
 features/bicycle/area.feature                 |  103 ++
 features/bicycle/barrier.feature              |   39 +
 features/bicycle/cycleway.feature             |   81 ++
 features/bicycle/destination.feature          |   77 ++
 features/bicycle/ferry.feature                |   63 ++
 features/bicycle/maxspeed.feature             |   70 ++
 features/bicycle/mode.feature                 |   89 ++
 features/bicycle/names.feature                |   49 +
 features/bicycle/oneway.feature               |  128 +++
 features/bicycle/pushing.feature              |  124 +++
 features/bicycle/ref.feature                  |   41 +
 features/bicycle/restrictions.feature         |  289 ++++++
 features/bicycle/stop_area.feature            |   37 +
 features/bicycle/train.feature                |   39 +
 features/bicycle/turn_penalty.feature         |   33 +
 features/bicycle/way.feature                  |   41 +
 features/car/access.feature                   |  144 +++
 features/car/barrier.feature                  |   38 +
 features/car/destination.feature              |   77 ++
 features/car/ferry.feature                    |   30 +
 features/car/maxspeed.feature                 |   54 ++
 features/car/names.feature                    |   33 +
 features/car/oneway.feature                   |   73 ++
 features/car/permissive.feature               |    0
 features/car/restrictions.feature             |  251 +++++
 features/car/shuttle_train.feature            |   33 +
 features/car/way.feature                      |   33 +
 features/foot/maxspeed.feature                |   20 +
 features/foot/oneway.feature                  |   60 ++
 features/foot/way.feature                     |   32 +
 features/investigate/weird.feature            |   42 +
 features/nearest/pick.feature                 |   56 ++
 features/nearest/projection.feature           |  105 +++
 features/step_definitions/data.rb             |  121 +++
 features/step_definitions/nearest.rb          |   51 +
 features/step_definitions/requests.rb         |   45 +
 features/step_definitions/routability.rb      |   51 +
 features/step_definitions/routing.rb          |  113 +++
 features/step_definitions/timestamp.rb        |    7 +
 features/stress/launch.feature                |   58 ++
 features/support/config.rb                    |   30 +
 features/support/cucumber.rb                  |   76 ++
 features/support/data.rb                      |  271 ++++++
 features/support/env.rb                       |   18 +
 features/support/exceptions.rb                |   49 +
 features/support/file.rb                      |   22 +
 features/support/fuzzy.rb                     |   30 +
 features/support/hash.rb                      |   47 +
 features/support/hooks.rb                     |   20 +
 features/support/launch.rb                    |   83 ++
 features/support/log.rb                       |   67 ++
 features/support/nearest.rb                   |   17 +
 features/support/osm_parser.rb                |   23 +
 features/support/osmlib.rb                    |   14 +
 features/support/route.rb                     |  135 +++
 features/support/shortcuts.rb                 |    3 +
 features/testbot/bad.feature                  |   86 ++
 features/testbot/basic.feature                |  272 ++++++
 features/testbot/bearing.feature              |  141 +++
 features/testbot/bearing_param.feature        |   93 ++
 features/testbot/bug.feature                  |   23 +
 features/testbot/distance.feature             |  228 +++++
 features/testbot/duration.feature             |   42 +
 features/testbot/example.feature              |   38 +
 features/testbot/fastest.feature              |   38 +
 features/testbot/ferry.feature                |  175 ++++
 features/testbot/graph.feature                |   22 +
 features/testbot/impedance.feature            |   96 ++
 features/testbot/maxspeed.feature             |   52 +
 features/testbot/mode.feature                 |   26 +
 features/testbot/opposite.feature             |   18 +
 features/testbot/origin.feature               |   75 ++
 features/testbot/penalty.feature              |  168 ++++
 features/testbot/planetary.feature            |   86 ++
 features/testbot/routes.feature               |   35 +
 features/testbot/snap.feature                 |  154 +++
 features/testbot/time.feature                 |  215 +++++
 features/testbot/turns.feature                |  123 +++
 features/testbot/utf.feature                  |   21 +
 features/testbot/via.feature                  |   52 +
 features/timestamp/timestamp.feature          |   12 +
 profiles/bicycle.lua                          |  353 +++++++
 profiles/car.lua                              |  219 +++++
 profiles/foot.lua                             |  193 ++++
 profiles/lib/access.lua                       |   13 +
 profiles/testbot.lua                          |  107 +++
 profiles/turnbot.lua                          |    8 +
 routed.cpp                                    |  159 ++++
 server.ini                                    |   11 +
 test/.gitignore                               |    3 +
 test/.stxxl                                   |    1 +
 test/contractor.ini                           |    1 +
 test/extractor.ini                            |    1 +
 typedefs.h                                    |   68 ++
 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 +
 223 files changed, 27056 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2e6107a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,82 @@
+# Compiled source #
+###################
+*.com
+*.class
+*.dll
+*.exe
+*.o
+*.so
+
+# Packages #
+############
+# it's better to unpack these files and commit the raw source
+# git has its own built in compression methods
+*.7z
+*.dmg
+*.gz
+*.iso
+*.jar
+*.rar
+*.tar
+*.zip
+
+# Logs and databases #
+######################
+*.log
+*.sql
+*.sqlite
+
+# OS generated files #
+######################
+.DS_Store
+ehthumbs.db
+Icon?
+Thumbs.db
+
+# build related files #
+#######################
+/build/
+
+# Eclipse related files #
+#########################
+.setting*
+.scb
+.cproject
+.project
+
+# stxxl related files #
+#######################
+.stxxl
+stxxl.log
+stxxl.errlog
+
+# compiled protobuffers #
+#########################
+/DataStructures/pbf-proto/*.pb.h
+/DataStructures/pbf-proto/*.pb.cc
+
+# External Libs #
+#################
+/lib/
+/win/lib
+
+# Visual Studio Temp + build Files #
+####################################
+/win/*.user
+/win/*.ncb
+/win/*.suo
+/win/Debug/
+/win/Release/
+/win/bin/
+/win/bin-debug/
+/osrm-extract
+/osrm-routed
+/osrm-prepare
+/nohup.out
+
+# Sandbox folder #
+###################
+/sandbox/
+
+/test/profile.lua
+/profile.lua
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..e69de29
diff --git a/AUTHORS.TXT b/AUTHORS.TXT
new file mode 100644
index 0000000..8268ebd
--- /dev/null
+++ b/AUTHORS.TXT
@@ -0,0 +1,11 @@
+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/Bresenham.h b/Algorithms/Bresenham.h
new file mode 100644
index 0000000..a4f7e61
--- /dev/null
+++ b/Algorithms/Bresenham.h
@@ -0,0 +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.
+
+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
new file mode 100644
index 0000000..d2f821c
--- /dev/null
+++ b/Algorithms/CRC32.cpp
@@ -0,0 +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.
+
+ 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
new file mode 100644
index 0000000..6321030
--- /dev/null
+++ b/Algorithms/CRC32.h
@@ -0,0 +1,45 @@
+/*
+ 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.h b/Algorithms/DouglasPeucker.h
new file mode 100644
index 0000000..47b0ce9
--- /dev/null
+++ b/Algorithms/DouglasPeucker.h
@@ -0,0 +1,129 @@
+/*
+    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 DOUGLASPEUCKER_H_
+#define DOUGLASPEUCKER_H_
+
+#include <cassert>
+#include <cmath>
+#include <cfloat>
+#include <stack>
+
+#include "../DataStructures/Coordinate.h"
+
+/*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.
+ * 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;
+    }
+
+
+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);
+
+                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;
+
+            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) );
+            }
+        }
+    }
+};
+
+#endif /* DOUGLASPEUCKER_H_ */
diff --git a/Algorithms/IteratorBasedCRC32.h b/Algorithms/IteratorBasedCRC32.h
new file mode 100644
index 0000000..5d4415c
--- /dev/null
+++ b/Algorithms/IteratorBasedCRC32.h
@@ -0,0 +1,109 @@
+/*
+    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 ITERATORBASEDCRC32_H_
+#define ITERATORBASEDCRC32_H_
+
+#include <boost/crc.hpp>  // for boost::crc_32_type
+#include <iostream>
+
+template<class ContainerT>
+class IteratorbasedCRC32 {
+private:
+    typedef typename ContainerT::iterator ContainerT_iterator;
+    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();
+    }
+    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)
+            );
+            ++p;
+        }
+
+        str=(char*)p;
+        while (r--) {
+            __asm__ __volatile__(
+                    ".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
+                    :"=S"(crc)
+                     :"0"(crc), "c"(*str)
+            );
+            ++str;
+        }
+        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));
+        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;
+        }
+    }
+    CRC32CFunctionPtr crcFunction;
+public:
+    IteratorbasedCRC32(): crc(0) {
+        crcFunction = detectBestCRC32C();
+    }
+
+    virtual ~IteratorbasedCRC32() {};
+
+    unsigned operator()( ContainerT_iterator iter, const ContainerT_iterator end) {
+        unsigned crc = 0;
+        while(iter != end) {
+            char * data = reinterpret_cast<char*>(&(*iter) );
+            crc =((*this).*(crcFunction))(data, sizeof(typename ContainerT::value_type*), crc);
+            ++iter;
+        }
+        return crc;
+    }
+};
+
+#endif /* ITERATORBASEDCRC32_H_ */
diff --git a/Algorithms/ObjectToBase64.h b/Algorithms/ObjectToBase64.h
new file mode 100644
index 0000000..8d69c0a
--- /dev/null
+++ b/Algorithms/ObjectToBase64.h
@@ -0,0 +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.
+
+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 OBJECTTOBASE64_H_
+#define OBJECTTOBASE64_H_
+
+#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"
+
+typedef
+        boost::archive::iterators::base64_from_binary<
+        boost::archive::iterators::transform_width<std::string::const_iterator, 6, 8>
+> base64_t;
+
+typedef
+        boost::archive::iterators::transform_width<
+        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 "_"
+    replaceAll(encoded, "+", "-");
+    replaceAll(encoded, "/", "_");
+}
+
+template<class ToEncodeT>
+static void DecodeObjectFromBase64(ToEncodeT & object, const std::string& _encoded) {
+    try {
+    	std::string encoded(_encoded);
+        //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(...) {}
+}
+
+#endif /* OBJECTTOBASE64_H_ */
diff --git a/Algorithms/PolylineCompressor.h b/Algorithms/PolylineCompressor.h
new file mode 100644
index 0000000..7bb143b
--- /dev/null
+++ b/Algorithms/PolylineCompressor.h
@@ -0,0 +1,134 @@
+/*
+    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 POLYLINECOMPRESSOR_H_
+#define POLYLINECOMPRESSOR_H_
+
+#include <string>
+
+//#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);
+		}
+	}
+
+	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;
+		}
+
+		numberToEncode += 63;
+		output += (static_cast<char> (numberToEncode));
+		if(92 == numberToEncode)
+			output += (static_cast<char> (numberToEncode));
+	}
+
+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 += "\"";
+
+    }
+
+	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 += "\"";
+	}
+
+    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 += "]";
+    }
+
+    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 += "]";
+    }
+};
+
+#endif /* POLYLINECOMPRESSOR_H_ */
diff --git a/Algorithms/StronglyConnectedComponents.h b/Algorithms/StronglyConnectedComponents.h
new file mode 100644
index 0000000..a831100
--- /dev/null
+++ b/Algorithms/StronglyConnectedComponents.h
@@ -0,0 +1,373 @@
+/*
+    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 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 "../DataStructures/DeallocatingVector.h"
+#include "../DataStructures/DynamicGraph.h"
+#include "../DataStructures/ImportEdge.h"
+#include "../DataStructures/NodeCoords.h"
+#include "../DataStructures/Percent.h"
+#include "../DataStructures/Restriction.h"
+#include "../DataStructures/TurnInstructions.h"
+
+// Strongly connected components using Tarjan's Algorithm
+
+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;
+    };
+
+    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;
+
+    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;
+
+
+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;
+
+    struct TarjanNode {
+        TarjanNode() : index(UINT_MAX), lowlink(UINT_MAX), onStack(false) {}
+        unsigned index;
+        unsigned lowlink;
+        bool onStack;
+    };
+
+    struct TarjanStackFrame {
+        explicit TarjanStackFrame(NodeID _v, NodeID p) : v(_v), parent(p) {}
+        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);
+            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();
+                }
+            }
+
+            _restrictionBucketVector.at(index).push_back(std::make_pair(restriction.toNode, restriction.flags.isOnly));
+        }
+
+        BOOST_FOREACH(NodeID id, bn) {
+            _barrierNodes[id] = true;
+        }
+        BOOST_FOREACH(NodeID id, tl) {
+            _trafficLights[id] = true;
+        }
+
+        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)
+                continue;
+
+            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();
+            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 );
+            }
+        }
+        std::vector<NodeBasedEdge>().swap(inputEdges);
+        std::sort( edges.begin(), edges.end() );
+        _nodeBasedGraph = boost::make_shared<_NodeBasedDynamicGraph>( nodes, edges );
+    }
+
+    void Run() {
+        Percent p(_nodeBasedGraph->GetNumberOfNodes());
+
+        const char *pszDriverName = "ESRI Shapefile";
+        OGRSFDriver *poDriver;
+
+        OGRRegisterAll();
+
+        poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(
+                pszDriverName );
+        if( poDriver == NULL )
+        {
+            printf( "%s driver not available.\n", pszDriverName );
+            exit( 1 );
+        }
+        OGRDataSource *poDS;
+
+        poDS = poDriver->CreateDataSource( "component.shp", NULL );
+        if( poDS == NULL ) {
+            printf( "Creation of output file failed.\n" );
+            exit( 1 );
+        }
+
+        OGRLayer *poLayer;
+
+        poLayer = poDS->CreateLayer( "component", NULL, wkbLineString, NULL );
+        if( poLayer == NULL ) {
+            printf( "Layer creation failed.\n" );
+            exit( 1 );
+        }
+
+
+        //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;
+        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)) );
+            }
+
+            while(!recursionStack.empty()) {
+                bool beforeRecursion = recursionStack.top().first;
+                TarjanStackFrame currentFrame = recursionStack.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;
+                    ++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");
+                            }
+                        }
+                    }
+                } 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) {
+                        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;
+                    }
+                }
+            }
+        }
+
+        INFO("identified: " << vectorOfComponentSizes.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");
+
+        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);
+
+                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. << ")");
+                        OGRLineString lineString;
+                        lineString.addPoint(inputNodeInfoList[u].lon/100000., inputNodeInfoList[u].lat/100000.);
+                        lineString.addPoint(inputNodeInfoList[v].lon/100000., inputNodeInfoList[v].lat/100000.);
+
+                        OGRFeature *poFeature;
+                        poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() );
+                        poFeature->SetGeometry( &lineString );
+                        if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE )
+                        {
+                            ERR( "Failed to create feature in shapefile.\n" );
+                        }
+                        OGRFeature::DestroyFeature( poFeature );
+                    }
+                }
+            }
+        }
+        OGRDataSource::DestroyDataSource( poDS );
+        std::vector<NodeID>().swap(vectorOfComponentSizes);
+        std::vector<NodeID>().swap(componentsIndex);
+
+    }
+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;
+                }
+            }
+        }
+        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)
+                    return true;
+            }
+        }
+        return false;
+    }
+};
+
+#endif /* STRONGLYCONNECTEDCOMPONENTS_H_ */
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..3de4c4f
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,111 @@
+cmake_minimum_required(VERSION 2.6)
+project(OSRM)
+include(FindPackageHandleStandardArgs)
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
+set(BOOST_COMPONENTS filesystem regex system thread)
+
+file(GLOB ExtractorGlob Extractor/*.cpp)
+set(ExtractorSources extractor.cpp ${ExtractorGlob})
+add_executable(osrm-extract ${ExtractorSources})
+
+file(GLOB PrepareGlob Contractor/*.cpp)
+set(PrepareSources createHierarchy.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)
+
+# Check the release mode
+if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
+	set(CMAKE_BUILD_TYPE Release)
+endif(NOT CMAKE_BUILD_TYPE MATCHES Debug) 
+if(CMAKE_BUILD_TYPE MATCHES Debug)
+    message(STATUS "Configuring OSRM in debug mode")
+endif(CMAKE_BUILD_TYPE MATCHES Debug) 
+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++
+endif()
+
+if(APPLE)
+	SET(CMAKE_OSX_ARCHITECTURES "x86_64")
+	message("Set Architecture to x64 on OS X")
+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)
+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})
+
+find_package( Threads REQUIRED )
+target_link_libraries (osrm-extract ${Threads_LIBRARY})
+
+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( LibXml2 REQUIRED )
+include_directories(${LIBXML2_INCLUDE_DIR})
+target_link_libraries (osrm-extract ${LIBXML2_LIBRARIES})
+
+find_package( Luabind REQUIRED )
+include_directories(${LUABIND_INCLUDE_DIR})
+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})
+
+find_package( STXXL REQUIRED )
+include_directories(${STXXL_INCLUDE_DIR})
+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})
+
+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)
diff --git a/Contractor/ContractionCleanup.h b/Contractor/ContractionCleanup.h
new file mode 100644
index 0000000..e42dad3
--- /dev/null
+++ b/Contractor/ContractionCleanup.h
@@ -0,0 +1,261 @@
+/*
+    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
new file mode 100644
index 0000000..35d2aa2
--- /dev/null
+++ b/Contractor/Contractor.h
@@ -0,0 +1,783 @@
+/*
+    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 CONTRACTOR_H_INCLUDED
+#define CONTRACTOR_H_INCLUDED
+
+#include "TemporaryStorage.h"
+#include "../DataStructures/BinaryHeap.h"
+#include "../DataStructures/DeallocatingVector.h"
+#include "../DataStructures/DynamicGraph.h"
+#include "../DataStructures/Percent.h"
+#include "../DataStructures/XORFastHash.h"
+#include "../DataStructures/XORFastHashStorage.h"
+#include "../Util/OpenMPWrapper.h"
+#include "../Util/StringUtil.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 <algorithm>
+#include <limits>
+#include <vector>
+
+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) {}
+        unsigned distance;
+        unsigned id;
+        unsigned originalEdges:28;
+        bool shortcut:1;
+        bool forward:1;
+        bool backward:1;
+        bool originalViaNodeID:1;
+    } data;
+
+    struct _HeapData {
+        short hop;
+        bool target;
+        _HeapData() : hop(0), target(false) {}
+        _HeapData( 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 ) { }
+    };
+
+    struct _PriorityData {
+        int depth;
+        _PriorityData() : depth(0) { }
+    };
+
+    struct _ContractionInformation {
+        int edgesDeleted;
+        int edgesAdded;
+        int originalEdgesDeleted;
+        int originalEdgesAdded;
+        _ContractionInformation() : edgesDeleted(0), edgesAdded(0), originalEdgesDeleted(0), originalEdgesAdded(0) {}
+    };
+
+    struct _RemainingNodeData {
+        _RemainingNodeData() : id (0), isIndependent(false) {}
+        NodeID id:31;
+        bool isIndependent:1;
+    };
+
+    struct _NodePartitionor {
+        inline bool operator()(_RemainingNodeData & nodeData ) const {
+            return !nodeData.isIndependent;
+        }
+    };
+
+public:
+
+    template<class ContainerT >
+    Contractor( int nodes, ContainerT& inputEdges) {
+        std::vector< _ContractorEdge > edges;
+        edges.reserve(inputEdges.size()*2);
+
+        typename ContainerT::deallocation_iterator diter = inputEdges.dbegin();
+        typename ContainerT::deallocation_iterator dend  = inputEdges.dend();
+
+        _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());
+
+            BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" );
+#ifndef NDEBUG
+            if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
+                WARN("Edge weight large -> " << newEdge.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 );
+            ++diter;
+        }
+        //clear input vector and trim the current set of edges with the well-known swap trick
+        inputEdges.clear();
+        sort( edges.begin(), edges.end() );
+        NodeID edge = 0;
+        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 ) {
+                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 );
+                }
+                if ( edges[i].data.backward) {
+                    backwardEdge.data.distance = std::min( edges[i].data.distance, backwardEdge.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;
+                }
+            } else { //insert seperate edges
+                if ( ((int)forwardEdge.data.distance) != std::numeric_limits< int >::max() ) {
+                    edges[edge++] = forwardEdge;
+                }
+                if ( (int)backwardEdge.data.distance != std::numeric_limits< int >::max() ) {
+                    edges[edge++] = backwardEdge;
+                }
+            }
+        }
+        std::cout << "merged " << edges.size() - edge << " edges out of " << edges.size() << std::endl;
+        edges.resize( edge );
+        _graph = boost::make_shared<_DynamicGraph>( nodes, edges );
+        edges.clear();
+        std::vector<_ContractorEdge>().swap(edges);
+        //        unsigned maxdegree = 0;
+        //        NodeID highestNode = 0;
+        //
+        //        for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
+        //            unsigned degree = _graph->EndEdges(i) - _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);
+        //        }
+
+        //Create temporary file
+
+        //        GetTemporaryFileName(temporaryEdgeStorageFilename);
+        temporaryStorageSlotID = TemporaryStorage::GetInstance().allocateSlot();
+        std::cout << "contractor finished initalization" << std::endl;
+    }
+
+    ~Contractor() {
+        //Delete temporary file
+        //        remove(temporaryEdgeStorageFilename.c_str());
+        TemporaryStorage::GetInstance().deallocateSlot(temporaryStorageSlotID);
+    }
+
+    void Run() {
+        const NodeID numberOfNodes = _graph->GetNumberOfNodes();
+        Percent p (numberOfNodes);
+
+        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;
+
+        NodeID numberOfContractedNodes = 0;
+        std::vector< _RemainingNodeData > remainingNodes( numberOfNodes );
+        std::vector< float > nodePriority( numberOfNodes );
+        std::vector< _PriorityData > nodeData( numberOfNodes );
+
+        //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 );
+            }
+        }
+        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;
+                }
+                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);
+                        }
+                    }
+                }
+                //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() ) );
+                }
+            }
+
+            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 );
+                }
+            }
+            _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;
+                }
+
+                std::sort( data->insertedEdges.begin(), data->insertedEdges.end() );
+            }
+#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;
+                    _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);
+                            continue;
+                        }
+                    }
+                    _graph->InsertEdge( edge.source, edge.target, edge.data );
+                }
+                data.insertedEdges.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 );
+                }
+            }
+            //remove contracted nodes from the pool
+            numberOfContractedNodes += last - firstIndependent;
+            remainingNodes.resize( firstIndependent );
+            std::vector< _RemainingNodeData>( remainingNodes ).swap( remainingNodes );
+            //            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);
+            //                if(degree > maxdegree)
+            //                    maxdegree = degree;
+            //                if(degree < mindegree)
+            //                    mindegree = degree;
+            //
+            //                avgdegree += degree;
+            //                quaddegree += (degree*degree);
+            //            }
+            //
+            //            avgdegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
+            //            quaddegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
+            //
+            //            INFO("rest: " << remainingNodes.size() << ", max: " << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ", quad: " << quaddegree);
+
+            p.printStatus(numberOfContractedNodes);
+        }
+        BOOST_FOREACH(_ThreadData * data, threadData)
+        	delete data;
+        threadData.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 ) {
+                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;
+                    }
+                    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(
+                        newEdge.data.id <= INT_MAX, //2^31
+                        "edge id invalid"
+                    );
+                    newEdge.data.forward = data.forward;
+                    newEdge.data.backward = data.backward;
+                    edges.push_back( newEdge );
+                }
+            }
+        }
+        _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;
+        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 );
+        }
+        tempStorage.deallocateSlot(temporaryStorageSlotID);
+    }
+
+private:
+    inline void _Dijkstra( const int maxDistance, const unsigned numTargets, const int maxNodes, _ThreadData* const data, const NodeID middleNode ){
+
+        _Heap& heap = data->heap;
+
+        int nodes = 0;
+        unsigned targetsFound = 0;
+        while ( heap.Size() > 0 ) {
+            const NodeID node = heap.DeleteMin();
+            const int distance = heap.GetKey( node );
+            const short currentHop = heap.GetData( node ).hop+1;
+
+            if ( ++nodes > maxNodes )
+                return;
+            //Destination settled?
+            if ( distance > maxDistance )
+                return;
+
+            if ( heap.GetData( node ).target ) {
+                ++targetsFound;
+                if ( targetsFound >= numTargets ) {
+                    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 ){
+                    continue;
+                }
+                const NodeID to = _graph->GetTarget( edge );
+                if(middleNode == to) {
+                    continue;
+                }
+                const int toDistance = distance + data.distance;
+
+                //New Node discovered -> Add to Heap + Node Info Storage
+                if ( !heap.WasInserted( to ) ) {
+                    heap.Insert( to, toDistance, _HeapData(currentHop, false) );
+                }
+                //Found a shorter Path -> Update distance
+                else if ( toDistance < heap.GetKey( to ) ) {
+                    heap.DecreaseKey( to, toDistance );
+                    heap.GetData( to ).hop = currentHop;
+                }
+            }
+        }
+    }
+
+    inline float _Evaluate( _ThreadData* const data, _PriorityData* const nodeData, const NodeID node){
+        _ContractionInformation stats;
+
+        //perform simulated contraction
+        _Contract< true> ( data, node, &stats );
+
+        // Result will contain the priority
+        float result;
+        if ( 0 == (stats.edgesDeleted*stats.originalEdgesDeleted) )
+            result = 1 * nodeData->depth;
+        else
+            result =  2 * ((( float ) stats.edgesAdded ) / stats.edgesDeleted ) + 4 * ((( float ) stats.originalEdgesAdded ) / stats.originalEdgesDeleted ) + 1 * nodeData->depth;
+        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;
+            }
+            if ( !inData.backward )
+                continue;
+
+            heap.Clear();
+            heap.Insert( source, 0, _HeapData() );
+            int maxDistance = 0;
+            unsigned numTargets = 0;
+
+            for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
+                const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
+                if ( !outData.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;
+                }
+            }
+
+            if( Simulate ) {
+                _Dijkstra( maxDistance, numTargets, 1000, data, node );
+            } else {
+                _Dijkstra( maxDistance, numTargets, 2000, 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 ) {
+                    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 );
+                    }
+                }
+            }
+        }
+        if ( !Simulate ) {
+            for ( int i = insertedEdgesSize, iend = insertedEdges.size(); i < iend; ++i ) {
+                bool found = false;
+                for ( int other = i + 1 ; other < iend ; ++other ) {
+                    if ( insertedEdges[other].source != insertedEdges[i].source )
+                        continue;
+                    if ( insertedEdges[other].target != insertedEdges[i].target )
+                        continue;
+                    if ( insertedEdges[other].data.distance != insertedEdges[i].data.distance )
+                        continue;
+                    if ( insertedEdges[other].data.shortcut != insertedEdges[i].data.shortcut )
+                        continue;
+                    insertedEdges[other].data.forward |= insertedEdges[i].data.forward;
+                    insertedEdges[other].data.backward |= insertedEdges[i].data.backward;
+                    found = true;
+                    break;
+                }
+                if ( !found ) {
+                    insertedEdges[insertedEdgesSize++] = insertedEdges[i];
+                }
+            }
+            insertedEdges.resize( insertedEdgesSize );
+        }
+        return true;
+    }
+
+    inline void _DeleteIncomingEdges( _ThreadData* 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 );
+        }
+        //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 );
+        }
+    }
+
+    inline bool _UpdateNeighbours( std::vector< float > & priorities, std::vector< _PriorityData > & nodeData, _ThreadData* 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 )
+                continue;
+            neighbours.push_back( u );
+            nodeData[u].depth = (std::max)(nodeData[node].depth + 1, nodeData[u].depth );
+        }
+        //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 );
+        }
+        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];
+
+        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)
+                continue;
+            const double targetPriority = priorities[target];
+            assert( targetPriority >= 0 );
+            //found a neighbour with lower priority?
+            if ( priority > targetPriority )
+                return false;
+            //tie breaking
+            if ( fabs(priority - targetPriority) < FLT_EPSILON && bias(node, target) ) {
+                return false;
+            }
+            neighbours.push_back( target );
+        }
+
+        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)
+                    continue;
+
+                const double targetPriority = priorities[target];
+                assert( targetPriority >= 0 );
+                //found a neighbour with lower priority?
+                if ( priority > targetPriority)
+                    return false;
+                //tie breaking
+                if ( fabs(priority - targetPriority) < FLT_EPSILON && bias(node, target) ) {
+                    return false;
+                }
+            }
+        }
+        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 = fastHash(a);
+        unsigned short hashb = fastHash(b);
+
+        //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;
+};
+
+#endif // CONTRACTOR_H_INCLUDED
diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp
new file mode 100644
index 0000000..13f49ec
--- /dev/null
+++ b/Contractor/EdgeBasedGraphFactory.cpp
@@ -0,0 +1,412 @@
+/*
+ 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 "EdgeBasedGraphFactory.h"
+
+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();
+            }
+        }
+
+        _restrictionBucketVector.at(index).push_back(std::make_pair(restriction.toNode, restriction.flags.isOnly));
+    }
+
+	_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(edge.source == edge.target) {
+        	continue;
+        }
+        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 );
+        }
+    }
+    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::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);
+}
+
+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;
+            }
+        }
+    }
+    return UINT_MAX;
+}
+
+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;
+        }
+    }
+    return false;
+}
+
+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);
+}
+
+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();
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            //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) );
+            }
+        }
+    }
+
+    std::vector<NodeID>().swap(vectorOfComponentSizes);
+    std::vector<NodeID>().swap(componentsIndex);
+
+    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;
+                    continue;
+                }
+
+                if(u == w && 1 != _nodeBasedGraph->GetOutDegree(v) ) {
+                    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;
+                    }
+                }
+            }
+        }
+        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");
+}
+
+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]);
+
+    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
+        }
+    } else {
+        penalty = 0;
+    }
+
+    if(u == w) {
+        return TurnInstructions.UTurn;
+    }
+
+    _NodeBasedDynamicGraph::EdgeIterator edge1 = _nodeBasedGraph->FindEdge(u, v);
+    _NodeBasedDynamicGraph::EdgeIterator edge2 = _nodeBasedGraph->FindEdge(v, w);
+
+    _NodeBasedDynamicGraph::EdgeData & data1 = _nodeBasedGraph->GetEdgeData(edge1);
+    _NodeBasedDynamicGraph::EdgeData & data2 = _nodeBasedGraph->GetEdgeData(edge2);
+
+    if(!data1.contraFlow && data2.contraFlow) {
+    	return TurnInstructions.EnterAgainstAllowedDirection;
+    }
+    if(data1.contraFlow && !data2.contraFlow) {
+    	return TurnInstructions.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;
+        }
+        return TurnInstructions.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;
+        }
+        //We are leaving the roundabout
+        if(data1.roundabout && (!data2.roundabout) ) {
+            return TurnInstructions.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;
+    }
+
+    return TurnInstructions.GetTurnDirectionOfInstruction(angle);
+}
+
+unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const {
+    return _nodeBasedGraph->GetNumberOfEdges();
+}
+
+/* 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;
+}
diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h
new file mode 100644
index 0000000..c51e4d2
--- /dev/null
+++ b/Contractor/EdgeBasedGraphFactory.h
@@ -0,0 +1,162 @@
+/*
+ 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.
+ */
+
+/*
+ * This class constructs the edge base representation of a graph from a given node based edge list
+ */
+
+#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/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 <algorithm>
+#include <queue>
+#include <vector>
+
+class EdgeBasedGraphFactory : boost::noncopyable {
+public:
+    struct EdgeBasedNode {
+        bool operator<(const EdgeBasedNode & other) const {
+            return other.id < id;
+        }
+
+        bool operator==(const EdgeBasedNode & other) const {
+            return id == other.id;
+        }
+
+        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;
+        }
+
+        inline bool isIgnored() const {
+            return ignoreInGrid;
+        }
+        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;
+};
+
+#endif /* EDGEBASEDGRAPHFACTORY_H_ */
diff --git a/Contractor/TemporaryStorage.cpp b/Contractor/TemporaryStorage.cpp
new file mode 100644
index 0000000..7c894b0
--- /dev/null
+++ b/Contractor/TemporaryStorage.cpp
@@ -0,0 +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.
+
+ 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 <boost/foreach.hpp>
+
+#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());
+    }
+}
+
+TemporaryStorage & TemporaryStorage::GetInstance(){
+    static TemporaryStorage runningInstance;
+    return runningInstance;
+}
+
+TemporaryStorage::~TemporaryStorage() {
+    removeAll();
+}
+
+void TemporaryStorage::removeAll() {
+    boost::mutex::scoped_lock lock(mutex);
+    try {
+        for(unsigned slotID = 0; slotID < vectorOfStreamDatas.size(); ++slotID)
+            deallocateSlot(slotID);
+
+    } catch(boost::filesystem::filesystem_error & e) {
+        ERR("could not retrieve location of temporary path: " << e.what());
+    }
+    vectorOfStreamDatas.clear();
+}
+
+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;
+}
+
+void TemporaryStorage::deallocateSlot(int slotID) {
+    try {
+        StreamData & data = vectorOfStreamDatas[slotID];
+        boost::mutex::scoped_lock lock(*data.readWriteMutex);
+                if(!boost::filesystem::exists(data.pathToTemporaryFile)) {
+            return;
+        }
+        if(data.streamToTemporaryFile->is_open())
+            data.streamToTemporaryFile->close();
+
+        //INFO("deallocating slot " << slotID << " and its file: " << data.pathToTemporaryFile);
+        boost::filesystem::remove(data.pathToTemporaryFile);
+    } catch(boost::filesystem::filesystem_error & e) {
+        abort(e);
+    }
+}
+
+void TemporaryStorage::writeToSlot(int slotID, char * pointer, std::streamsize size) {
+    try {
+        StreamData & data = vectorOfStreamDatas[slotID];
+        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);
+    }
+}
+void TemporaryStorage::readFromSlot(int slotID, char * pointer, std::streamsize size) {
+    try {
+        StreamData & data = vectorOfStreamDatas[slotID];
+        boost::mutex::scoped_lock lock(*data.readWriteMutex);
+        if(data.writeMode) {
+            data.writeMode = false;
+            data.streamToTemporaryFile->seekg(0, data.streamToTemporaryFile->beg);
+        }
+        data.streamToTemporaryFile->read(pointer, size);
+    } catch(boost::filesystem::filesystem_error & e) {
+        abort(e);
+    }
+}
+
+unsigned TemporaryStorage::getFreeBytesOnTemporaryDevice() {
+    boost::filesystem::space_info tempSpaceInfo;
+    try {
+        tempSpaceInfo = boost::filesystem::space(tempDirectory);
+    } catch(boost::filesystem::filesystem_error & e) {
+        abort(e);
+    }
+    return tempSpaceInfo.available;
+}
+
+boost::filesystem::fstream::pos_type TemporaryStorage::tell(int slotID) {
+    boost::filesystem::fstream::pos_type position;
+    try {
+        StreamData & data = vectorOfStreamDatas[slotID];
+        boost::mutex::scoped_lock lock(*data.readWriteMutex);
+        position = data.streamToTemporaryFile->tellp();
+    } catch(boost::filesystem::filesystem_error & e) {
+        abort(e);
+   }
+//    INFO("telling position: " << position);
+    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);
+    }
+}
diff --git a/Contractor/TemporaryStorage.h b/Contractor/TemporaryStorage.h
new file mode 100644
index 0000000..e189981
--- /dev/null
+++ b/Contractor/TemporaryStorage.h
@@ -0,0 +1,113 @@
+/*
+ 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 TEMPORARYSTORAGE_H_
+#define TEMPORARYSTORAGE_H_
+
+#include <vector>
+#include <fstream>
+
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/mutex.hpp>
+
+#include "../typedefs.h"
+
+//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;
+static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%");
+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:
+    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;
+    boost::mutex mutex;
+};
+
+#endif /* TEMPORARYSTORAGE_H_ */
diff --git a/DataStructures/BinaryHeap.h b/DataStructures/BinaryHeap.h
new file mode 100644
index 0000000..f8b3470
--- /dev/null
+++ b/DataStructures/BinaryHeap.h
@@ -0,0 +1,267 @@
+/*
+    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 BINARYHEAP_H_INCLUDED
+#define BINARYHEAP_H_INCLUDED
+
+//Not compatible with non contiguous node ids
+
+#include <cassert>
+#include <limits>
+#include <vector>
+#include <algorithm>
+#include <map>
+#include <boost/unordered_map.hpp>
+
+template< typename NodeID, typename Key >
+class ArrayStorage {
+public:
+
+    ArrayStorage( size_t size ) : positions( new Key[size] ) {
+        memset(positions, 0, size*sizeof(Key));
+    }
+
+    ~ArrayStorage() {
+        delete[] positions;
+    }
+
+    Key &operator[]( NodeID node ) {
+        return positions[node];
+    }
+
+    void Clear() {}
+
+private:
+    Key* positions;
+};
+
+template< typename NodeID, typename Key >
+class MapStorage {
+public:
+
+    MapStorage( size_t ) {}
+
+    Key &operator[]( NodeID node ) {
+        return nodes[node];
+    }
+
+    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);
+	}
+
+    Key &operator[]( const NodeID node ) {
+    	return nodes[node];
+    }
+
+    void Clear() {
+        nodes.clear();
+    }
+
+private:
+    boost::unordered_map< NodeID, Key > nodes;
+};
+
+template<typename NodeID = unsigned>
+struct _SimpleHeapData {
+    NodeID parent;
+    _SimpleHeapData( NodeID p ) : parent(p) { }
+};
+
+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();
+    }
+
+    void Clear() {
+        heap.resize( 1 );
+        insertedNodes.clear();
+        heap[0].weight = std::numeric_limits< Weight >::min();
+        nodeIndex.Clear();
+    }
+
+    Key Size() const {
+        return static_cast<Key>( heap.size() - 1 );
+    }
+
+    void Insert( NodeID node, Weight weight, const Data &data ) {
+        HeapElement element;
+        element.index = static_cast<NodeID>(insertedNodes.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 );
+        CheckHeap();
+    }
+
+    Data& GetData( NodeID node ) {
+        const Key index = nodeIndex[node];
+        return insertedNodes[index].data;
+    }
+
+    Weight& GetKey( NodeID node ) {
+        const Key index = nodeIndex[node];
+        return insertedNodes[index].weight;
+    }
+
+    bool WasRemoved( NodeID node ) {
+        assert( WasInserted( node ) );
+        const Key index = nodeIndex[node];
+        return insertedNodes[index].key == 0;
+    }
+
+    bool WasInserted( NodeID node ) {
+        const Key index = nodeIndex[node];
+        if ( index >= static_cast<Key> (insertedNodes.size()) )
+            return false;
+        return insertedNodes[index].node == node;
+    }
+
+    NodeID Min() const {
+        assert( heap.size() > 1 );
+        return insertedNodes[heap[1].index].node;
+    }
+
+    NodeID DeleteMin() {
+        assert( heap.size() > 1 );
+        const Key removedIndex = heap[1].index;
+        heap[1] = heap[heap.size()-1];
+        heap.pop_back();
+        if ( heap.size() > 1 )
+            Downheap( 1 );
+        insertedNodes[removedIndex].key = 0;
+        CheckHeap();
+        return insertedNodes[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 DecreaseKey( NodeID node, Weight weight ) {
+        assert( UINT_MAX != node );
+        const Key index = nodeIndex[node];
+        Key key = insertedNodes[index].key;
+        assert ( key >= 0 );
+
+        insertedNodes[index].weight = weight;
+        heap[key].weight = weight;
+        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 ) {
+        }
+
+        NodeID node;
+        Key key;
+        Weight weight;
+        Data data;
+    };
+    struct HeapElement {
+        Key index;
+        Weight weight;
+    };
+
+    std::vector< HeapNode > insertedNodes;
+    std::vector< HeapElement > heap;
+    IndexStorage nodeIndex;
+
+    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() ) ) {
+            const Key nextKeyOther = nextKey + 1;
+            if ( ( nextKeyOther < static_cast<Key> ( heap.size() ) )&& ( heap[nextKey].weight > heap[nextKeyOther].weight) )
+                nextKey = nextKeyOther;
+
+            if ( weight <= heap[nextKey].weight )
+                break;
+
+            heap[key] = heap[nextKey];
+            insertedNodes[heap[key].index].key = key;
+            key = nextKey;
+            nextKey <<= 1;
+        }
+        heap[key].index = droppingIndex;
+        heap[key].weight = weight;
+        insertedNodes[droppingIndex].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 );
+            heap[key] = heap[nextKey];
+            insertedNodes[heap[key].index].key = key;
+            key = nextKey;
+            nextKey >>= 1;
+        }
+        heap[key].index = risingIndex;
+        heap[key].weight = weight;
+        insertedNodes[risingIndex].key = key;
+    }
+
+    void CheckHeap() {
+#ifndef NDEBUG
+        for ( Key i = 2; i < (Key) heap.size(); ++i ) {
+            assert( heap[i].weight >= heap[i >> 1].weight );
+        }
+#endif
+    }
+};
+
+#endif //#ifndef BINARYHEAP_H_INCLUDED
diff --git a/DataStructures/ConcurrentQueue.h b/DataStructures/ConcurrentQueue.h
new file mode 100644
index 0000000..0466ab2
--- /dev/null
+++ b/DataStructures/ConcurrentQueue.h
@@ -0,0 +1,83 @@
+/*
+    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 CONCURRENTQUEUE_H_INCLUDED
+#define CONCURRENTQUEUE_H_INCLUDED
+
+#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;
+
+public:
+    ConcurrentQueue(const size_t max_size) : internal_queue(max_size) { }
+
+    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();
+        m_not_empty.notify_one();
+    }
+
+    inline bool empty() const {
+        return 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();
+        m_not_full.notify_one();
+    }
+
+    inline bool try_pop(Data& popped_value) {
+        boost::mutex::scoped_lock lock(m_mutex);
+        if(internal_queue.empty()) {
+            return false;
+        }
+        popped_value=internal_queue.front();
+        internal_queue.pop_front();
+        lock.unlock();
+        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(); }
+};
+
+#endif //#ifndef CONCURRENTQUEUE_H_INCLUDED
diff --git a/DataStructures/Coordinate.h b/DataStructures/Coordinate.h
new file mode 100644
index 0000000..bc63289
--- /dev/null
+++ b/DataStructures/Coordinate.h
@@ -0,0 +1,108 @@
+/*
+    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
new file mode 100644
index 0000000..89d8e2c
--- /dev/null
+++ b/DataStructures/DeallocatingVector.h
@@ -0,0 +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.
+
+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 DEALLOCATINGVECTOR_H_
+#define DEALLOCATINGVECTOR_H_
+
+#include <cassert>
+#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();
+    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();
+        }
+        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 (mData != other.mData) || (mIndex != other.mIndex) || (mBucketList != other.mBucketList);
+        }
+
+        inline bool operator==(const DeallocatingVectorIteratorState &other) {
+            return (mData == other.mData) && (mIndex == other.mIndex) && (mBucketList == other.mBucketList);
+        }
+
+        inline bool operator<(const DeallocatingVectorIteratorState &other) {
+            return mIndex < other.mIndex;
+        }
+
+        //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;
+
+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>::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) {}
+
+    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) {}
+
+    template<typename T2>
+    DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
+        if(DeallocateC) assert(false);
+        mState = r.mState; return *this;
+    }
+
+    inline DeallocatingVectorIterator& operator++() { //prefix
+//        if(DeallocateC) assert(false);
+        ++mState.mIndex; mState.setPointerForIndex(); return *this;
+    }
+
+    inline DeallocatingVectorIterator& operator--() { //prefix
+        if(DeallocateC) assert(false);
+        --mState.mIndex; mState.setPointerForIndex(); return *this;
+    }
+
+    inline DeallocatingVectorIterator operator++(int) { //postfix
+        DeallocatingVectorIteratorState _myState(mState);
+        mState.mIndex++; mState.setPointerForIndex();
+        return DeallocatingVectorIterator(_myState);
+    }
+    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 {
+        DeallocatingVectorIteratorState _myState(mState);
+        _myState.mIndex+=n; _myState.setPointerForIndex();
+        return DeallocatingVectorIterator(_myState);
+    }
+
+    inline DeallocatingVectorIterator& operator+=(const difference_type& n) const {
+        mState.mIndex+=n; return *this;
+    }
+
+    inline DeallocatingVectorIterator operator-(const difference_type& n) const {
+        if(DeallocateC) assert(false);
+        DeallocatingVectorIteratorState _myState(mState);
+        _myState.mIndex-=n; _myState.setPointerForIndex();
+        return DeallocatingVectorIterator(_myState);
+    }
+
+    inline DeallocatingVectorIterator& operator-=(const difference_type &n) const {
+        if(DeallocateC) assert(false);
+        mState.mIndex-=n; return *this;
+    }
+    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 mState != other.mState;
+    }
+
+    inline bool operator==(const DeallocatingVectorIterator & other) {
+        return mState == other.mState;
+    }
+
+    bool operator<(const DeallocatingVectorIterator & other) {
+        return mState < other.mState;
+    }
+
+    difference_type operator-(const DeallocatingVectorIterator & other) {
+        if(DeallocateC) assert(false);
+        return mState.mIndex-other.mState.mIndex;
+    }
+};
+
+template<typename ElementT, std::size_t bucketSizeC = 8388608/sizeof(ElementT) >
+class DeallocatingVector {
+private:
+    std::size_t mCurrentSize;
+    std::vector<ElementT *> mBucketList;
+
+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.
+    typedef DeallocatingVectorIterator<ElementT, bucketSizeC, true> deallocation_iterator;
+
+    DeallocatingVector() : mCurrentSize(0) {
+        //initial bucket
+        mBucketList.push_back(new ElementT[bucketSizeC]);
+    }
+
+    ~DeallocatingVector() {
+        clear();
+    }
+
+    inline void swap(DeallocatingVector<ElementT, bucketSizeC> & other) {
+        std::swap(mCurrentSize, other.mCurrentSize);
+        mBucketList.swap(other.mBucketList);
+    }
+
+    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;
+            }
+        }
+        //Removing all ptrs from vector
+        std::vector<ElementT *>().swap(mBucketList);
+        mCurrentSize = 0;
+    }
+
+    inline void push_back(const ElementT & element) {
+        std::size_t _capacity = capacity();
+        if(mCurrentSize == _capacity) {
+            mBucketList.push_back(new ElementT[bucketSizeC]);
+        }
+
+        std::size_t _index = size()%bucketSizeC;
+        mBucketList.back()[_index] = element;
+        ++mCurrentSize;
+    }
+
+    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]);
+            }
+            mCurrentSize = new_size;
+        }
+        if(new_size < mCurrentSize) {
+            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];
+            }
+            mBucketList.resize(number_of_necessary_buckets);
+            mCurrentSize = new_size;
+        }
+    }
+
+    inline std::size_t size() const {
+        return mCurrentSize;
+    }
+
+    inline std::size_t capacity() const {
+        return mBucketList.size() * bucketSizeC;
+    }
+
+    inline iterator begin() {
+        return iterator(static_cast<std::size_t>(0), mBucketList);
+    }
+
+    inline iterator end() {
+        return iterator(size(), mBucketList);
+    }
+
+    inline deallocation_iterator dbegin() {
+        return deallocation_iterator(static_cast<std::size_t>(0), mBucketList);
+    }
+
+    inline deallocation_iterator dend() {
+        return deallocation_iterator(size(), mBucketList);
+    }
+
+    inline const_iterator begin() const {
+        return const_iterator(static_cast<std::size_t>(0), mBucketList);
+    }
+
+    inline const_iterator end() const {
+        return const_iterator(size(), mBucketList);
+    }
+
+    inline ElementT & operator[](const std::size_t index) {
+        std::size_t _bucket = index / bucketSizeC;
+        std::size_t _index = index % bucketSizeC;
+        return (mBucketList[_bucket][_index]);
+    }
+
+    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]);
+    }
+
+    inline ElementT & back() {
+        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 = mCurrentSize / bucketSizeC;
+        std::size_t _index = mCurrentSize % bucketSizeC;
+    	return (mBucketList[_bucket][_index]);
+    }
+};
+
+#endif /* DEALLOCATINGVECTOR_H_ */
diff --git a/DataStructures/DynamicGraph.h b/DataStructures/DynamicGraph.h
new file mode 100644
index 0000000..67db065
--- /dev/null
+++ b/DataStructures/DynamicGraph.h
@@ -0,0 +1,233 @@
+/*
+    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 DYNAMICGRAPH_H_INCLUDED
+#define DYNAMICGRAPH_H_INCLUDED
+
+#include "../DataStructures/DeallocatingVector.h"
+
+#include <boost/assert.hpp>
+#include <boost/integer.hpp>
+
+#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 );
+        }
+
+        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;
+                }
+            }
+        }
+
+        ~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 );
+        }
+
+        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 );
+        }
+
+        //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;
+                }
+            }
+            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 );
+                }
+            }
+
+            #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;
+                }
+            }
+            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
+            uint32_t edges;
+        };
+
+        struct Edge {
+            NodeIterator target;
+            EdgeDataT data;
+        };
+
+        NodeIterator m_numNodes;
+        EdgeIterator m_numEdges;
+
+        std::vector< Node > m_nodes;
+        DeallocatingVector< Edge > m_edges;
+};
+
+#endif // DYNAMICGRAPH_H_INCLUDED
diff --git a/DataStructures/GridEdge.h b/DataStructures/GridEdge.h
new file mode 100644
index 0000000..7b2dd78
--- /dev/null
+++ b/DataStructures/GridEdge.h
@@ -0,0 +1,82 @@
+/*
+    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
new file mode 100644
index 0000000..57c2dde
--- /dev/null
+++ b/DataStructures/HashTable.h
@@ -0,0 +1,79 @@
+/*
+    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.
+
+  Created on: 18.11.2010
+  Author: dennis
+ */
+
+#ifndef HASHTABLE_H_
+#define HASHTABLE_H_
+
+#include <boost/unordered_map.hpp>
+
+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;
+    }
+
+    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();
+    }
+
+    inline valueT operator[] (keyT key) const {
+    	if(table.find(key) == table.end())
+    		return valueT();
+    	return table.find(key)->second;
+    }
+    inline unsigned Size() const {
+        return table.size();
+    }
+    MyIterator begin() const {
+        return table.begin();
+    }
+    MyIterator end() const {
+        return table.end();
+    }
+private:
+    MyHashTable table;
+};
+
+#endif /* HASHTABLE_H_ */
diff --git a/DataStructures/HilbertValue.h b/DataStructures/HilbertValue.h
new file mode 100644
index 0000000..05e2bb1
--- /dev/null
+++ b/DataStructures/HilbertValue.h
@@ -0,0 +1,87 @@
+/*
+    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 HILBERTVALUE_H_
+#define HILBERTVALUE_H_
+
+#include <boost/integer.hpp>
+#include <boost/noncopyable.hpp>
+
+// 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);
+
+		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;
+	}
+
+	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;
+		}
+	}
+};
+
+#endif /* HILBERTVALUE_H_ */
diff --git a/DataStructures/ImportEdge.h b/DataStructures/ImportEdge.h
new file mode 100644
index 0000000..714560c
--- /dev/null
+++ b/DataStructures/ImportEdge.h
@@ -0,0 +1,142 @@
+/*
+    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.
+
+};
+
+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;
+};
+
+typedef NodeBasedEdge ImportEdge;
+
+#endif // EDGE_H
diff --git a/DataStructures/ImportNode.h b/DataStructures/ImportNode.h
new file mode 100644
index 0000000..b9c27be
--- /dev/null
+++ b/DataStructures/ImportNode.h
@@ -0,0 +1,54 @@
+/*
+    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 IMPORTNODE_H_
+#define IMPORTNODE_H_
+
+#include "NodeCoords.h"
+#include "../DataStructures/HashTable.h"
+
+
+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) {}
+
+    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 {
+    HashTable<std::string, std::string> keyVals;
+	
+	inline void Clear() {
+		keyVals.EraseAll();
+		lat = 0; lon = 0; id = 0; bollard = false; trafficLight = false;
+	}
+};
+
+#endif /* IMPORTNODE_H_ */
diff --git a/DataStructures/InputReaderFactory.h b/DataStructures/InputReaderFactory.h
new file mode 100644
index 0000000..f58232f
--- /dev/null
+++ b/DataStructures/InputReaderFactory.h
@@ -0,0 +1,94 @@
+/*
+    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 INPUTREADERFACTORY_H
+#define INPUTREADERFACTORY_H
+
+#include <bzlib.h>
+#include <libxml/xmlreader.h>
+
+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 read = 0;
+    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) {
+            return read;
+        } 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++) {
+                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);};
+            context->error = BZ_STREAM_END; // set to the stream end for next call to this function
+            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); }
+    }
+    return read;
+}
+
+int closeBz2Stream( void *pointer )
+{
+    BZ2Context* context = (BZ2Context*) pointer;
+    fclose( context->file );
+    delete context;
+    return 0;
+}
+
+xmlTextReaderPtr inputReaderFactory( const char* name )
+{
+    std::string inputName(name);
+
+    if(inputName.find(".osm.bz2")!=std::string::npos)
+    {
+        BZ2Context* context = new BZ2Context();
+        context->error = false;
+        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 ) {
+            delete context;
+            return NULL;
+        }
+        return xmlReaderForIO( readFromBz2Stream, closeBz2Stream, (void*) context, NULL, NULL, 0 );
+    } else {
+        return xmlNewTextReaderFilename(name);
+    }
+}
+
+#endif // INPUTREADERFACTORY_H
diff --git a/DataStructures/LRUCache.h b/DataStructures/LRUCache.h
new file mode 100644
index 0000000..a2c0b13
--- /dev/null
+++ b/DataStructures/LRUCache.h
@@ -0,0 +1,82 @@
+/*
+    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 LRUCACHE_H
+#define LRUCACHE_H
+
+#include <list>
+#include <boost/unordered_map.hpp>
+
+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) {}
+
+    bool Holds(KeyT key) {
+        if(positionMap.find(key) != positionMap.end()) {
+            return true;
+        }
+        return false;
+    }
+
+    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) {
+            positionMap.erase(itemsInCache.back().key);
+            itemsInCache.pop_back();
+        }
+    }
+
+    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) {
+            positionMap.erase(itemsInCache.back().key);
+            itemsInCache.pop_back();
+        }
+    }
+
+    bool Fetch(const KeyT key, ValueT& result) {
+        if(Holds(key)) {
+            CacheEntry e = *(positionMap.find(key)->second);
+            result = e.value;
+
+            //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();
+    }
+};
+#endif //LRUCACHE_H
diff --git a/DataStructures/MercatorUtil.h b/DataStructures/MercatorUtil.h
new file mode 100644
index 0000000..15bea27
--- /dev/null
+++ b/DataStructures/MercatorUtil.h
@@ -0,0 +1,38 @@
+/*
+    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
new file mode 100644
index 0000000..22cb4e2
--- /dev/null
+++ b/DataStructures/NNGrid.h
@@ -0,0 +1,602 @@
+/*
+    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/NodeCoords.h b/DataStructures/NodeCoords.h
new file mode 100644
index 0000000..4893a9d
--- /dev/null
+++ b/DataStructures/NodeCoords.h
@@ -0,0 +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.
+
+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
new file mode 100644
index 0000000..f13c9ad
--- /dev/null
+++ b/DataStructures/NodeInformationHelpDesk.h
@@ -0,0 +1,159 @@
+/*
+    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/Percent.h b/DataStructures/Percent.h
new file mode 100644
index 0000000..dafbe55
--- /dev/null
+++ b/DataStructures/Percent.h
@@ -0,0 +1,94 @@
+/*
+    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 PERCENT_H
+#define PERCENT_H
+
+#include <iostream>
+
+
+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);
+    }
+
+    /** Reinitializes this object. */
+    void reinit(unsigned maxValue, unsigned step = 5) {
+        _maxValue = maxValue;
+        _current_value = 0;
+        _intervalPercent = _maxValue / 100;
+        _nextThreshold = _intervalPercent;
+        _lastPercent = 0;
+        _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 (currentValue + 1 == _maxValue)
+            std::cout << " 100%" << std::endl;
+    }
+
+    void printIncrement()
+    {
+#pragma omp atomic
+        ++_current_value;
+        printStatus(_current_value);
+    }
+
+    void printAddition(const unsigned addition) {
+#pragma omp atomic
+        _current_value += addition;
+        printStatus(_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 << "% ";
+            }
+            else {
+                std::cout << ".";
+            }
+            std::cout.flush();
+        }
+    }
+};
+
+#endif // PERCENT_H
diff --git a/DataStructures/PhantomNodes.h b/DataStructures/PhantomNodes.h
new file mode 100644
index 0000000..2827d7a
--- /dev/null
+++ b/DataStructures/PhantomNodes.h
@@ -0,0 +1,94 @@
+/*
+    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;
+    }
+    bool isValid(const unsigned numberOfNodes) const {
+        return location.isValid() && (edgeBasedNode < numberOfNodes) && (weight1 != INT_MAX) && (ratio >= 0.) && (ratio <= 1.) && (nodeBasedEdgeNameID != UINT_MAX);
+    }
+
+    bool operator==(const PhantomNode & other) const {
+        return location == other.location;
+    }
+};
+
+struct PhantomNodes {
+    PhantomNode startPhantom;
+    PhantomNode targetPhantom;
+    void Reset() {
+        startPhantom.Reset();
+        targetPhantom.Reset();
+    }
+
+    bool PhantomsAreOnSameNodeBasedEdge() const {
+        return (startPhantom.edgeBasedNode == targetPhantom.edgeBasedNode);
+    }
+
+    bool AtLeastOnePhantomNodeIsUINTMAX() const {
+        return !(startPhantom.edgeBasedNode == UINT_MAX || targetPhantom.edgeBasedNode == UINT_MAX);
+    }
+
+    bool PhantomNodesHaveEqualLocation() const {
+        return startPhantom == targetPhantom;
+    }
+};
+
+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;
+    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;
+    return out;
+}
+
+struct NodesOfEdge {
+    NodeID edgeBasedNode;
+    double ratio;
+    _Coordinate projectedPoint;
+};
+
+#endif /* PHANTOMNODES_H_ */
diff --git a/DataStructures/QueryEdge.h b/DataStructures/QueryEdge.h
new file mode 100644
index 0000000..3a2aecb
--- /dev/null
+++ b/DataStructures/QueryEdge.h
@@ -0,0 +1,76 @@
+/*
+    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 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 {
+    NodeID source;
+    NodeID target;
+    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 )
+            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
+        );
+    }
+};
+
+#endif /* QUERYEDGE_H_ */
diff --git a/DataStructures/Restriction.h b/DataStructures/Restriction.h
new file mode 100644
index 0000000..3627c6a
--- /dev/null
+++ b/DataStructures/Restriction.h
@@ -0,0 +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.
+
+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 RESTRICTION_H_
+#define RESTRICTION_H_
+
+#include <climits>
+
+struct _Restriction {
+    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;
+    } 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) {
+        flags.isOnly = isOnly;
+    }
+};
+
+inline bool CmpRestrictionByFrom ( _Restriction a, _Restriction b) { return (a.fromNode < b.fromNode);  }
+
+struct _RawRestrictionContainer {
+    _Restriction restriction;
+    EdgeID fromWay;
+    EdgeID toWay;
+    unsigned viaNode;
+
+    _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);
+    }
+    static _RawRestrictionContainer max_value() {
+        return _RawRestrictionContainer(UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX);
+    }
+};
+
+struct CmpRestrictionContainerByFrom: public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
+    typedef _RawRestrictionContainer value_type;
+    bool operator ()  (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
+        return a.fromWay < b.fromWay;
+    }
+    value_type max_value()  {
+        return _RawRestrictionContainer::max_value();
+    }
+    value_type min_value() {
+        return _RawRestrictionContainer::min_value();
+    }
+};
+
+struct CmpRestrictionContainerByTo: public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
+    typedef _RawRestrictionContainer value_type;
+    bool operator ()  (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
+        return a.toWay < b.toWay;
+    }
+    value_type max_value()  {
+        return _RawRestrictionContainer::max_value();
+    }
+    value_type min_value() {
+        return _RawRestrictionContainer::min_value();
+    }
+};
+
+
+
+#endif /* RESTRICTION_H_ */
diff --git a/DataStructures/SearchEngine.cpp b/DataStructures/SearchEngine.cpp
new file mode 100644
index 0000000..2a538a7
--- /dev/null
+++ b/DataStructures/SearchEngine.cpp
@@ -0,0 +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.
+
+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
new file mode 100644
index 0000000..64d273b
--- /dev/null
+++ b/DataStructures/SearchEngine.h
@@ -0,0 +1,68 @@
+/*
+    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 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/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();
+
+	void GetCoordinatesForNodeID(NodeID id, _Coordinate& result) const;
+
+    void FindPhantomNodeForCoordinate(
+        const _Coordinate & location, 
+        PhantomNode & result, 
+        unsigned zoomLevel
+    ) const;
+
+    NodeID GetNameIDForOriginDestinationNodeID(
+        const NodeID s, const NodeID t) const;
+
+    std::string GetEscapedNameForNameID(const unsigned nameID) const;
+};
+
+#endif /* SEARCHENGINE_H_ */
diff --git a/DataStructures/SearchEngineData.cpp b/DataStructures/SearchEngineData.cpp
new file mode 100644
index 0000000..77492f6
--- /dev/null
+++ b/DataStructures/SearchEngineData.cpp
@@ -0,0 +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.
+
+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 "SearchEngineData.h"
+
+void SearchEngineData::InitializeOrClearFirstThreadLocalStorage() {
+    if(!forwardHeap.get()) {
+        forwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
+    } else {
+        forwardHeap->Clear();
+    }
+    if(!backwardHeap.get()) {
+        backwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
+    } else {
+        backwardHeap->Clear();
+    }
+}
+
+void SearchEngineData::InitializeOrClearSecondThreadLocalStorage() {
+    if(!forwardHeap2.get()) {
+        forwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
+    } else {
+        forwardHeap2->Clear();
+    }
+    if(!backwardHeap2.get()) {
+        backwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
+     } else {
+        backwardHeap2->Clear();
+    }
+}
+
+void SearchEngineData::InitializeOrClearThirdThreadLocalStorage() {
+    if(!forwardHeap3.get()) {
+        forwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
+    } else {
+        forwardHeap3->Clear();
+    }
+    if(!backwardHeap3.get()) {
+        backwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
+    } else {
+        backwardHeap3->Clear();
+    }
+}
diff --git a/DataStructures/SearchEngineData.h b/DataStructures/SearchEngineData.h
new file mode 100644
index 0000000..f9a2623
--- /dev/null
+++ b/DataStructures/SearchEngineData.h
@@ -0,0 +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.
+
+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 "BinaryHeap.h"
+#include "QueryEdge.h"
+#include "NodeInformationHelpDesk.h"
+#include "StaticGraph.h"
+
+#include "../typedefs.h"
+
+#include <boost/thread.hpp>
+
+#include <string>
+#include <vector>
+
+struct _HeapData {
+    NodeID parent;
+    _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;
+    static SearchEngineHeapPtr forwardHeap;
+    static SearchEngineHeapPtr backwardHeap;
+    static SearchEngineHeapPtr forwardHeap2;
+    static SearchEngineHeapPtr backwardHeap2;
+    static SearchEngineHeapPtr forwardHeap3;
+    static SearchEngineHeapPtr backwardHeap3;
+
+    void InitializeOrClearFirstThreadLocalStorage();
+
+    void InitializeOrClearSecondThreadLocalStorage();
+
+    void InitializeOrClearThirdThreadLocalStorage();
+};
diff --git a/DataStructures/SegmentInformation.h b/DataStructures/SegmentInformation.h
new file mode 100644
index 0000000..cbe4b81
--- /dev/null
+++ b/DataStructures/SegmentInformation.h
@@ -0,0 +1,42 @@
+/*
+    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 SEGMENTINFORMATION_H_
+#define SEGMENTINFORMATION_H_
+
+#include <climits>
+
+#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) {}
+};
+
+#endif /* SEGMENTINFORMATION_H_ */
diff --git a/DataStructures/SimpleStack.h b/DataStructures/SimpleStack.h
new file mode 100644
index 0000000..0335bcc
--- /dev/null
+++ b/DataStructures/SimpleStack.h
@@ -0,0 +1,71 @@
+/*
+    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
new file mode 100644
index 0000000..eb41683
--- /dev/null
+++ b/DataStructures/StaticGraph.h
@@ -0,0 +1,188 @@
+/*
+    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 STATICGRAPH_H_INCLUDED
+#define STATICGRAPH_H_INCLUDED
+
+#include <vector>
+#include <algorithm>
+
+#include "../typedefs.h"
+#include "ImportEdge.h"
+
+template< typename EdgeDataT>
+class StaticGraph {
+public:
+    typedef NodeID NodeIterator;
+    typedef NodeID EdgeIterator;
+    typedef EdgeDataT EdgeData;
+    class InputEdge {
+    public:
+        EdgeDataT data;
+        NodeIterator source;
+        NodeIterator target;
+        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 _StrEdge {
+        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);
+        EdgeIterator edge = 0;
+        EdgeIterator position = 0;
+        for ( NodeIterator node = 0; node <= _numNodes; ++node ) {
+            EdgeIterator lastEdge = edge;
+            while ( edge < _numEdges && graph[edge].source == node )
+                ++edge;
+            _nodes[node].firstEdge = position; //=edge
+            position += edge - lastEdge; //remove
+        }
+        _edges.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);
+                edge++;
+            }
+        }
+    }
+
+    StaticGraph( std::vector<_StrNode> & nodes, std::vector<_StrEdge> & edges) {
+        _numNodes = nodes.size();
+        _numEdges = edges.size();
+
+        _nodes.swap(nodes);
+        _edges.swap(edges);
+
+        //Add dummy node to end of _nodes array;
+        _nodes.push_back(_nodes.back());
+
+#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;
+                    }
+                }
+            }
+            p.printIncrement();
+        }
+#endif
+    }
+
+    unsigned GetNumberOfNodes() const {
+        return _numNodes;
+    }
+
+    unsigned GetNumberOfEdges() const {
+        return _numEdges;
+    }
+
+    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 EdgeDataT &GetEdgeData( const EdgeIterator &e ) {
+        return _edges[e].data;
+    }
+
+    const EdgeDataT &GetEdgeData( const EdgeIterator &e ) const {
+        return _edges[e].data;
+    }
+
+    EdgeIterator BeginEdges( const NodeIterator &n ) const {
+        return EdgeIterator( _nodes[n].firstEdge );
+    }
+
+    EdgeIterator EndEdges( const NodeIterator &n ) const {
+        return EdgeIterator( _nodes[n+1].firstEdge );
+    }
+
+    //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++ ) {
+            const NodeID target = GetTarget(edge);
+            const EdgeWeight weight = GetEdgeData(edge).distance;
+            if(target == to && weight < smallestWeight) {
+                smallestEdge = edge; smallestWeight = weight;
+            }
+        }
+        return smallestEdge;
+    }
+
+    EdgeIterator FindEdgeInEitherDirection( const NodeIterator &from, const NodeIterator &to ) const {
+        EdgeIterator tmp =  FindEdge( from, to );
+        return (UINT_MAX != 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)
+                result = true;
+        }
+        return tmp;
+    }
+
+private:
+
+    NodeIterator _numNodes;
+    EdgeIterator _numEdges;
+
+    std::vector< _StrNode > _nodes;
+    std::vector< _StrEdge > _edges;
+};
+
+#endif // STATICGRAPH_H_INCLUDED
diff --git a/DataStructures/StaticKDTree.h b/DataStructures/StaticKDTree.h
new file mode 100644
index 0000000..85ffb80
--- /dev/null
+++ b/DataStructures/StaticKDTree.h
@@ -0,0 +1,223 @@
+/*
+    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.
+
+KD Tree coded by Christian Vetter, Monav Project
+
+ */
+#ifndef STATICKDTREE_H_INCLUDED
+#define STATICKDTREE_H_INCLUDED
+
+#include <cassert>
+#include <vector>
+#include <algorithm>
+#include <stack>
+#include <limits>
+
+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();
+        }
+    }
+
+    T min[k];
+    T max[k];
+};
+
+struct NoData {};
+
+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 ) {
+            double temp = (double)left[i] - (double)right[i];
+            result += temp * temp;
+        }
+        return result;
+    }
+
+    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] )
+                nearest[dim] = box.min[dim];
+            else if ( point[dim] > box.max[dim] )
+                nearest[dim] = box.max[dim];
+            else
+                nearest[dim] = point[dim];
+        }
+        return operator() ( point, nearest );
+    }
+};
+
+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] )
+                    return false;
+            }
+            return true;
+		                }
+    };
+
+    StaticKDTree( std::vector< InputPoint > * points ){
+        assert( k > 0 );
+        assert ( points->size() > 0 );
+        size = points->size();
+        kdtree = new InputPoint[size];
+        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] )
+                    boundingBox.min[dim] = kdtree[i].coordinates[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() ) {
+            Tree tree = s.top();
+            s.pop();
+
+            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 ) );
+        }
+    }
+
+    ~StaticKDTree(){
+        delete[] kdtree;
+    }
+
+    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() ) {
+            NNTree tree = s.top();
+            s.pop();
+
+            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 ) {
+                        nearestDistance = newDistance;
+                        *result = kdtree[i];
+                        found = true;
+                    }
+                }
+                continue;
+            }
+
+            Iterator middle = tree.left + ( tree.right - tree.left ) / 2;
+
+            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 );
+                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 );
+            }
+            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 );
+            }
+        }
+        return found;
+    }
+
+private:
+    typedef unsigned Iterator;
+    struct Tree {
+        Iterator left;
+        Iterator right;
+        unsigned dimension;
+        Tree() {}
+        Tree( Iterator l, Iterator r, unsigned d ): left( l ), right( r ), dimension( d ) {}
+    };
+    struct NNTree {
+        Iterator left;
+        Iterator right;
+        unsigned dimension;
+        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 ) {}
+    };
+    class Less {
+    public:
+        Less( unsigned d ) {
+            dimension = d;
+            assert( dimension < k );
+        }
+
+        bool operator() ( const InputPoint& left, const InputPoint& right ) {
+            assert( dimension < k );
+            return left.coordinates[dimension] < right.coordinates[dimension];
+        }
+    private:
+        unsigned dimension;
+    };
+
+    BoundingBox< k, T > boundingBox;
+    InputPoint* kdtree;
+    Iterator size;
+};
+
+}
+
+#endif // STATICKDTREE_H_INCLUDED
diff --git a/DataStructures/StaticRTree.h b/DataStructures/StaticRTree.h
new file mode 100644
index 0000000..b85516f
--- /dev/null
+++ b/DataStructures/StaticRTree.h
@@ -0,0 +1,909 @@
+/*
+    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"
+#include "DeallocatingVector.h"
+#include "HilbertValue.h"
+#include "../typedefs.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/thread.hpp>
+
+#include <cassert>
+#include <cfloat>
+#include <climits>
+
+#include <algorithm>
+#include <fstream>
+#include <queue>
+#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
+
+static boost::thread_specific_ptr<std::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) {}
+
+        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 AugmentMBRectangle(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);
+        }
+
+        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;
+            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);
+
+            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;
+            }
+
+            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
+                    )
+            );
+            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);
+
+            min_max_dist = std::min(
+                    min_max_dist,
+                    std::max(
+                            ApproximateDistance(location, upper_left ),
+                            ApproximateDistance(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::min(
+                    min_max_dist,
+                    std::max(
+                            ApproximateDistance(location, lower_right),
+                            ApproximateDistance(location, lower_left )
+                    )
+            );
+
+            min_max_dist = std::min(
+                    min_max_dist,
+                    std::max(
+                            ApproximateDistance(location, lower_left ),
+                            ApproximateDistance(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);
+            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.;
+            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) {}
+
+        uint32_t m_array_index;
+        uint64_t m_hilbert_value;
+
+        inline bool operator<(const WrappedInputElement & other) const {
+            return m_hilbert_value < other.m_hilbert_value;
+        }
+    };
+
+    struct LeafNode {
+        LeafNode() : object_count(0) {}
+        uint32_t object_count;
+        DataT objects[RTREE_LEAF_NODE_SIZE];
+    };
+
+    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 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;
+        }
+    };
+
+    std::vector<TreeNode> m_search_tree;
+    uint64_t m_element_count;
+
+    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");
+        std::vector<TreeNode> tree_nodes_in_level;
+
+        //pack M elements into leaf node and write to leaf file
+        uint64_t processed_objects_count = 0;
+        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];
+                    ++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);
+            current_node.child_is_on_disk = true;
+            current_node.children[0] = tree_nodes_in_level.size();
+            tree_nodes_in_level.push_back(current_node);
+
+            //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
+        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);
+            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()) {
+                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
+                        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
+                        ++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_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]);
+
+        //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;
+            }
+        }
+
+        //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.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. << ")");
+*/
+    }
+
+    //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);
+        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");
+        m_search_tree.resize(tree_size);
+        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
+        std::ifstream leaf_node_file(leaf_filename, 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");
+    }
+/*
+    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;
+
+        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;
+
+        _Coordinate nearest, current_start_coordinate, current_end_coordinate;
+
+        //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) {
+                    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) {
+                            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;
+                        }
+                    }
+                } 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));
+                    }
+                }
+            }
+        }
+
+        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;
+
+        //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;
+        }
+
+        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;
+
+    }
+
+  */
+    bool FindPhantomNodeForCoordinate(
+            const _Coordinate & input_coordinate,
+            PhantomNode & result_phantom_node,
+            const unsigned zoom_level
+    ) {
+
+        bool ignore_tiny_components = (zoom_level <= 14);
+        DataT nearest_edge;
+
+        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;
+
+        _Coordinate nearest, current_start_coordinate, current_end_coordinate;
+
+        //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) {
+                    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()) {
+                            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
+                        );
+
+                        //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
+                            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
+                            )
+                        ) {
+                            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));
+                    }
+                }
+            }
+        }
+
+        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);
+        }
+        result_phantom_node.ratio = ratio;
+
+        //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;
+        }
+
+//        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;
+
+    }
+/*
+    //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));
+                    }
+                }
+            }
+        }
+        INFO("mindist: " << min_dist << ", io's: " << io_count << ",  touched nodes: " << explored_tree_nodes_count);
+        return found_return_value;
+    }
+ */
+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()) {
+            thread_local_rtree_stream->clear(std::ios::goodbit);
+            DEBUG("Resetting stale filestream");
+        }
+        uint64_t seek_pos = sizeof(uint64_t) + leaf_id*sizeof(LeafNode);
+        thread_local_rtree_stream->seekg(seek_pos);
+        thread_local_rtree_stream->read((char *)&result_node, sizeof(LeafNode));
+    }
+
+    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 {
+        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);
+    }
+
+};
+
+//[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_ */
diff --git a/DataStructures/TimingUtil.h b/DataStructures/TimingUtil.h
new file mode 100644
index 0000000..6e980e2
--- /dev/null
+++ b/DataStructures/TimingUtil.h
@@ -0,0 +1,50 @@
+/*
+    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
new file mode 100644
index 0000000..3284d9b
--- /dev/null
+++ b/DataStructures/TurnInstructions.h
@@ -0,0 +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.
+
+ 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 TURNINSTRUCTIONS_H_
+#define TURNINSTRUCTIONS_H_
+
+#include <boost/noncopyable.hpp>
+
+typedef unsigned char TurnInstruction;
+
+//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.
+
+    const static int AccessRestrictionPenalty = 1 << 15; //unrelated to the bit set in the restriction flag
+
+    static inline TurnInstruction GetTurnDirectionOfInstruction( const double angle ) {
+        if(angle >= 23 && angle < 67) {
+            return TurnSharpRight;
+        }
+        if (angle >= 67 && angle < 113) {
+            return TurnRight;
+        }
+        if (angle >= 113 && angle < 158) {
+            return TurnSlightRight;
+        }
+        if (angle >= 158 && angle < 202) {
+            return GoStraight;
+        }
+        if (angle >= 202 && angle < 248) {
+            return TurnSlightLeft;
+        }
+        if (angle >= 248 && angle < 292) {
+            return TurnLeft;
+        }
+        if (angle >= 292 && angle < 336) {
+            return TurnSharpLeft;
+        }
+        return UTurn;
+    }
+
+    static inline bool TurnIsNecessary ( const short turnInstruction ) {
+        if(NoTurn == turnInstruction || StayOnRoundAbout == turnInstruction)
+            return false;
+        return true;
+    }
+
+};
+
+static TurnInstructionsClass TurnInstructions;
+
+#endif /* TURNINSTRUCTIONS_H_ */
diff --git a/DataStructures/XORFastHash.h b/DataStructures/XORFastHash.h
new file mode 100644
index 0000000..c3c1470
--- /dev/null
+++ b/DataStructures/XORFastHash.h
@@ -0,0 +1,95 @@
+/*
+    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 FASTXORHASH_H_
+#define FASTXORHASH_H_
+
+#include <algorithm>
+#include <vector>
+
+/*
+    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:
+
+    1: movq    table2(%rip), %rdx
+    2: movl    %edi, %eax
+    3: movzwl  %di, %edi
+    4: shrl    $16, %eax
+    5: movzwl  %ax, %eax
+    6: movzbl  (%rdx,%rax), %eax
+    7: movq    table1(%rip), %rdx
+    8: xorb    (%rdx,%rdi), %al
+    9: movzbl  %al, %eax
+    10: ret
+
+*/
+class XORFastHash { //65k entries
+    std::vector<unsigned short> table1;
+    std::vector<unsigned short> table2;
+public:
+    XORFastHash() {
+        table1.resize(2 << 16);
+        table2.resize(2 << 16);
+        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 {
+        unsigned short lsb = ((originalValue) & 0xffff);
+        unsigned short msb = (((originalValue) >> 16) & 0xffff);
+        return table1[lsb] ^ table2[msb];
+    }
+};
+
+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() {
+        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;
+        }
+        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 byte1 = ((originalValue) & 0xff);
+        unsigned char byte2 = ((originalValue >> 8) & 0xff);
+        unsigned char byte3 = ((originalValue >> 16) & 0xff);
+        unsigned char byte4 = ((originalValue >> 24) & 0xff);
+        return table1[byte1] ^ table2[byte2] ^ table3[byte3] ^ table4[byte4];
+    }
+};
+
+#endif /* FASTXORHASH_H_ */
diff --git a/DataStructures/XORFastHashStorage.h b/DataStructures/XORFastHashStorage.h
new file mode 100644
index 0000000..91820e1
--- /dev/null
+++ b/DataStructures/XORFastHashStorage.h
@@ -0,0 +1,80 @@
+/*
+    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 XORFASTHASHSTORAGE_H_
+#define XORFASTHASHSTORAGE_H_
+
+#include <climits>
+#include <vector>
+#include <bitset>
+
+#include "XORFastHash.h"
+
+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(const HashCell & other) : key(other.key), id(other.id), time(other.time) { }
+
+        inline operator Key() const {
+            return key;
+        }
+
+        inline void operator=(const Key & keyToInsert) {
+            key = keyToInsert;
+        }
+    };
+
+    XORFastHashStorage( size_t ) : positions(2<<16), currentTimestamp(0) { }
+
+    inline HashCell& operator[]( const NodeID node ) {
+        unsigned short position = fastHash(node);
+        while((positions[position].time == currentTimestamp) && (positions[position].id != node)){
+            ++position %= (2<<16);
+        }
+
+        positions[position].id = node;
+        positions[position].time = currentTimestamp;
+        return positions[position];
+    }
+
+    inline void Clear() {
+        ++currentTimestamp;
+        if(UINT_MAX == currentTimestamp) {
+            positions.clear();
+            positions.resize((2<<16));
+        }
+    }
+
+private:
+    XORFastHashStorage() : positions(2<<16), currentTimestamp(0) {}
+    std::vector<HashCell> positions;
+    XORFastHash fastHash;
+    unsigned currentTimestamp;
+};
+
+
+#endif /* XORFASTHASHSTORAGE_H_ */
+
diff --git a/Descriptors/BaseDescriptor.h b/Descriptors/BaseDescriptor.h
new file mode 100644
index 0000000..2ead8bd
--- /dev/null
+++ b/Descriptors/BaseDescriptor.h
@@ -0,0 +1,55 @@
+/*
+    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"
+#include "../DataStructures/PhantomNodes.h"
+#include "../DataStructures/SearchEngine.h"
+#include "../Util/StringUtil.h"
+
+#include "../Plugins/RawRouteData.h"
+
+struct _DescriptorConfig {
+    _DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(true), z(18) {}
+    bool instructions;
+    bool geometry;
+    bool encodeGeometry;
+    unsigned short z;
+};
+
+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;
+};
+
+#endif /* BASE_DESCRIPTOR_H_ */
diff --git a/Descriptors/DescriptionFactory.cpp b/Descriptors/DescriptionFactory.cpp
new file mode 100644
index 0000000..b1f2f85
--- /dev/null
+++ b/Descriptors/DescriptionFactory.cpp
@@ -0,0 +1,210 @@
+/*
+ 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 "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.);
+
+    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;
+}
+
+void DescriptionFactory::SetStartSegment(const PhantomNode & _startPhantom) {
+    startPhantom = _startPhantom;
+    AppendSegment(_startPhantom.location, _PathData(0, _startPhantom.nodeBasedEdgeNameID, 10, _startPhantom.weight1));
+}
+
+void DescriptionFactory::SetEndSegment(const PhantomNode & _targetPhantom) {
+    targetPhantom = _targetPhantom;
+    pathDescription.push_back(SegmentInformation(_targetPhantom.location, _targetPhantom.nodeBasedEdgeNameID, 0, _targetPhantom.weight1, 0, true) );
+}
+
+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) );
+    }
+}
+
+void DescriptionFactory::AppendEncodedPolylineString(std::string & output, bool isEncoded) {
+    if(isEncoded)
+        pc.printEncodedString(pathDescription, output);
+    else
+        pc.printUnencodedString(pathDescription, output);
+}
+
+void DescriptionFactory::AppendEncodedPolylineString(std::string &output) {
+    pc.printEncodedString(pathDescription, output);
+}
+
+void DescriptionFactory::AppendUnencodedPolylineString(std::string &output) {
+    pc.printUnencodedString(pathDescription, output);
+}
+
+void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLevel) {
+
+    if(0 == pathDescription.size())
+        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);
+
+    //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;
+        }
+    }
+
+//    BuildRouteSummary(entireLength, duration);
+    return;
+}
+
+void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time) {
+    summary.startName = startPhantom.nodeBasedEdgeNameID;
+    summary.destName = targetPhantom.nodeBasedEdgeNameID;
+    summary.BuildDurationAndLengthStrings(distance, time);
+}
diff --git a/Descriptors/DescriptionFactory.h b/Descriptors/DescriptionFactory.h
new file mode 100644
index 0000000..911aae7
--- /dev/null
+++ b/Descriptors/DescriptionFactory.h
@@ -0,0 +1,76 @@
+/*
+ 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 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/SegmentInformation.h"
+#include "../DataStructures/TurnInstructions.h"
+
+/* 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;
+
+    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);
+        }
+    } summary;
+
+    double entireLength;
+
+    //I know, declaring this public is considered bad. I'm lazy
+    std::vector <SegmentInformation> pathDescription;
+    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 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);
+};
+
+#endif /* DESCRIPTIONFACTORY_H_ */
diff --git a/Descriptors/GPXDescriptor.h b/Descriptors/GPXDescriptor.h
new file mode 100644
index 0000000..1d3389a
--- /dev/null
+++ b/Descriptors/GPXDescriptor.h
@@ -0,0 +1,65 @@
+/*
+    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 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>";
+            }
+            convertInternalLatLonToString(phantomNodes.targetPhantom.location.lat, tmp);
+            reply.content += "<rtept lat=\"" + tmp + "\" ";
+            convertInternalLatLonToString(phantomNodes.targetPhantom.location.lon, tmp);
+            reply.content += "lon=\"" + tmp + "\"></rtept>";
+        }
+        reply.content += "</rte></gpx>";
+    }
+};
+#endif /* GPX_DESCRIPTOR_H_ */
diff --git a/Descriptors/JSONDescriptor.h b/Descriptors/JSONDescriptor.h
new file mode 100644
index 0000000..1db2c68
--- /dev/null
+++ b/Descriptors/JSONDescriptor.h
@@ -0,0 +1,392 @@
+/*
+    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_ */
diff --git a/Docs/webclient.txt b/Docs/webclient.txt
new file mode 100644
index 0000000..55fcd15
--- /dev/null
+++ b/Docs/webclient.txt
@@ -0,0 +1,3 @@
+The javascript based web client is a seperate project available at
+
+https://github.com/DennisSchiefer/Project-OSRM-Web
\ No newline at end of file
diff --git a/Extractor/BaseParser.cpp b/Extractor/BaseParser.cpp
new file mode 100644
index 0000000..6981e95
--- /dev/null
+++ b/Extractor/BaseParser.cpp
@@ -0,0 +1,116 @@
+/*
+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 "BaseParser.h"
+
+BaseParser::BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se) :
+extractor_callbacks(ec), scriptingEnvironment(se), luaState(NULL), use_turn_restrictions(true) {
+    luaState = se.getLuaStateForThreadID(0);
+    ReadUseRestrictionsSetting();
+    ReadRestrictionExceptions();
+}
+
+void BaseParser::ReadUseRestrictionsSetting() {
+    if( 0 != luaL_dostring( luaState, "return use_turn_restrictions\n") ) {
+        ERR(lua_tostring( luaState,-1)<< " occured in scripting block");
+    }
+    if( lua_isboolean( luaState, -1) ) {
+        use_turn_restrictions = lua_toboolean(luaState, -1);
+    }
+    if( use_turn_restrictions ) {
+        INFO("Using turn restrictions" );
+    } else {
+        INFO("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());
+        }
+    } else {
+        INFO("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::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::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());
+    }
+}
+
+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 ) {
+        return false;
+    }
+    
+    //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) ) {
+            return true;
+        }
+    }
+    return false;
+}
diff --git a/Extractor/BaseParser.h b/Extractor/BaseParser.h
new file mode 100644
index 0000000..6a19efa
--- /dev/null
+++ b/Extractor/BaseParser.h
@@ -0,0 +1,59 @@
+/*
+    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 BASEPARSER_H_
+#define BASEPARSER_H_
+
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+}
+
+#include <boost/noncopyable.hpp>
+
+#include "ExtractorCallbacks.h"
+#include "ScriptingEnvironment.h"
+
+class BaseParser : boost::noncopyable {
+public:
+    BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se);
+    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;
+
+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;
+    std::vector<std::string> restriction_exceptions;
+    bool use_turn_restrictions;
+
+};
+
+#endif /* BASEPARSER_H_ */
diff --git a/Extractor/ExtractionContainers.cpp b/Extractor/ExtractionContainers.cpp
new file mode 100644
index 0000000..2cb2baf
--- /dev/null
+++ b/Extractor/ExtractionContainers.cpp
@@ -0,0 +1,306 @@
+/*
+ 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 "ExtractionContainers.h"
+
+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;
+
+        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;
+
+        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();
+
+        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();
+
+        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] 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;
+                continue;
+            }
+            if(wayStartAndEndEdgeIT->wayID > restrictionsIT->fromWay) {
+                ++restrictionsIT;
+                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;
+            }
+            ++restrictionsIT;
+        }
+
+        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
+        time = get_timestamp();
+
+        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;
+
+        time = get_timestamp();
+        unsigned usableRestrictionsCounter(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;
+                continue;
+            }
+            if(wayStartAndEndEdgeIT->wayID > restrictionsIT->toWay) {
+                ++restrictionsIT;
+                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;
+            }
+
+            if(UINT_MAX != restrictionsIT->restriction.fromNode && UINT_MAX != restrictionsIT->restriction.toNode) {
+                ++usableRestrictionsCounter;
+            }
+            ++restrictionsIT;
+        }
+        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));
+            }
+        }
+        restrictionsOutstream.close();
+
+        std::ofstream fout;
+        fout.open(outputFileName.c_str(), std::ios::binary);
+        fout.write((char*)&usedNodeCounter, sizeof(unsigned));
+        time = get_timestamp();
+        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;
+                continue;
+            }
+            if(*usedNodeIDsIT > nodesIT->id) {
+                ++nodesIT;
+                continue;
+            }
+            if(*usedNodeIDsIT == nodesIT->id) {
+                fout.write((char*)&(*nodesIT), sizeof(_Node));
+                ++usedNodeCounter;
+                ++usedNodeIDsIT;
+                ++nodesIT;
+            }
+        }
+
+        std::cout << "ok, after " << get_timestamp() - time << "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::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();
+
+        std::cout << "[extractor] Setting start coords      ... " << std::flush;
+        fout.write((char*)&usedEdgeCounter, 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;
+                continue;
+            }
+            if(edgeIT->start > nodesIT->id) {
+                nodesIT++;
+                continue;
+            }
+            if(edgeIT->start == nodesIT->id) {
+                edgeIT->startCoord.lat = nodesIT->lat;
+                edgeIT->startCoord.lon = nodesIT->lon;
+                ++edgeIT;
+            }
+        }
+        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
+        time = get_timestamp();
+
+        // 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();
+
+        std::cout << "[extractor] Setting target coords     ... " << std::flush;
+        // 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;
+                continue;
+            }
+            if(edgeIT->target > nodesIT->id) {
+                ++nodesIT;
+                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;
+                }
+                ++edgeIT;
+            }
+        }
+        std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
+        std::cout << "[extractor] setting number of edges   ... " << std::flush;
+
+        fout.seekp(positionInFile);
+        fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
+        fout.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);
+        }
+
+        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;
+
+        INFO("Processed " << usedNodeCounter << " nodes and " << usedEdgeCounter << " edges");
+
+
+    } catch ( const std::exception& e ) {
+      std::cerr <<  "Caught Execption:" << e.what() << std::endl;
+    }
+}
+
diff --git a/Extractor/ExtractionContainers.h b/Extractor/ExtractionContainers.h
new file mode 100644
index 0000000..f5dfa78
--- /dev/null
+++ b/Extractor/ExtractionContainers.h
@@ -0,0 +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.
+
+ 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 EXTRACTIONCONTAINERS_H_
+#define EXTRACTIONCONTAINERS_H_
+
+#include "ExtractorStructs.h"
+#include "../DataStructures/TimingUtil.h"
+
+#include <boost/foreach.hpp>
+#include <stxxl.h>
+
+class ExtractionContainers {
+public:
+    typedef stxxl::vector<NodeID> STXXLNodeIDVector;
+    typedef stxxl::vector<_Node> 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());
+        }
+
+        nameVector.push_back("");
+    }
+    virtual ~ExtractionContainers() {
+        usedNodeIDs.clear();
+        allNodes.clear();
+        allEdges.clear();
+        nameVector.clear();
+        restrictionsVector.clear();
+        wayStartEndVector.clear();
+    }
+
+    void PrepareData( const std::string & outputFileName, const std::string restrictionsFileName, const unsigned amountOfRAM);
+
+    STXXLNodeIDVector           usedNodeIDs;
+    STXXLNodeVector             allNodes;
+    STXXLEdgeVector             allEdges;
+    STXXLStringVector           nameVector;
+    STXXLRestrictionsVector     restrictionsVector;
+    STXXLWayIDStartEndVector    wayStartEndVector;
+
+};
+
+#endif /* EXTRACTIONCONTAINERS_H_ */
diff --git a/Extractor/ExtractionHelperFunctions.h b/Extractor/ExtractionHelperFunctions.h
new file mode 100644
index 0000000..6771939
--- /dev/null
+++ b/Extractor/ExtractionHelperFunctions.h
@@ -0,0 +1,83 @@
+/*
+    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 EXTRACTIONHELPERFUNCTIONS_H_
+#define EXTRACTIONHELPERFUNCTIONS_H_
+
+#include <boost/algorithm/string.hpp>
+#include <boost/algorithm/string_regex.hpp>
+#include <boost/regex.hpp>
+#include <climits>
+
+
+#include "../Util/StringUtil.h"
+
+namespace qi = boost::spirit::qi;
+
+//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);
+
+    std::vector< std::string > result;
+    boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ;
+    bool matched = regex_match(s, e);
+    return matched;
+}
+
+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;
+    }
+    return n;
+}
+
+#endif /* EXTRACTIONHELPERFUNCTIONS_H_ */
diff --git a/Extractor/ExtractorCallbacks.cpp b/Extractor/ExtractorCallbacks.cpp
new file mode 100644
index 0000000..c8b5fc1
--- /dev/null
+++ b/Extractor/ExtractorCallbacks.cpp
@@ -0,0 +1,142 @@
+/*
+    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.
+ */
+
+/*
+    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 "ExtractorCallbacks.h"
+#include "ExtractionHelperFunctions.h"
+
+ExtractorCallbacks::ExtractorCallbacks() {externalMemory = NULL; stringMap = NULL; }
+ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap) {
+    externalMemory = ext;
+    stringMap = strMap;
+}
+
+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);
+    }
+}
+
+bool ExtractorCallbacks::restrictionFunction(const _RawRestrictionContainer &r) {
+    externalMemory->restrictionsVector.push_back(r);
+    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;
+        }
+
+        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(FLT_EPSILON >= fabs(-1. - parsed_way.speed)){
+            DEBUG("found way with bogus speed, id: " << parsed_way.id);
+            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(ExtractionWay::opposite == parsed_way.direction) {
+            std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
+            parsed_way.direction = ExtractionWay::oneway;
+        }
+
+        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()));
+        }
+    }
+}
diff --git a/Extractor/ExtractorCallbacks.h b/Extractor/ExtractorCallbacks.h
new file mode 100644
index 0000000..4293d13
--- /dev/null
+++ b/Extractor/ExtractorCallbacks.h
@@ -0,0 +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.
+ */
+
+#ifndef EXTRACTORCALLBACKS_H_
+#define EXTRACTORCALLBACKS_H_
+
+#include <string>
+#include <vector>
+
+#include <cfloat>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/algorithm/string/regex.hpp>
+#include <boost/regex.hpp>
+
+#include "ExtractionContainers.h"
+#include "ExtractorStructs.h"
+
+class ExtractorCallbacks{
+private:
+    StringMap * stringMap;
+    ExtractionContainers * externalMemory;
+
+    ExtractorCallbacks();
+public:
+    explicit ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap);
+
+    ~ExtractorCallbacks();
+
+    /** warning: caller needs to take care of synchronization! */
+    void nodeFunction(const _Node &n);
+
+    bool restrictionFunction(const _RawRestrictionContainer &r);
+
+    /** warning: caller needs to take care of synchronization! */
+    void wayFunction(ExtractionWay &w);
+
+};
+
+#endif /* EXTRACTORCALLBACKS_H_ */
diff --git a/Extractor/ExtractorStructs.h b/Extractor/ExtractorStructs.h
new file mode 100644
index 0000000..fe21da9
--- /dev/null
+++ b/Extractor/ExtractorStructs.h
@@ -0,0 +1,222 @@
+/*
+    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 EXTRACTORSTRUCTS_H_
+#define EXTRACTORSTRUCTS_H_
+
+#include <climits>
+#include <string>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/algorithm/string/regex.hpp>
+#include <boost/regex.hpp>
+#include <boost/unordered_map.hpp>
+
+#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;
+};
+
+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 {
+    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)());
+    }
+    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();
+    }
+};
+
+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;
+    }
+    value_type min_value() {
+        return 0x0;
+    }
+};
+
+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 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 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();
+    }
+};
+
+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/PBFParser.cpp b/Extractor/PBFParser.cpp
new file mode 100644
index 0000000..51b099f
--- /dev/null
+++ b/Extractor/PBFParser.cpp
@@ -0,0 +1,482 @@
+/*
+ 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 "PBFParser.h"
+
+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;
+	}
+
+#ifndef NDEBUG
+	blockCount = 0;
+	groupCount = 0;
+#endif
+}
+
+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
+}
+
+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 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::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 bool PBFParser::Parse() {
+	// Start the read and parse threads
+	boost::thread readThread(boost::bind(&PBFParser::ReadData, this));
+
+	//Open several parse threads that are synchronized before call to
+	boost::thread parseThread(boost::bind(&PBFParser::ParseData, this));
+
+	// Wait for the threads to finish
+	readThread.join();
+	parseThread.join();
+
+	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::parseNode(_ThreadData * ) {
+	ERR("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::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::loadGroup(_ThreadData * threadData) {
+#ifndef NDEBUG
+	++groupCount;
+#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 );
+}
+
+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 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::unpackLZMA(std::fstream &, _ThreadData * ) {
+	return false;
+}
+
+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;
+}
+
+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;
+}
diff --git a/Extractor/PBFParser.h b/Extractor/PBFParser.h
new file mode 100644
index 0000000..f3748b6
--- /dev/null
+++ b/Extractor/PBFParser.h
@@ -0,0 +1,102 @@
+/*
+ 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 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 <osmpbf/fileformat.pb.h>
+#include <osmpbf/osmformat.pb.h>
+
+#include <zlib.h>
+
+
+
+class PBFParser : public BaseParser {
+
+    enum EntityType {
+        TypeNode = 1,
+        TypeWay = 2,
+        TypeRelation = 4,
+        TypeDenseNode = 8
+    } ;
+
+    struct _ThreadData {
+        int currentGroupID;
+        int currentEntityID;
+        short entityTypeIndicator;
+
+        OSMPBF::BlobHeader PBFBlobHeader;
+        OSMPBF::Blob PBFBlob;
+
+        OSMPBF::HeaderBlock PBFHeaderBlock;
+        OSMPBF::PrimitiveBlock PBFprimitiveBlock;
+
+        std::vector<char> charBuffer;
+    };
+
+public:
+    PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se);
+    virtual ~PBFParser();
+
+    inline bool ReadHeader();
+	inline bool Parse();
+
+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);
+
+    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
+
+    std::fstream input;     // the input stream to parse
+    boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue;
+};
+
+#endif /* PBFPARSER_H_ */
diff --git a/Extractor/ScriptingEnvironment.cpp b/Extractor/ScriptingEnvironment.cpp
new file mode 100644
index 0000000..6bab21c
--- /dev/null
+++ b/Extractor/ScriptingEnvironment.cpp
@@ -0,0 +1,108 @@
+/*
+ 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 "ScriptingEnvironment.h"
+
+ScriptingEnvironment::ScriptingEnvironment() {}
+ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
+	INFO("Using script " << fileName);
+
+    // Create a new lua state
+    for(int i = 0; i < omp_get_max_threads(); ++i)
+        luaStateVector.push_back(luaL_newstate());
+
+    // Connect LuaBind to this lua state for all threads
+#pragma omp parallel
+    {
+        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");
+        }
+    }
+}
+
+ScriptingEnvironment::~ScriptingEnvironment() {
+    for(unsigned i = 0; i < luaStateVector.size(); ++i) {
+        //        luaStateVector[i];
+    }
+}
+
+lua_State * ScriptingEnvironment::getLuaStateForThreadID(const int id) {
+    return luaStateVector[id];
+}
diff --git a/Extractor/ScriptingEnvironment.h b/Extractor/ScriptingEnvironment.h
new file mode 100644
index 0000000..015ff25
--- /dev/null
+++ b/Extractor/ScriptingEnvironment.h
@@ -0,0 +1,50 @@
+/*
+ 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 SCRIPTINGENVIRONMENT_H_
+#define SCRIPTINGENVIRONMENT_H_
+
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+}
+#include <luabind/luabind.hpp>
+
+#include "ExtractionHelperFunctions.h"
+#include "ExtractorStructs.h"
+
+#include "../typedefs.h"
+#include "../DataStructures/ImportNode.h"
+#include "../Util/LuaUtil.h"
+#include "../Util/OpenMPWrapper.h"
+
+class ScriptingEnvironment {
+public:
+    ScriptingEnvironment();
+    ScriptingEnvironment(const char * fileName);
+    virtual ~ScriptingEnvironment();
+
+    lua_State * getLuaStateForThreadID(const int);
+
+    std::vector<lua_State *> luaStateVector;
+};
+
+#endif /* SCRIPTINGENVIRONMENT_H_ */
diff --git a/Extractor/XMLParser.cpp b/Extractor/XMLParser.cpp
new file mode 100644
index 0000000..fa810a7
--- /dev/null
+++ b/Extractor/XMLParser.cpp
@@ -0,0 +1,276 @@
+/*
+ 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 <boost/ref.hpp>
+
+#include "XMLParser.h"
+
+#include "ExtractorStructs.h"
+#include "../DataStructures/HashTable.h"
+#include "../DataStructures/InputReaderFactory.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);
+}
+
+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;
+}
+
+_RawRestrictionContainer XMLParser::_ReadXMLRestriction() {
+    _RawRestrictionContainer restriction;
+    std::string except_tag_string;
+
+	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;
+}
+
+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;
+}
+
+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;
+}
diff --git a/Extractor/XMLParser.h b/Extractor/XMLParser.h
new file mode 100644
index 0000000..a2af2fb
--- /dev/null
+++ b/Extractor/XMLParser.h
@@ -0,0 +1,42 @@
+/*
+ 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 XMLPARSER_H_
+#define XMLPARSER_H_
+
+#include <libxml/xmlreader.h>
+
+#include "../typedefs.h"
+#include "BaseParser.h"
+
+class XMLParser : public BaseParser {
+public:
+    XMLParser(const char* filename, ExtractorCallbacks* ec, ScriptingEnvironment& se);
+    bool ReadHeader();
+    bool Parse();
+    
+private:
+    _RawRestrictionContainer _ReadXMLRestriction();
+    ExtractionWay _ReadXMLWay();
+    ImportNode _ReadXMLNode();
+    xmlTextReaderPtr inputReader;
+};
+
+#endif /* XMLPARSER_H_ */
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..114808e
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,7 @@
+source "http://rubygems.org"
+
+gem "cucumber"
+gem "rake"
+gem "osmlib-base"
+gem "sys-proctable"
+gem "rspec-expectations"
\ No newline at end of file
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000..32a3fda
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,30 @@
+GEM
+  remote: http://rubygems.org/
+  specs:
+    builder (3.0.0)
+    cucumber (1.1.4)
+      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)
+    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)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  cucumber
+  osmlib-base
+  rake
+  rspec-expectations
+  sys-proctable
diff --git a/LICENCE.TXT b/LICENCE.TXT
new file mode 100644
index 0000000..dba13ed
--- /dev/null
+++ b/LICENCE.TXT
@@ -0,0 +1,661 @@
+                    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/>.
diff --git a/Plugins/BasePlugin.h b/Plugins/BasePlugin.h
new file mode 100644
index 0000000..266d5d8
--- /dev/null
+++ b/Plugins/BasePlugin.h
@@ -0,0 +1,41 @@
+/*
+    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 BASEPLUGIN_H_
+#define BASEPLUGIN_H_
+
+#include <cassert>
+#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;
+};
+
+#endif /* BASEPLUGIN_H_ */
diff --git a/Plugins/HelloWorldPlugin.h b/Plugins/HelloWorldPlugin.h
new file mode 100644
index 0000000..ae0ff64
--- /dev/null
+++ b/Plugins/HelloWorldPlugin.h
@@ -0,0 +1,50 @@
+/*
+ * LocatePlugin.h
+ *
+ *  Created on: 01.01.2011
+ *      Author: dennis
+ */
+
+#ifndef HELLOWORLDPLUGIN_H_
+#define HELLOWORLDPLUGIN_H_
+
+#include <sstream>
+
+#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";
+        }
+        content << "Number of hints: " << routeParameters.hints.size() << "\n";
+        for(unsigned i = 0; i < routeParameters.hints.size(); ++i) {
+            content << "  [" << i << "] " << routeParameters.hints[i] << "\n";
+        }
+        content << "</pre>";
+		reply.content.append(content.str());
+		reply.content.append("</body></html>");
+	}
+};
+
+#endif /* HELLOWORLDPLUGIN_H_ */
diff --git a/Plugins/LocatePlugin.h b/Plugins/LocatePlugin.h
new file mode 100644
index 0000000..f1c7d60
--- /dev/null
+++ b/Plugins/LocatePlugin.h
@@ -0,0 +1,113 @@
+/*
+    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 LOCATEPLUGIN_H_
+#define LOCATEPLUGIN_H_
+
+#include "BasePlugin.h"
+#include "RouteParameters.h"
+#include "../DataStructures/NodeInformationHelpDesk.h"
+#include "../Server/DataStructures/QueryObjectsStorage.h"
+#include "../Util/StringUtil.h"
+
+#include <fstream>
+
+/*
+ * 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);
+            return;
+        }
+
+        //query to helpdesk
+        _Coordinate result;
+        std::string tmp;
+        //json
+
+//        JSONParameter = routeParameters.options.Find("jsonp");
+        if("" != routeParameters.jsonpParameter) {
+            reply.content += routeParameters.jsonpParameter;
+            reply.content += "(";
+        }
+        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
+            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\"";
+        }
+        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;
+    }
+
+    NodeInformationHelpDesk * nodeHelpDesk;
+};
+
+#endif /* LOCATEPLUGIN_H_ */
diff --git a/Plugins/NearestPlugin.h b/Plugins/NearestPlugin.h
new file mode 100644
index 0000000..c10230f
--- /dev/null
+++ b/Plugins/NearestPlugin.h
@@ -0,0 +1,124 @@
+/*
+    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_
+
+#include <fstream>
+
+#include "BasePlugin.h"
+#include "RouteParameters.h"
+
+#include "../Server/DataStructures/QueryObjectsStorage.h"
+
+#include "../DataStructures/NodeInformationHelpDesk.h"
+#include "../Util/StringUtil.h"
+
+/*
+ * 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);
+            return;
+        }
+
+        //query to helpdesk
+        PhantomNode result;
+        nodeHelpDesk->FindPhantomNodeForCoordinate(routeParameters.coordinates[0], result, routeParameters.zoomLevel);
+
+        std::string tmp;
+        //json
+
+        if("" != routeParameters.jsonpParameter) {
+            reply.content += routeParameters.jsonpParameter;
+            reply.content += "(";
+        }
+
+        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.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;
+    }
+
+    NodeInformationHelpDesk * nodeHelpDesk;
+    HashTable<std::string, unsigned> descriptorTable;
+    std::vector<std::string> & names;
+};
+
+#endif /* NearestPlugin_H_ */
diff --git a/Plugins/PluginMapFactory.h b/Plugins/PluginMapFactory.h
new file mode 100644
index 0000000..9027b18
--- /dev/null
+++ b/Plugins/PluginMapFactory.h
@@ -0,0 +1,34 @@
+/*
+    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
new file mode 100644
index 0000000..f0c1054
--- /dev/null
+++ b/Plugins/RawRouteData.h
@@ -0,0 +1,45 @@
+/*
+    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
new file mode 100644
index 0000000..a718f96
--- /dev/null
+++ b/Plugins/RouteParameters.h
@@ -0,0 +1,107 @@
+/*
+    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
new file mode 100644
index 0000000..33c606e
--- /dev/null
+++ b/Plugins/TimestampPlugin.h
@@ -0,0 +1,75 @@
+/*
+    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 TIMESTAMPPLUGIN_H_
+#define TIMESTAMPPLUGIN_H_
+
+#include <cassert>
+
+#include "BasePlugin.h"
+#include "RouteParameters.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;
+
+        //json
+        if("" != routeParameters.jsonpParameter) {
+            reply.content += routeParameters.jsonpParameter;
+            reply.content += "(";
+        }
+
+        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;
+    }
+private:
+    QueryObjectsStorage * objects;
+};
+
+#endif /* TIMESTAMPPLUGIN_H_ */
diff --git a/Plugins/ViaRoutePlugin.h b/Plugins/ViaRoutePlugin.h
new file mode 100644
index 0000000..8249d99
--- /dev/null
+++ b/Plugins/ViaRoutePlugin.h
@@ -0,0 +1,224 @@
+/*
+    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_ */
diff --git a/README.TXT b/README.TXT
new file mode 100644
index 0000000..a8ae177
--- /dev/null
+++ b/README.TXT
@@ -0,0 +1,27 @@
+For instructions on how to compile and run OSRM, please consult the Wiki at
+
+https://github.com/DennisOSRM/Project-OSRM/wiki
+
+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
+
+ at inproceedings{luxen-vetter-2011,
+ author = {Luxen, Dennis and Vetter, Christian},
+ title = {Real-time routing with OpenStreetMap data},
+ booktitle = {Proceedings of the 19th ACM SIGSPATIAL International Conference on Advances in Geographic Information Systems},
+ series = {GIS '11},
+ year = {2011},
+ isbn = {978-1-4503-1031-4},
+ location = {Chicago, Illinois},
+ pages = {513--516},
+ numpages = {4},
+ url = {http://doi.acm.org/10.1145/2093973.2094062},
+ doi = {10.1145/2093973.2094062},
+ acmid = {2094062},
+ publisher = {ACM},
+ address = {New York, NY, USA},
+} 
+
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..ccbb0cb
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,211 @@
+require 'OSM/StreamParser'
+require 'socket'
+require 'digest/sha1'
+require 'cucumber/rake/task'
+require 'sys/proctable'
+
+BUILD_FOLDER = 'build'
+DATA_FOLDER = 'sandbox'
+PROFILE = 'bicycle'
+OSRM_PORT = 5000
+PROFILES_FOLDER = '../profiles'
+
+Cucumber::Rake::Task.new do |t|
+  t.cucumber_opts = %w{--format pretty}
+end
+
+areas = {
+  :kbh => { :country => 'denmark', :bbox => 'top=55.6972 left=12.5222 right=12.624 bottom=55.6376' },
+  :frd => { :country => 'denmark', :bbox => 'top=55.7007 left=12.4765 bottom=55.6576 right=12.5698' },
+  :regh => { :country => 'denmark', :bbox => 'top=56.164 left=11.792 bottom=55.403 right=12.731' },
+  :denmark => { :country => 'denmark', :bbox => nil },
+  :skaane => { :country => 'sweden', :bbox => 'top=56.55 left=12.4 bottom=55.3 right=14.6' }
+}
+
+
+
+osm_data_area_name = ARGV[1] ? ARGV[1].to_s.to_sym : :kbh
+raise "Unknown data area." unless areas[osm_data_area_name]
+osm_data_country = areas[osm_data_area_name][:country]
+osm_data_area_bbox = areas[osm_data_area_name][:bbox]
+
+
+task osm_data_area_name.to_sym {}   #define empty task to prevent rake from whining. will break if area has same name as a task
+
+
+def each_process name, &block
+  Sys::ProcTable.ps do |process|
+    if process.comm.strip == name.strip && process.state != 'zombie'
+      yield process.pid.to_i, process.state.strip
+    end
+  end
+end
+
+def up?
+  find_pid('osrm-routed') != nil
+end
+
+def find_pid name
+  each_process(name) { |pid,state| return pid.to_i }
+  return nil
+end
+
+def wait_for_shutdown name
+  timeout = 10
+  (timeout*10).times do
+    return if find_pid(name) == nil
+    sleep 0.1
+  end
+  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"
+  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
+  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"
+  raise "Error while downloading data." unless system "curl http://download.geofabrik.de/europe/#{osm_data_country}-latest.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
+  if osm_data_area_bbox
+    puts "Cropping and converting to protobuffer..."
+    raise "Error while cropping data." unless system "osmosis --read-pbf file=#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true"
+  end
+end
+
+desc "Crop OSM data"
+task :crop do
+  if osm_data_area_bbox
+    raise "Error while cropping data." unless system "osmosis --read-pbf file=#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true"
+  end
+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
+end
+
+desc "Extract OSM data."
+task :extract => :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/#{PROFILE}.lua"
+  end
+end
+
+desc "Prepare OSM data."
+task :prepare => :setup 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"
+  end
+end
+
+desc "Delete preprocessing files."
+task :clean do
+  File.delete *Dir.glob("#{DATA_FOLDER}/*.osrm")
+  File.delete *Dir.glob("#{DATA_FOLDER}/*.osrm.*")
+end
+
+desc "Run all cucumber test"
+task :test do
+  system "cucumber"
+  puts
+end
+
+desc "Run the routing server in the terminal. Press Ctrl-C to stop."
+task :run => :setup do
+  Dir.chdir DATA_FOLDER do
+    write_server_ini osm_data_area_name
+    system "../#{BUILD_FOLDER}/osrm-routed"
+  end
+end
+
+desc "Launch the routing server in the background. Use rake:down to stop it."
+task :up => :setup 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")
+    timeout = 5
+    (timeout*10).times do
+      begin
+        socket = TCPSocket.new('localhost', OSRM_PORT)
+        socket.puts 'ping'
+      rescue Errno::ECONNREFUSED
+        sleep 0.1
+      end
+    end
+  end
+end
+
+desc "Stop the routing server."
+task :down do
+  pid = find_pid 'osrm-routed'
+  if pid
+    Process.kill 'TERM', pid
+  else
+    puts "Already down."
+  end 
+end
+
+desc "Kill all osrm-extract, osrm-prepare and osrm-routed processes."
+task :kill do
+  each_process('osrm-routed') { |pid,state| Process.kill 'KILL', pid }
+  each_process('osrm-prepare') { |pid,state| Process.kill 'KILL', pid }
+  each_process('osrm-extract') { |pid,state| Process.kill 'KILL', pid }
+  wait_for_shutdown 'osrm-routed'
+  wait_for_shutdown 'osrm-prepare'
+  wait_for_shutdown 'osrm-extract'  
+end
+
+desc "Get PIDs of all osrm-extract, osrm-prepare and osrm-routed processes."
+task :pid do
+  each_process 'osrm-routed' do |pid,state|
+    puts "#{pid}\t#{state}"
+  end
+end
+
+desc "Stop, reprocess and restart."
+task :update => [:down,:process,:up] do
+end
diff --git a/RoutingAlgorithms/AlternativePathRouting.h b/RoutingAlgorithms/AlternativePathRouting.h
new file mode 100644
index 0000000..4cd256b
--- /dev/null
+++ b/RoutingAlgorithms/AlternativePathRouting.h
@@ -0,0 +1,535 @@
+/*
+    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 ALTERNATIVEROUTES_H_
+#define ALTERNATIVEROUTES_H_
+
+#include <boost/unordered_map.hpp>
+#include <vector>
+#include <cmath>
+
+#include "BasicRoutingInterface.h"
+
+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.
+
+template<class QueryDataT>
+class AlternativeRouting : private BasicRoutingInterface<QueryDataT> {
+    typedef BasicRoutingInterface<QueryDataT> super;
+    typedef typename QueryDataT::Graph SearchGraph;
+    typedef typename QueryDataT::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) {}
+        NodeID node;
+        int length;
+        int sharing;
+        bool operator<(const RankedCandidateNode& other) const {
+            return (2*length + sharing) < (2*other.length + other.sharing);
+        }
+    };
+
+    const SearchGraph * search_graph;
+
+public:
+
+    AlternativeRouting(QueryDataT & qd) : super(qd), search_graph(qd.graph) { }
+
+    ~AlternativeRouting() {}
+
+    void operator()(const PhantomNodes & phantomNodePair, RawRouteData & rawRouteData) {
+        if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX() || phantomNodePair.PhantomNodesHaveEqualLocation()) {
+            rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
+            return;
+        }
+
+        std::vector<NodeID> alternativePath;
+        std::vector<NodeID> viaNodeCandidates;
+        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);
+            }
+            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);
+            }
+        }
+        sort_unique_resize(viaNodeCandidates);
+
+        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;
+
+        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];
+        	}
+        }
+
+        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);
+            }
+        }
+
+        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));
+            }
+        }
+        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)) {
+                // select first admissable
+                selectedViaNode = 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;
+        } 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;
+        }
+    }
+
+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);
+    }
+
+    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)
+            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);
+                    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);
+                    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 {
+                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;
+    }
+
+    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();
+            return;
+        }
+
+        search_space.push_back(std::make_pair(_forward_heap.GetData( node ).parent, node));
+
+        if(_reverse_heap.WasInserted(node) ){
+            searchSpaceIntersection.push_back(node);
+
+            const int newDistance = _reverse_heap.GetKey(node) + distance;
+            if(newDistance < *upper_bound_to_shortest_path_distance ){
+                if(newDistance>=0 ) {
+                    *middle_node = node;
+                    *upper_bound_to_shortest_path_distance = newDistance;
+                }
+            }
+        }
+
+        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) {
+
+                const NodeID to = search_graph->GetTarget(edge);
+                const int edgeWeight = 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 );
+
+                }
+                //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
+                }
+            }
+        }
+    }
+
+    //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;
+
+        *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);
+        }
+
+        if(INT_MAX == upperBoundFor_s_v_Path)
+            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;
+
+        *lengthOfViaPath = upperBoundFor_s_v_Path + upperBoundFor_v_t_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);
+
+        NodeID s_P = *s_v_middle, t_P = *v_t_middle;
+        if(UINT_MAX == s_P) {
+            return false;
+        }
+
+        if(UINT_MAX == 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;
+                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)
+                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));
+                }
+            } else {
+                // edge is not a shortcut, set the start node for T-Test to end of edge.
+                unpackedUntilDistance += currentEdgeData.distance;
+                s_P = viaPathEdge.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;
+                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)
+                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));
+                }
+            } else {
+                // edge is not a shortcut, set the start node for T-Test to end of edge.
+                unpackedUntilDistance += currentEdgeData.distance;
+                t_P = viaPathEdge.second;
+            }
+        }
+
+        lengthOfPathT_Test_Path += unpackedUntilDistance;
+        //Run actual T-Test query and compare if distances equal.
+        super::_queryData.InitializeOrClearThirdThreadLocalStorage();
+
+        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);
+            }
+            if (backward_heap3.Size() > 0) {
+                super::RoutingStep(backward_heap3, forward_heap3, &middle, &_upperBound, offset, false);
+            }
+        }
+        return (_upperBound <= lengthOfPathT_Test_Path);
+    }
+};
+
+#endif /* ALTERNATIVEROUTES_H_ */
diff --git a/RoutingAlgorithms/BasicRoutingInterface.h b/RoutingAlgorithms/BasicRoutingInterface.h
new file mode 100644
index 0000000..caef97a
--- /dev/null
+++ b/RoutingAlgorithms/BasicRoutingInterface.h
@@ -0,0 +1,225 @@
+/*
+    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"
+#include "../Util/ContainerUtils.h"
+
+#include <boost/noncopyable.hpp>
+
+#include <cassert>
+#include <climits>
+
+#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 {
+                }
+            }
+        }
+
+        if(distance-edgeBasedOffset > *_upperbound){
+            _forwardHeap.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) {
+                        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) {
+
+                const NodeID to = _queryData.graph->GetTarget(edge);
+                const int edgeWeight = data.distance;
+
+                assert( edgeWeight > 0 );
+                const int toDistance = distance + edgeWeight;
+
+                //New Node discovered -> Add to Heap + Node Info Storage
+                if ( !_forwardHeap.WasInserted( to ) ) {
+                    _forwardHeap.Insert( to, toDistance, node );
+                }
+                //Found a shorter Path -> Update distance
+                else if ( toDistance < _forwardHeap.GetKey( to ) ) {
+                    _forwardHeap.GetData( to ).parent = node;
+                    _forwardHeap.DecreaseKey( to, toDistance );
+                    //new parent
+                }
+            }
+        }
+    }
+
+    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]));
+        }
+
+        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;
+                }
+            }
+
+            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;
+                    }
+                }
+            }
+            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(_PathData(ed.id, _queryData.nodeHelpDesk->getNameIndexFromEdgeID(ed.id), _queryData.nodeHelpDesk->getTurnInstructionFromEdgeID(ed.id), ed.distance) );
+            }
+        }
+    }
+
+    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));
+
+        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;
+                }
+            }
+
+            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;
+                    }
+                }
+            }
+            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 );
+            }
+        }
+        unpackedPath.push_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);
+        }
+
+        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);
+        }
+    }
+};
+
+
+#endif /* BASICROUTINGINTERFACE_H_ */
diff --git a/RoutingAlgorithms/ShortestPathRouting.h b/RoutingAlgorithms/ShortestPathRouting.h
new file mode 100644
index 0000000..472e7dd
--- /dev/null
+++ b/RoutingAlgorithms/ShortestPathRouting.h
@@ -0,0 +1,201 @@
+/*
+    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 SHORTESTPATHROUTING_H_
+#define SHORTESTPATHROUTING_H_
+
+#include "BasicRoutingInterface.h"
+
+template<class QueryDataT>
+class ShortestPathRouting : public BasicRoutingInterface<QueryDataT>{
+    typedef BasicRoutingInterface<QueryDataT> super;
+    typedef typename QueryDataT::QueryHeap QueryHeap;
+public:
+    ShortestPathRouting( QueryDataT & qd) : super(qd) {}
+
+    ~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;
+            }
+        }
+        int distance1 = 0;
+        int distance2 = 0;
+
+        bool searchFrom1stStartNode = true;
+        bool searchFrom2ndStartNode = true;
+        NodeID middle1 = UINT_MAX;
+        NodeID middle2 = UINT_MAX;
+        std::vector<NodeID> packedPath1;
+        std::vector<NodeID> packedPath2;
+
+        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);
+
+        //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;
+
+            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);
+                }
+                if(0 < reverse_heap1.Size() ){
+                    super::RoutingStep(reverse_heap1, forward_heap1, &middle1, &_localUpperbound1, reverse_offset, 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(0 < reverse_heap2.Size()){
+                        super::RoutingStep(reverse_heap2, forward_heap2, &middle2, &_localUpperbound2, reverse_offset, false);
+                    }
+                }
+            }
+
+            //No path found for both target nodes?
+            if((INT_MAX == _localUpperbound1) && (INT_MAX == _localUpperbound2)) {
+                rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
+                return;
+            }
+            if(UINT_MAX == middle1) {
+                searchFrom1stStartNode = false;
+            }
+            if(UINT_MAX == middle2) {
+                searchFrom2ndStartNode = false;
+            }
+
+            //Was at most one of the two paths not found?
+            assert(!(INT_MAX == distance1 && INT_MAX == distance2));
+
+            //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);
+            }
+
+            if(INT_MAX != _localUpperbound2) {
+                super::RetrievePackedPathFromHeap(forward_heap2, reverse_heap2, middle2, temporaryPackedPath2);
+            }
+
+            //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(0 == temporaryPackedPath2.size()) {
+                temporaryPackedPath2.insert(temporaryPackedPath2.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
+                _localUpperbound2 = _localUpperbound1;
+            }
+
+            assert(0 < temporaryPackedPath1.size() && 0 < temporaryPackedPath2.size());
+
+            //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;
+                    }
+                } else  {
+                    //packed paths 1 and 2 may need to switch.
+                    if(*(packedPath1.end()-1) != *(temporaryPackedPath1.begin())) {
+                        packedPath1.swap(packedPath2);
+                        std::swap(distance1, distance2);
+                    }
+                }
+            }
+            packedPath1.insert(packedPath1.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
+            packedPath2.insert(packedPath2.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
+
+            if( (packedPath1.back() == packedPath2.back()) && phantomNodePair.targetPhantom.isBidirected() ) {
+
+                NodeID lastNodeID = packedPath2.back();
+                searchFrom1stStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode+1);
+                searchFrom2ndStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode);
+            }
+
+            distance1 += _localUpperbound1;
+            distance2 += _localUpperbound2;
+        }
+
+        if(distance1 > distance2){
+            std::swap(packedPath1, packedPath2);
+        }
+        remove_consecutive_duplicates_from_vector(packedPath1);
+        super::UnpackPath(packedPath1, rawRouteData.computedShortestPath);
+        rawRouteData.lengthOfShortestPath = std::min(distance1, distance2);
+        return;
+    }
+};
+
+#endif /* SHORTESTPATHROUTING_H_ */
diff --git a/Server/APIGrammar.h b/Server/APIGrammar.h
new file mode 100644
index 0000000..3b87941
--- /dev/null
+++ b/Server/APIGrammar.h
@@ -0,0 +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.
+
+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 APIGRAMMAR_H_
+#define APIGRAMMAR_H_
+
+#include <boost/bind.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+
+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) {
+        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)];
+        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)];
+        location    = (-qi::lit('&')) >> qi::lit("loc")          >> '=' >> (qi::double_ >> qi::lit(',') >> qi::double_)[boost::bind(&HandlerT::addCoordinate, handler, ::_1)];
+        hint        = (-qi::lit('&')) >> qi::lit("hint")         >> '=' >> stringwithDot[boost::bind(&HandlerT::addHint, handler, ::_1)];
+        language    = (-qi::lit('&')) >> qi::lit("hl")           >> '=' >> string[boost::bind(&HandlerT::setLanguage, handler, ::_1)];
+        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_.-"));
+    }
+    qi::rule<Iterator> api_call, query;
+    qi::rule<Iterator, std::string()> service, zoom, output, string, jsonp, checksum, location, hint,
+                                      stringwithDot, language, instruction, geometry,
+                                      cmp, alt_route, old_API;
+
+    HandlerT * handler;
+};
+
+
+#endif /* APIGRAMMAR_H_ */
diff --git a/Server/BasicDatastructures.h b/Server/BasicDatastructures.h
new file mode 100644
index 0000000..366abae
--- /dev/null
+++ b/Server/BasicDatastructures.h
@@ -0,0 +1,157 @@
+/*
+    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.h b/Server/Connection.h
new file mode 100644
index 0000000..5dd4b79
--- /dev/null
+++ b/Server/Connection.h
@@ -0,0 +1,181 @@
+/*
+    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 CONNECTION_H
+#define CONNECTION_H
+
+#include <vector>
+
+#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 "BasicDatastructures.h"
+#include "RequestHandler.h"
+#include "RequestParser.h"
+
+#include "zlib.h"
+
+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;
+};
+
+} // namespace http
+
+#endif // CONNECTION_H
diff --git a/Server/DataStructures/QueryObjectsStorage.cpp b/Server/DataStructures/QueryObjectsStorage.cpp
new file mode 100644
index 0000000..df15f53
--- /dev/null
+++ b/Server/DataStructures/QueryObjectsStorage.cpp
@@ -0,0 +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.
+
+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
new file mode 100644
index 0000000..be8bba0
--- /dev/null
+++ b/Server/DataStructures/QueryObjectsStorage.h
@@ -0,0 +1,47 @@
+/*
+    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/RequestHandler.h b/Server/RequestHandler.h
new file mode 100644
index 0000000..9dd0e28
--- /dev/null
+++ b/Server/RequestHandler.h
@@ -0,0 +1,117 @@
+/*
+    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 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;
+
+                ltime=time(NULL);
+                Tm=localtime(&ltime);
+
+                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 );
+            }
+
+            RouteParameters routeParameters;
+            APIGrammar<std::string::iterator, RouteParameters> apiParser(&routeParameters);
+
+            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;
+        }
+    };
+
+    void RegisterPlugin(BasePlugin * plugin) {
+        std::cout << "[handler] registering plugin " << plugin->GetDescriptor() << std::endl;
+        pluginMap.Add(plugin->GetDescriptor(), _pluginCount);
+        _pluginVector.push_back(plugin);
+        ++_pluginCount;
+    }
+
+private:
+    HashTable<std::string, unsigned> pluginMap;
+    std::vector<BasePlugin *> _pluginVector;
+    unsigned _pluginCount;
+};
+} // namespace http
+
+#endif // REQUEST_HANDLER_H
diff --git a/Server/RequestParser.h b/Server/RequestParser.h
new file mode 100644
index 0000000..7e33f9e
--- /dev/null
+++ b/Server/RequestParser.h
@@ -0,0 +1,291 @@
+/*
+    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 REQUEST_PARSER_H
+#define REQUEST_PARSER_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_;
+
+    Header header;
+};
+
+} // namespace http
+
+#endif // REQUEST_PARSER_H
diff --git a/Server/Server.h b/Server/Server.h
new file mode 100644
index 0000000..db525f5
--- /dev/null
+++ b/Server/Server.h
@@ -0,0 +1,88 @@
+/*
+    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 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 "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;
+};
+
+}   // namespace http
+
+#endif // SERVER_H
diff --git a/Server/ServerConfiguration.h b/Server/ServerConfiguration.h
new file mode 100644
index 0000000..0393a7f
--- /dev/null
+++ b/Server/ServerConfiguration.h
@@ -0,0 +1,28 @@
+/*
+    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
new file mode 100644
index 0000000..966dc92
--- /dev/null
+++ b/Server/ServerFactory.h
@@ -0,0 +1,84 @@
+/*
+    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.
+
+ Created on: 26.11.2010
+ Author: dennis
+
+ */
+
+#ifndef SERVERFACTORY_H_
+#define SERVERFACTORY_H_
+
+#include <zlib.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");
+		}
+
+		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;
+	}
+
+	static Server * CreateServer(const char * iniFile) {
+		ServerConfiguration serverConfig(iniFile);
+		return CreateServer(serverConfig);
+	}
+};
+
+#endif /* SERVERFACTORY_H_ */
diff --git a/Tools/.gitignore b/Tools/.gitignore
new file mode 100644
index 0000000..5c86178
--- /dev/null
+++ b/Tools/.gitignore
@@ -0,0 +1 @@
+/osrm-component
diff --git a/Tools/componentAnalysis.cpp b/Tools/componentAnalysis.cpp
new file mode 100644
index 0000000..64790aa
--- /dev/null
+++ b/Tools/componentAnalysis.cpp
@@ -0,0 +1,102 @@
+/*
+    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/Util/Azimuth.h b/Util/Azimuth.h
new file mode 100644
index 0000000..166f55f
--- /dev/null
+++ b/Util/Azimuth.h
@@ -0,0 +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.
+
+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 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)
+                return "N";
+            if(heading > 22.5 && heading <= 67.5)
+                return "NE";
+            if(heading > 67.5 && heading <= 112.5)
+                return "E";
+            if(heading > 112.5 && heading <= 157.5)
+                return "SE";
+            return "S";
+        }
+        if(heading > 202.5 && heading <= 247.5)
+            return "SW";
+        if(heading > 247.5 && heading <= 292.5)
+            return "W";
+        if(heading > 292.5 && heading <= 337.5)
+            return "NW";
+        return "N";
+    }
+};
+
+
+#endif /* AZIMUTH_H_ */
diff --git a/Util/BaseConfiguration.h b/Util/BaseConfiguration.h
new file mode 100644
index 0000000..69bc61f
--- /dev/null
+++ b/Util/BaseConfiguration.h
@@ -0,0 +1,107 @@
+/*
+    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/ContainerUtils.h b/Util/ContainerUtils.h
new file mode 100644
index 0000000..215e988
--- /dev/null
+++ b/Util/ContainerUtils.h
@@ -0,0 +1,34 @@
+/*
+ * ContainerUtils.h
+ *
+ *  Created on: 02.02.2013
+ *      Author: dennis
+ */
+
+#ifndef CONTAINERUTILS_H_
+#define CONTAINERUTILS_H_
+
+#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_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();
+    vector.resize(number_of_unique_elements);
+}
+
+
+#endif /* CONTAINERUTILS_H_ */
diff --git a/Util/GraphLoader.h b/Util/GraphLoader.h
new file mode 100644
index 0000000..5dc50f8
--- /dev/null
+++ b/Util/GraphLoader.h
@@ -0,0 +1,377 @@
+/*
+    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 GRAPHLOADER_H
+#define GRAPHLOADER_H
+
+#include "../DataStructures/ImportNode.h"
+#include "../DataStructures/ImportEdge.h"
+#include "../DataStructures/NodeCoords.h"
+#include "../DataStructures/Restriction.h"
+#include "../typedefs.h"
+
+#include <boost/assert.hpp>
+#include <boost/unordered_map.hpp>
+
+#include <cassert>
+#include <cmath>
+
+#include <algorithm>
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+#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 &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);
+    }
+
+    //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");
+            continue;
+
+        }
+        inputRestrictions[i].fromNode = intNodeID->second;
+
+        intNodeID = ext2IntNodeMap.find(inputRestrictions[i].viaNode);
+        if( intNodeID == ext2IntNodeMap.end()) {
+            DEBUG("Unmapped via node of restriction");
+            continue;
+        }
+        inputRestrictions[i].viaNode = intNodeID->second;
+
+        intNodeID = ext2IntNodeMap.find(inputRestrictions[i].toNode);
+        if( intNodeID == ext2IntNodeMap.end()) {
+            DEBUG("Unmapped to node of restriction");
+            continue;
+        }
+        inputRestrictions[i].toNode = intNodeID->second;
+    }
+
+    edgeList.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" );
+        BOOST_ASSERT_MSG(weight > 0, "loaded null weight");
+        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; }
+
+        assert(type >= 0);
+
+        //         translate the external NodeIDs to internal IDs
+        ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(source);
+        if( ext2IntNodeMap.find(source) == ext2IntNodeMap.end()) {
+#ifndef NDEBUG
+            WARN(" unresolved source NodeID: " << source );
+#endif
+            continue;
+        }
+        source = intNodeID->second;
+        intNodeID = ext2IntNodeMap.find(target);
+        if(ext2IntNodeMap.find(target) == ext2IntNodeMap.end()) {
+#ifndef NDEBUG
+            WARN("unresolved target NodeID : " << target );
+#endif
+            continue;
+        }
+        target = intNodeID->second;
+        BOOST_ASSERT_MSG(source != UINT_MAX && target != UINT_MAX,
+            "nonexisting source or 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);
+    }
+    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();
+                }
+            } 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");
+    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;
+
+        if(source == UINT_MAX || target == UINT_MAX) { ERR("nonexisting source or target" ); }
+
+        EdgeT inputEdge(source, target, 0, weight, forward, backward, type );
+        edgeList.push_back(inputEdge);
+    }
+    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);
+
+        bool forward = true;
+        bool backward = true;
+        if (dir == 1) backward = false;
+        if (dir == 2) forward = false;
+        if (dir == 3) {backward = true; forward = true;}
+
+        if(weight == 0) { ERR("loaded null length edge"); }
+
+        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);
+    }
+    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));
+
+    return numberOfNodes;
+}
+
+#endif // GRAPHLOADER_H
diff --git a/Util/InputFileUtil.h b/Util/InputFileUtil.h
new file mode 100644
index 0000000..685d92f
--- /dev/null
+++ b/Util/InputFileUtil.h
@@ -0,0 +1,46 @@
+/*
+    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
new file mode 100644
index 0000000..a3a23a7
--- /dev/null
+++ b/Util/LinuxStackTrace.h
@@ -0,0 +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.
+
+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
new file mode 100644
index 0000000..3793d8b
--- /dev/null
+++ b/Util/LuaUtil.h
@@ -0,0 +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.
+ */
+
+#ifndef LUAUTIL_H_
+#define LUAUTIL_H_
+
+extern "C" {
+    #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;
+}
+
+// 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);
+}
+
+// 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() );
+}
+
+#endif /* LUAUTIL_H_ */
diff --git a/Util/MachineInfo.h b/Util/MachineInfo.h
new file mode 100644
index 0000000..7c0f31c
--- /dev/null
+++ b/Util/MachineInfo.h
@@ -0,0 +1,86 @@
+/*
+ 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 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
+};
+
+//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;
+    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) );
+    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/OpenMPWrapper.h b/Util/OpenMPWrapper.h
new file mode 100644
index 0000000..232dcbd
--- /dev/null
+++ b/Util/OpenMPWrapper.h
@@ -0,0 +1,34 @@
+/*
+    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/StringUtil.h b/Util/StringUtil.h
new file mode 100644
index 0000000..b09ac16
--- /dev/null
+++ b/Util/StringUtil.h
@@ -0,0 +1,163 @@
+/*
+    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 STRINGUTIL_H_
+#define STRINGUTIL_H_
+
+#include <string>
+#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"
+
+// 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;
+        value = -value;
+    }
+    buffer += length - 1;
+    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 );
+        value /= 10;
+        if ( value == 0 ) break;
+        buffer--;
+    }
+    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();
+    std::back_insert_iterator<std::string> sink(output);
+    boost::spirit::karma::generate(sink, boost::spirit::karma::int_, value);
+}
+
+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 void doubleToString(const double value, std::string & output){
+    output.clear();
+    std::back_insert_iterator<std::string> sink(output);
+    boost::spirit::karma::generate(sink, boost::spirit::karma::double_, 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 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 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 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 += " ";
+}
+
+inline void replaceAll(std::string &s, const std::string &sub, const std::string &other) {
+	boost::replace_all(s, sub, other);
+}
+
+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 std::string originals[] = {"&", "\"",  "<",  ">", "'", "[", "]", "\\"};
+static std::string entities[] = {"&", """, "<", ">", "'", "&91;", "&93;", " \" };
+
+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]);
+    }
+    return result;
+}
+
+inline std::string HTMLDeEntitize( std::string & result) {
+    for(unsigned i = 0; i < sizeof(originals)/sizeof(std::string); ++i) {
+        replaceAll(result, entities[i], originals[i]);
+    }
+    return result;
+}
+
+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;
+}
+
+#endif /* STRINGUTIL_H_ */
diff --git a/cmake/FindLuabind.cmake b/cmake/FindLuabind.cmake
new file mode 100644
index 0000000..39b3250
--- /dev/null
+++ b/cmake/FindLuabind.cmake
@@ -0,0 +1,75 @@
+# Locate Luabind library
+# This module defines
+#  LUABIND_FOUND, if false, do not try to link to Luabind
+#  LUABIND_LIBRARIES
+#  LUABIND_INCLUDE_DIR, where to find luabind.hpp
+#
+# Note that the expected include convention is
+#  #include <luabind/luabind.hpp>
+# and not
+#  #include <luabind.hpp>
+
+IF( NOT LUABIND_FIND_QUIETLY )
+    MESSAGE(STATUS "Looking for Luabind...")
+ENDIF()
+
+FIND_PATH(LUABIND_INCLUDE_DIR luabind.hpp
+  HINTS
+  $ENV{LUABIND_DIR}
+  PATH_SUFFIXES luabind include/luabind include
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /opt/local # DarwinPorts
+  /opt
+)
+
+FIND_LIBRARY(LUABIND_LIBRARY
+  NAMES luabind
+  HINTS
+  $ENV{LUABIND_DIR}
+  PATH_SUFFIXES lib64 lib
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /opt/local
+  /opt
+)
+
+FIND_LIBRARY(LUABIND_LIBRARY_DBG
+  NAMES luabindd
+  HINTS
+  $ENV{LUABIND_DIR}
+  PATH_SUFFIXES lib64 lib
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /opt/local
+  /opt
+)
+
+IF(LUABIND_LIBRARY)
+    SET( LUABIND_LIBRARIES "${LUABIND_LIBRARY}" CACHE STRING "Luabind Libraries")
+ENDIF(LUABIND_LIBRARY)
+
+INCLUDE(FindPackageHandleStandardArgs)
+# handle the QUIETLY and REQUIRED arguments and set LUABIND_FOUND to TRUE if
+# all listed variables are TRUE
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Luabind  DEFAULT_MSG  LUABIND_LIBRARIES LUABIND_INCLUDE_DIR)
+
+IF( NOT LUABIND_FIND_QUIETLY )
+    IF( LUABIND_FOUND )
+        MESSAGE(STATUS "Found Luabind: ${LUABIND_LIBRARY}" )
+    ENDIF()
+    IF( LUABIND_LIBRARY_DBG )
+        MESSAGE(STATUS "Luabind debug library availible: ${LUABIND_LIBRARY_DBG}")
+    ENDIF()
+ENDIF()
+
+MARK_AS_ADVANCED(LUABIND_INCLUDE_DIR LUABIND_LIBRARIES LUABIND_LIBRARY LUABIND_LIBRARY_DBG) 
diff --git a/cmake/FindOSMPBF.cmake b/cmake/FindOSMPBF.cmake
new file mode 100644
index 0000000..78b1d9d
--- /dev/null
+++ b/cmake/FindOSMPBF.cmake
@@ -0,0 +1,54 @@
+# Locate OSMPBF library
+# This module defines
+#  OSMPBF_FOUND, if false, do not try to link to OSMPBF
+#  OSMPBF_LIBRARIES
+#  OSMPBF_INCLUDE_DIR, where to find OSMPBF.hpp
+#
+# Note that the expected include convention is
+#  #include <osmpbf/osmpbf.h>
+# and not
+#  #include <osmpbf.h>
+
+IF( NOT OSMPBF_FIND_QUIETLY )
+    MESSAGE(STATUS "Looking for OSMPBF...")
+ENDIF()
+
+FIND_PATH(OSMPBF_INCLUDE_DIR osmpbf.h
+  HINTS
+  $ENV{OSMPBF_DIR}
+  PATH_SUFFIXES OSMPBF include/osmpbf include
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /opt/local # DarwinPorts
+  /opt
+)
+
+FIND_LIBRARY(OSMPBF_LIBRARY
+  NAMES osmpbf
+  HINTS
+  $ENV{OSMPBF_DIR}
+  PATH_SUFFIXES lib64 lib
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /opt/local
+  /opt
+)
+
+INCLUDE(FindPackageHandleStandardArgs)
+# handle the QUIETLY and REQUIRED arguments and set OSMPBF_FOUND to TRUE if
+# all listed variables are TRUE
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(OSMPBF  DEFAULT_MSG  OSMPBF_LIBRARY OSMPBF_INCLUDE_DIR)
+
+IF( NOT OSMPBF_FIND_QUIETLY )
+    IF( OSMPBF_FOUND )
+        MESSAGE(STATUS "Found OSMPBF: ${OSMPBF_LIBRARY}" )
+    ENDIF()
+ENDIF()
+
+#MARK_AS_ADVANCED(OSMPBF_INCLUDE_DIR OSMPBF_LIBRARIES OSMPBF_LIBRARY OSMPBF_LIBRARY_DBG) 
diff --git a/cmake/FindSTXXL.cmake b/cmake/FindSTXXL.cmake
new file mode 100644
index 0000000..52d508c
--- /dev/null
+++ b/cmake/FindSTXXL.cmake
@@ -0,0 +1,51 @@
+# Locate STXXL library
+# This module defines
+#  STXXL_FOUND, if false, do not try to link to libstxxl
+#  STXXL_LIBRARY
+#  STXXL_INCLUDE_DIR, where to find stxxl.h
+#
+
+
+IF( NOT STXXL_FIND_QUIETLY )
+    MESSAGE(STATUS "Looking for STXXL...")
+ENDIF()
+
+FIND_PATH(STXXL_INCLUDE_DIR stxxl.h
+  HINTS
+  $ENV{STXXL_DIR}
+  PATH_SUFFIXES stxxl include/stxxl/stxxl include/stxxl include
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /opt/local # DarwinPorts
+  /opt
+)
+
+FIND_LIBRARY(STXXL_LIBRARY
+  NAMES stxxl
+  HINTS
+  $ENV{STXXL_DIR}
+  PATH_SUFFIXES lib64 lib
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /opt/local
+  /opt
+)
+
+INCLUDE(FindPackageHandleStandardArgs)
+# handle the QUIETLY and REQUIRED arguments and set STXXL_FOUND to TRUE if
+# all listed variables are TRUE
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(STXXL  DEFAULT_MSG  STXXL_LIBRARY STXXL_INCLUDE_DIR)
+
+IF( NOT STXXL_FIND_QUIETLY )
+    IF( STXXL_FOUND )
+        MESSAGE(STATUS "Found STXXL: ${STXXL_LIBRARY}" )
+    ENDIF()
+ENDIF()
+
+MARK_AS_ADVANCED(STXXL_INCLUDE_DIR STXXL_LIBRARY) 
diff --git a/cmake/GetGitRevisionDescription.cmake b/cmake/GetGitRevisionDescription.cmake
new file mode 100644
index 0000000..1bf0230
--- /dev/null
+++ b/cmake/GetGitRevisionDescription.cmake
@@ -0,0 +1,123 @@
+# - Returns a version string from Git
+#
+# These functions force a re-configure on each git commit so that you can
+# trust the values of the variables in your build system.
+#
+#  get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
+#
+# Returns the refspec and sha hash of the current head revision
+#
+#  git_describe(<var> [<additional arguments to git describe> ...])
+#
+# Returns the results of git describe on the source tree, and adjusting
+# the output so that it tests false if an error occurs.
+#
+#  git_get_exact_tag(<var> [<additional arguments to git describe> ...])
+#
+# Returns the results of git describe --exact-match on the source tree,
+# and adjusting the output so that it tests false if there was no exact
+# matching tag.
+#
+# 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)
+
+if(__get_git_revision_description)
+	return()
+endif()
+set(__get_git_revision_description YES)
+
+# We must run the following at "include" time, not at function call time,
+# to find the path to this module rather than the path to a calling list file
+get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
+
+function(get_git_head_revision _refspecvar _hashvar)
+	set(GIT_PARENT_DIR "${CMAKE_SOURCE_DIR}")
+	set(GIT_DIR "${GIT_PARENT_DIR}/.git")
+	while(NOT EXISTS "${GIT_DIR}")	# .git dir not found, search parent directories
+		set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
+		get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
+		if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
+			# We have reached the root directory, we are not in git
+			set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
+			set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
+			return()
+		endif()
+		set(GIT_DIR "${GIT_PARENT_DIR}/.git")
+	endwhile()
+	set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
+	if(NOT EXISTS "${GIT_DATA}")
+		file(MAKE_DIRECTORY "${GIT_DATA}")
+	endif()
+
+	if(NOT EXISTS "${GIT_DIR}/HEAD")
+		return()
+	endif()
+	set(HEAD_FILE "${GIT_DATA}/HEAD")
+	configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
+
+	configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
+		"${GIT_DATA}/grabRef.cmake"
+		@ONLY)
+	include("${GIT_DATA}/grabRef.cmake")
+
+	set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
+	set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
+endfunction()
+
+function(git_describe _var)
+	if(NOT GIT_FOUND)
+		find_package(Git QUIET)
+	endif()
+	get_git_head_revision(refspec hash)
+	if(NOT GIT_FOUND)
+		set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
+		return()
+	endif()
+	if(NOT hash)
+		set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
+		return()
+	endif()
+
+	# TODO sanitize
+	#if((${ARGN}" MATCHES "&&") OR
+	#	(ARGN MATCHES "||") OR
+	#	(ARGN MATCHES "\\;"))
+	#	message("Please report the following error to the project!")
+	#	message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
+	#endif()
+
+	#message(STATUS "Arguments to execute_process: ${ARGN}")
+
+	execute_process(COMMAND
+		"${GIT_EXECUTABLE}"
+		describe
+		${hash}
+		${ARGN}
+		WORKING_DIRECTORY
+		"${CMAKE_SOURCE_DIR}"
+		RESULT_VARIABLE
+		res
+		OUTPUT_VARIABLE
+		out
+		ERROR_QUIET
+		OUTPUT_STRIP_TRAILING_WHITESPACE)
+	if(NOT res EQUAL 0)
+		set(out "${out}-${res}-NOTFOUND")
+	endif()
+
+	set(${_var} "${out}" PARENT_SCOPE)
+endfunction()
+
+function(git_get_exact_tag _var)
+	git_describe(out --exact-match ${ARGN})
+	set(${_var} "${out}" PARENT_SCOPE)
+endfunction()
diff --git a/config/cucumber.yml b/config/cucumber.yml
new file mode 100644
index 0000000..5a9fa4e
--- /dev/null
+++ b/config/cucumber.yml
@@ -0,0 +1,5 @@
+# config/cucumber.yml
+##YAML Template
+---
+default: --require features
+verify: --require features --tags ~@todo --tag ~@stress -f progress
\ No newline at end of file
diff --git a/contractor.ini b/contractor.ini
new file mode 100644
index 0000000..4da33c7
--- /dev/null
+++ b/contractor.ini
@@ -0,0 +1 @@
+Threads = 4
diff --git a/createHierarchy.cpp b/createHierarchy.cpp
new file mode 100644
index 0000000..5e6343d
--- /dev/null
+++ b/createHierarchy.cpp
@@ -0,0 +1,276 @@
+/*
+    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/extractor.cpp b/extractor.cpp
new file mode 100644
index 0000000..3beeef5
--- /dev/null
+++ b/extractor.cpp
@@ -0,0 +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.
+
+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 "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/MachineInfo.h"
+#include "Util/OpenMPWrapper.h"
+#include "Util/StringUtil.h"
+#include "typedefs.h"
+
+#include <cstdlib>
+#include <iostream>
+#include <fstream>
+
+#include <string>
+
+typedef BaseConfiguration ExtractorConfiguration;
+
+ExtractorCallbacks * extractCallBacks;
+
+int main (int argc, char *argv[]) {
+    double earliestTime = get_timestamp();
+
+    if(argc < 2) {
+        ERR("usage: \n" << argv[0] << " <file.osm/.osm.bz2/.osm.pbf> [<profile.lua>]");
+    }
+
+    /*** Setup Scripting Environment ***/
+    ScriptingEnvironment scriptingEnvironment((argc > 2 ? argv[2] : "profile.lua"));
+
+    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;
+        }
+    }
+    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");
+        }
+    }
+
+    unsigned amountOfRAM = 1;
+    unsigned installedRAM = GetPhysicalmemory();
+    if(installedRAM < 2048264) {
+        WARN("Machine has less than 2GB RAM.");
+    }
+
+    StringMap stringMap;
+    ExtractionContainers externalMemory;
+
+    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(!parser->ReadHeader()) {
+        ERR("Parser not initialized!");
+    }
+    INFO("Parsing in progress..");
+    double time = get_timestamp();
+    parser->Parse();
+    INFO("Parsing finished after " << get_timestamp() - time << " seconds");
+
+    externalMemory.PrepareData(outputFileName, restrictionsFileName, amountOfRAM);
+
+    stringMap.clear();
+    delete parser;
+    delete extractCallBacks;
+    INFO("finished after " << get_timestamp() - earliestTime << "s");
+
+    std::cout << "\nRun:\n"
+                   "./osrm-prepare " << outputFileName << " " << restrictionsFileName << std::endl;
+    return 0;
+}
diff --git a/extractor.ini b/extractor.ini
new file mode 100644
index 0000000..8dd11de
--- /dev/null
+++ b/extractor.ini
@@ -0,0 +1,2 @@
+Memory = 2
+Threads = 10
diff --git a/features/bicycle/access.feature b/features/bicycle/access.feature
new file mode 100644
index 0000000..cb1fc0d
--- /dev/null
+++ b/features/bicycle/access.feature
@@ -0,0 +1,173 @@
+ at routing @bicycle @access
+Feature: Bike - Access tags on ways
+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      |       |
+
+    @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              |      |       |
+
+    @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 - 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 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 - 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
new file mode 100644
index 0000000..eba808d
--- /dev/null
+++ b/features/bicycle/access_node.feature
@@ -0,0 +1,64 @@
+ at routing @bicycle @access
+Feature: Bike - Access tags on nodes
+Reference: http://wiki.openstreetmap.org/wiki/Key:access
+
+	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 - 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 - 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
diff --git a/features/bicycle/area.feature b/features/bicycle/area.feature
new file mode 100644
index 0000000..541f026
--- /dev/null
+++ b/features/bicycle/area.feature
@@ -0,0 +1,103 @@
+ at 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 |
+
+		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 |
+
+		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: 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       |
\ No newline at end of file
diff --git a/features/bicycle/barrier.feature b/features/bicycle/barrier.feature
new file mode 100644
index 0000000..ed387c1
--- /dev/null
+++ b/features/bicycle/barrier.feature
@@ -0,0 +1,39 @@
+ at routing @bicycle @barrier
+Feature: Barriers
+
+	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 - 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
new file mode 100644
index 0000000..f260294
--- /dev/null
+++ b/features/bicycle/cycleway.feature
@@ -0,0 +1,81 @@
+ at routing @bicycle @cycleway
+Feature: Bike - Cycle tracks/lanes
+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     |
+
+	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 - 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 | 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     |
diff --git a/features/bicycle/destination.feature b/features/bicycle/destination.feature
new file mode 100644
index 0000000..b3f8b5b
--- /dev/null
+++ b/features/bicycle/destination.feature
@@ -0,0 +1,77 @@
+ at 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 |
+
+		And the ways
+		 | nodes | access      |
+		 | ab    |             |
+		 | bcd   | 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      |
+		
+	Scenario: Bike - Destination only street
+		Given the node map
+		 | a |   |   |   | e |
+		 |   | b | c | d |   |
+		 |   |   |   |   |   |
+		 | x |   |   |   | y |
+
+		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,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 - 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       |
\ No newline at end of file
diff --git a/features/bicycle/ferry.feature b/features/bicycle/ferry.feature
new file mode 100644
index 0000000..5d67df7
--- /dev/null
+++ b/features/bicycle/ferry.feature
@@ -0,0 +1,63 @@
+ at 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 |
diff --git a/features/bicycle/maxspeed.feature b/features/bicycle/maxspeed.feature
new file mode 100644
index 0000000..9924f55
--- /dev/null
+++ b/features/bicycle/maxspeed.feature
@@ -0,0 +1,70 @@
+ at routing @maxspeed @bicycle
+Feature: Bike - Max speed restrictions
+
+	Background: Use specific speeds
+		Given the profile "bicycle"
+
+	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 - 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%  |
+
+    @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: 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       |
+
+		When I route I should get
+		 | from | to | route | time    |
+		 | a    | b  | ab    | 24s ~5% |
+		 | b    | c  | bc    | 24s ~5% |
+
+     Scenario: Bike - Forward/backward maxspeed
+        Given the shortcuts
+ 		 | 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 |
+     	 |          |                  |                   | bike  | bike   |
+     	 | 10       |                  |                   | run   | run    |
+     	 |          | 10               |                   | run   | bike   |
+     	 |          |                  | 10                | bike  | run    |
+     	 | 1        | 10               |                   | run   | snail  |
+     	 | 1        |                  | 10                | snail | run    |
+     	 | 1        | 5                | 10                | walk  | run    |
diff --git a/features/bicycle/mode.feature b/features/bicycle/mode.feature
new file mode 100644
index 0000000..c24af46
--- /dev/null
+++ b/features/bicycle/mode.feature
@@ -0,0 +1,89 @@
+ at routing @bicycle @mode
+Feature: Bike - Mode flag
+
+	Background:
+		Given the profile "bicycle"
+    
+    @todo
+    Scenario: Bike - Mode when using a ferry
+    	Given the node map
+    	 | a | b |   |
+    	 |   | c | d |
+
+    	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      |
+
+     @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 |        |
+
+     	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 |
+
+     	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      |
+
+     @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    |      |
+
+     	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
new file mode 100644
index 0000000..d8a1ecf
--- /dev/null
+++ b/features/bicycle/names.feature
@@ -0,0 +1,49 @@
+ at 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 |
+
+		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} |
+
+  	@area @names @todo
+  	Scenario: Bike - name on streets overlapping an area
+  		Given the node map
+  		 | x | a | b | y |
+  		 |   | d | c |   |
+
+  		And the ways
+  		 | nodes | highway     | area |
+  		 | xaby  | residential |      |
+  		 | abcda | residential | yes  |
+
+  		When I route I should get
+  		 | from | to | route |
+  		 | x    | y  | xaby  |
+  		 | y    | x  | xaby  |
diff --git a/features/bicycle/oneway.feature b/features/bicycle/oneway.feature
new file mode 100644
index 0000000..ee0d713
--- /dev/null
+++ b/features/bicycle/oneway.feature
@@ -0,0 +1,128 @@
+ at 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
diff --git a/features/bicycle/pushing.feature b/features/bicycle/pushing.feature
new file mode 100644
index 0000000..13590d0
--- /dev/null
+++ b/features/bicycle/pushing.feature
@@ -0,0 +1,124 @@
+ at routing @bicycle @pushing
+Feature: Bike - Accessability of different way types
+
+	Background:
+		Given the profile "bicycle"
+        Given the shortcuts
+		 | 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 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  |
+
+ 	@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 |
+
+ 		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  |
+    
+    @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  |
+
+    @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     |       |
+        
+    @roundabout
+  	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 |
+
+  		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                  |
+
+  	@todo
+    Scenario: Bike - Instructions when pushing bike on footway/pedestrian, etc.
+   		Given the node map
+   		 | a | b |   |
+   		 |   | c | d |
+
+   		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
diff --git a/features/bicycle/ref.feature b/features/bicycle/ref.feature
new file mode 100644
index 0000000..da15859
--- /dev/null
+++ b/features/bicycle/ref.feature
@@ -0,0 +1,41 @@
+ at 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 |
diff --git a/features/bicycle/restrictions.feature b/features/bicycle/restrictions.feature
new file mode 100644
index 0000000..2d5fa40
--- /dev/null
+++ b/features/bicycle/restrictions.feature
@@ -0,0 +1,289 @@
+ at 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 |
diff --git a/features/bicycle/stop_area.feature b/features/bicycle/stop_area.feature
new file mode 100644
index 0000000..7113808
--- /dev/null
+++ b/features/bicycle/stop_area.feature
@@ -0,0 +1,37 @@
+ at 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
+
+	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     |
+
+	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         |
+
+  		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/ |
diff --git a/features/bicycle/train.feature b/features/bicycle/train.feature
new file mode 100644
index 0000000..a4af362
--- /dev/null
+++ b/features/bicycle/train.feature
@@ -0,0 +1,39 @@
+ at routing @bicycle @train
+Feature: Bike - Handle ferry routes
+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     |
+
+	@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
new file mode 100644
index 0000000..157cbf2
--- /dev/null
+++ b/features/bicycle/turn_penalty.feature
@@ -0,0 +1,33 @@
+ at routing @bicycle @turn_penalty
+Feature: Turn Penalties
+
+    Background:
+        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 |
+
+        And the ways
+         | 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
diff --git a/features/bicycle/way.feature b/features/bicycle/way.feature
new file mode 100644
index 0000000..f5ad5bb
--- /dev/null
+++ b/features/bicycle/way.feature
@@ -0,0 +1,41 @@
+ at routing @bicycle @way
+Feature: Bike - Accessability of different way types
+
+	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 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
new file mode 100644
index 0000000..97e61c5
--- /dev/null
+++ b/features/car/access.feature
@@ -0,0 +1,144 @@
+ at routing @car @access
+Feature: Car - Restricted 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       |       |
+
+	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 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 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 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 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
new file mode 100644
index 0000000..9d37d35
--- /dev/null
+++ b/features/car/barrier.feature
@@ -0,0 +1,38 @@
+ at routing @car @barrier
+Feature: Car - Barriers
+
+	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 - 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
new file mode 100644
index 0000000..43059e1
--- /dev/null
+++ b/features/car/destination.feature
@@ -0,0 +1,77 @@
+ at 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 |
+
+		And the ways
+		 | nodes | access      |
+		 | ab    |             |
+		 | bcd   | 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      |
+		
+	Scenario: Car - Destination only street
+		Given the node map
+		 | a |   |   |   | e |
+		 |   | b | c | d |   |
+		 |   |   |   |   |   |
+		 | x |   |   |   | y |
+
+		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,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 - 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       |
\ No newline at end of file
diff --git a/features/car/ferry.feature b/features/car/ferry.feature
new file mode 100644
index 0000000..3182c75
--- /dev/null
+++ b/features/car/ferry.feature
@@ -0,0 +1,30 @@
+ at 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     |
+
+
diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature
new file mode 100644
index 0000000..3e09a0a
--- /dev/null
+++ b/features/car/maxspeed.feature
@@ -0,0 +1,54 @@
+ at routing @maxspeed @car
+Feature: Car - Max speed restrictions
+
+	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   |
diff --git a/features/car/names.feature b/features/car/names.feature
new file mode 100644
index 0000000..d7d98b7
--- /dev/null
+++ b/features/car/names.feature
@@ -0,0 +1,33 @@
+ at 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 |
+
+		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
new file mode 100644
index 0000000..b181085
--- /dev/null
+++ b/features/car/oneway.feature
@@ -0,0 +1,73 @@
+ at routing @car @oneway
+Feature: Car - Oneway streets
+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    |       |
+
+	Scenario: Car - Simple reverse oneway
+		Then routability should be
+		 | highway | oneway | forw | backw |
+		 | primary | -1     |      | 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 - 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 - 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
diff --git a/features/car/permissive.feature b/features/car/permissive.feature
new file mode 100644
index 0000000..e69de29
diff --git a/features/car/restrictions.feature b/features/car/restrictions.feature
new file mode 100644
index 0000000..91ba298
--- /dev/null
+++ b/features/car/restrictions.feature
@@ -0,0 +1,251 @@
+ at 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 |
diff --git a/features/car/shuttle_train.feature b/features/car/shuttle_train.feature
new file mode 100644
index 0000000..e58ffa2
--- /dev/null
+++ b/features/car/shuttle_train.feature
@@ -0,0 +1,33 @@
+ at routing @car @shuttle_train
+Feature: Car - Handle ferryshuttle train routes
+
+	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		  |
+
+
diff --git a/features/car/way.feature b/features/car/way.feature
new file mode 100644
index 0000000..8ca62a5
--- /dev/null
+++ b/features/car/way.feature
@@ -0,0 +1,33 @@
+ at routing @car @way
+Feature: Car - Accessability of different way types
+
+	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
diff --git a/features/foot/maxspeed.feature b/features/foot/maxspeed.feature
new file mode 100644
index 0000000..8a3571a
--- /dev/null
+++ b/features/foot/maxspeed.feature
@@ -0,0 +1,20 @@
+ at routing @maxspeed @foot
+Feature: Foot - Ignore max speed restrictions
+
+Background: Use specific speeds
+	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% |
diff --git a/features/foot/oneway.feature b/features/foot/oneway.feature
new file mode 100644
index 0000000..e1c96e3
--- /dev/null
+++ b/features/foot/oneway.feature
@@ -0,0 +1,60 @@
+ at routing @foot @oneway
+Feature: Foot - Oneway streets
+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     |
+
+	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     |
\ No newline at end of file
diff --git a/features/foot/way.feature b/features/foot/way.feature
new file mode 100644
index 0000000..e18d9f8
--- /dev/null
+++ b/features/foot/way.feature
@@ -0,0 +1,32 @@
+ at routing @foot @way
+Feature: Foot - Accessability of different way types
+
+	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
diff --git a/features/investigate/weird.feature b/features/investigate/weird.feature
new file mode 100644
index 0000000..f84a075
--- /dev/null
+++ b/features/investigate/weird.feature
@@ -0,0 +1,42 @@
+ 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/nearest/pick.feature b/features/nearest/pick.feature
new file mode 100644
index 0000000..f3bd76d
--- /dev/null
+++ b/features/nearest/pick.feature
@@ -0,0 +1,56 @@
+ at 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
diff --git a/features/nearest/projection.feature b/features/nearest/projection.feature
new file mode 100644
index 0000000..f33a19f
--- /dev/null
+++ b/features/nearest/projection.feature
@@ -0,0 +1,105 @@
+ at 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 |
+
+		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   |
+
+ 	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   |
+
+  	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    |
+
+  		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/step_definitions/data.rb b/features/step_definitions/data.rb
new file mode 100644
index 0000000..1e021b6
--- /dev/null
+++ b/features/step_definitions/data.rb
@@ -0,0 +1,121 @@
+Given /^the profile "([^"]*)"$/ do |profile|
+  set_profile profile
+end
+
+Given /^a grid size of (\d+) meters$/ do |meters|
+  set_grid_size meters
+end
+
+Given /^the shortcuts$/ do |table|
+  table.hashes.each do |row|
+    shortcuts_hash[ row['key'] ] = row['value']
+  end
+end
+
+Given /^the node map$/ do |table|
+  table.raw.each_with_index do |row,ri|
+    row.each_with_index do |name,ci|
+      unless name.empty?
+        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)
+        else
+            raise "*** duplicate node '#{name}'" if location_hash[name]
+            add_location name, *table_coord_to_lonlat(ci,ri)
+        end
+      end
+    end
+  end
+end
+
+Given /^the node locations$/ do |table|
+  table.hashes.each do |row|
+    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 
+    else
+        add_location name, row['lon'].to_f, row['lat'].to_f 
+    end
+  end
+end
+
+Given /^the nodes$/ do |table|
+  table.hashes.each do |row|
+    name = row.delete 'node'
+    node = find_node_by_name(name)
+    raise "*** unknown node '#{c}'" unless node
+    node << row
+  end
+end
+
+Given /^the ways$/ do |table|
+  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|
+      raise "*** ways can only use names a-z, '#{name}'" unless c.match /[a-z]/
+      node = find_node_by_name(c)
+      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'] == "''")
+      tags['name'] = ''
+    elsif row['name'] == '' || row['name'] == '(nil)'
+      tags.delete 'name'
+    else
+      tags['name'] = row['name']
+    end
+    
+    way << tags
+    osm_db << way
+    name_way_hash[nodes] = way
+  end
+end
+
+Given /^the relations$/ do |table|
+  table.hashes.each do |row|
+    relation = OSM::Relation.new make_osm_id, OSM_USER, OSM_TIMESTAMP
+    row.each_pair do |key,value|
+      if key =~ /^node:(.*)/
+        value.split(',').map { |v| v.strip }.each do |node_name|
+          raise "***invalid relation node member '#{node_name}', must be single character" unless node_name.size == 1
+          node = find_node_by_name(node_name)
+          raise "*** unknown relation node member '#{node_name}'" unless node
+          relation << OSM::Member.new( 'node', node.id, $1 )
+        end
+      elsif key =~ /^way:(.*)/
+        value.split(',').map { |v| v.strip }.each do |way_name|
+          way = find_way_by_name(way_name)
+          raise "*** unknown relation way member '#{way_name}'" unless way
+          relation << OSM::Member.new( 'way', way.id, $1 )
+        end
+      elsif key =~ /^(.*):(.*)/
+        raise "*** unknown relation member type '#{$1}', must be either 'node' or 'way'"
+      else
+        relation << { key => value }
+      end
+    end
+    relation.uid = OSM_UID
+    osm_db << relation
+  end
+end
+
+Given /^the defaults$/ do
+end
+
diff --git a/features/step_definitions/nearest.rb b/features/step_definitions/nearest.rb
new file mode 100644
index 0000000..3b65792
--- /dev/null
+++ b/features/step_definitions/nearest.rb
@@ -0,0 +1,51 @@
+When /^I request nearest I should get$/ do |table|
+  reprocess
+  actual = []
+  OSRMLauncher.new 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
+
+      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}")
+      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'
+          if FuzzyMatch.match_location coord, out_node
+            got[key] = row[key]
+          else
+            row[key] = "#{row[key]} [#{out_node.lat},#{out_node.lon}]"
+            ok = false
+          end
+        end
+      end
+      
+      unless ok
+        failed = { :attempt => 'nearest', :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|
+  ok = true
+  n.to_i.times do
+    ok = false unless step "I request nearest I should get", table
+  end
+  ok
+end
\ No newline at end of file
diff --git a/features/step_definitions/requests.rb b/features/step_definitions/requests.rb
new file mode 100644
index 0000000..d965b1a
--- /dev/null
+++ b/features/step_definitions/requests.rb
@@ -0,0 +1,45 @@
+When /^I request \/(.*)$/ do |path|
+  reprocess
+  OSRMLauncher.new do
+    @response = request_path path
+  end
+end
+
+Then /^I should get a response/ do
+  @response.code.should == "200"
+  @response.body.should_not == nil
+  @response.body.should_not == ''
+end
+
+Then /^response should be valid JSON$/ do
+  @json = JSON.parse @response.body
+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 /^response should be a well-formed route$/ do
+  step "response should be well-formed"
+  @json['status_message'].class.should == String
+  @json['route_summary'].class.should == Hash
+  @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
+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
diff --git a/features/step_definitions/routability.rb b/features/step_definitions/routability.rb
new file mode 100644
index 0000000..078428a
--- /dev/null
+++ b/features/step_definitions/routability.rb
@@ -0,0 +1,51 @@
+Then /^routability should be$/ do |table|
+  build_ways_from_table table
+  reprocess
+  actual = []
+  if table.headers&["forw","backw","bothw"] == []
+    raise "*** routability tabel must contain either 'forw', 'backw' or 'bothw' column"
+  end
+  OSRMLauncher.new do
+    table.hashes.each_with_index do |row,i|
+      got = 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
+        end
+      end
+      log_fail row,got,attempts if got != row
+      actual << got
+    end
+  end
+  table.routing_diff! actual
+end
diff --git a/features/step_definitions/routing.rb b/features/step_definitions/routing.rb
new file mode 100644
index 0000000..13c8b6a
--- /dev/null
+++ b/features/step_definitions/routing.rb
@@ -0,0 +1,113 @@
+When /^I route I should get$/ do |table|
+  reprocess
+  actual = []
+  OSRMLauncher.new 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
+          waypoints << node
+        end
+        got = {'waypoints' => row['waypoints'] }
+      else
+        raise "*** no waypoints"
+      end
+        
+      params = {}
+      row.each_pair do |k,v|
+        if k =~ /param:(.*)/
+          if v=='(nil)'
+            params[$1]=nil
+          elsif v!=nil
+            params[$1]=v
+          end
+          got[k]=v
+        end
+      end
+            
+      response = request_route(waypoints, params)
+      if response.code == "200" && response.body.empty? == false
+        json = JSON.parse response.body
+        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']
+        end
+      end
+      
+      if table.headers.include? 'start'
+        got['start'] = instructions ? json['route_summary']['start_point'] : nil
+      end
+      if table.headers.include? 'end'
+        got['end'] = instructions ? json['route_summary']['end_point'] : nil
+      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
+        end
+        if table.headers.include? 'turns'
+          got['turns'] = turns
+        end
+        if table.headers.include? 'modes'
+          got['modes'] = modes
+        end
+        if table.headers.include? '#'   # comment column
+          got['#'] = row['#']           # copy value so it always match
+        end
+      end
+      
+      ok = true
+      row.keys.each do |key|
+        if FuzzyMatch.match got[key], row[key]
+          got[key] = row[key]
+        else
+          ok = false
+        end
+      end
+      
+      unless ok
+        failed = { :attempt => 'route', :query => @query, :response => response }
+        log_fail row,got,[failed]
+      end
+      
+      actual << got
+    end
+  end
+  table.routing_diff! actual
+end
+
+When /^I route (\d+) times I should get$/ do |n,table|
+  ok = true
+  n.to_i.times do
+    ok = false unless step "I route I should get", table
+  end
+  ok
+end
diff --git a/features/step_definitions/timestamp.rb b/features/step_definitions/timestamp.rb
new file mode 100644
index 0000000..53d4083
--- /dev/null
+++ b/features/step_definitions/timestamp.rb
@@ -0,0 +1,7 @@
+Then /^I should get a valid timestamp/ do
+  step "I should get a response"
+  step "response should be valid JSON"
+  step "response should be well-formed"
+  @json['timestamp'].class.should == String
+  @json['timestamp'].should == OSM_TIMESTAMP
+end
diff --git a/features/stress/launch.feature b/features/stress/launch.feature
new file mode 100644
index 0000000..2463782
--- /dev/null
+++ b/features/stress/launch.feature
@@ -0,0 +1,58 @@
+ at 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   |
+
+ 		When I route 100 times I should get
+ 		 | from | to | route |
+ 		 | 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
new file mode 100644
index 0000000..63350d5
--- /dev/null
+++ b/features/support/config.rb
@@ -0,0 +1,30 @@
+def profile
+  @profile ||= reset_profile
+end
+
+def reset_profile
+  @profile = nil
+  set_profile DEFAULT_SPEEDPROFILE
+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
new file mode 100644
index 0000000..78465be
--- /dev/null
+++ b/features/support/cucumber.rb
@@ -0,0 +1,76 @@
+#monkey patch cucumber table class to reorder output.
+#we always want failed rows to be shown right below the expected row.
+
+class Cucumber::Ast::Table
+  def routing_diff!(other_table, options={})
+    options = {:missing_row => true, :surplus_row => true, :missing_col => true, :surplus_col => false}.merge(options)
+
+    other_table = ensure_table(other_table)
+    other_table.convert_headers!
+    other_table.convert_columns!
+    ensure_green!
+
+    convert_headers!
+    convert_columns!
+
+    original_width = cell_matrix[0].length
+    other_table_cell_matrix = pad!(other_table.cell_matrix)
+    padded_width = cell_matrix[0].length
+
+    missing_col = cell_matrix[0].detect{|cell| cell.status == :undefined}
+    surplus_col = padded_width > original_width
+
+    require_diff_lcs
+    cell_matrix.extend(Diff::LCS)
+    changes = cell_matrix.diff(other_table_cell_matrix).flatten
+    
+    inserted = 0
+    missing  = 0
+
+    row_indices = Array.new(other_table_cell_matrix.length) {|n| n}
+
+    last_change = nil
+    missing_row_pos = nil
+    insert_row_pos  = nil
+
+    changes.each do |change|
+      if(change.action == '-')
+        missing_row_pos = change.position + inserted
+        cell_matrix[missing_row_pos].each{|cell| cell.status = :undefined}
+        row_indices.insert(missing_row_pos, nil)
+        missing += 1
+      else # '+'
+        #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)
+        row_indices[insert_row_pos] = nil
+        inspect_rows(cell_matrix[missing_row_pos], inserted_row) if last_change && last_change.action == '-'
+        inserted += 1
+      end
+      last_change = change
+    end
+
+    other_table_cell_matrix.each_with_index do |other_row, i|
+      row_index = row_indices.index(i)
+      row = cell_matrix[row_index] if row_index
+      if row
+        (original_width..padded_width).each do |col_index|
+          surplus_cell = other_row[col_index]
+          row[col_index].value = surplus_cell.value if row[col_index]
+        end
+      end
+    end
+
+    clear_cache!
+    should_raise = 
+    missing_row_pos && options[:missing_row] ||
+    insert_row_pos  && options[:surplus_row] ||
+    missing_col     && options[:missing_col] ||
+    surplus_col     && options[:surplus_col]
+    raise Different.new(self) if should_raise
+  end
+end
\ No newline at end of file
diff --git a/features/support/data.rb b/features/support/data.rb
new file mode 100644
index 0000000..dbb0398
--- /dev/null
+++ b/features/support/data.rb
@@ -0,0 +1,271 @@
+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
+end
+
+def sanitized_scenario_title
+  @sanitized_scenario_title ||= @scenario_title.gsub /[^0-9A-Za-z.\-]/, '_'
+end
+
+def set_grid_size meters
+  #the constant is calculated (with BigDecimal as: 1.0/(DEG_TO_RAD*EARTH_RADIUS_IN_METERS
+  #see ApproximateDistance() in ExtractorStructs.h
+  #it's only accurate when measuring along the equator, or going exactly north-south
+  @zoom = meters.to_f*0.8990679362704610899694577444566908445396483347536032203503E-5
+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.uid = OSM_UID
+    node2.uid = OSM_UID
+    node3.uid = OSM_UID
+    node4.uid = OSM_UID
+    node5.uid = OSM_UID
+    node1 << { :name => "a#{ri}" }
+    node2 << { :name => "b#{ri}" }
+    node3 << { :name => "c#{ri}" }
+    node4 << { :name => "d#{ri}" }
+    node5 << { :name => "e#{ri}" }
+
+    osm_db << node1
+    osm_db << node2
+    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
+    way << node1
+    way << node2
+    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 =~ /^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\/(.*)/
+        if v=='(nil)'
+          node_tags.delete k
+        else
+          node_tags[$1] = v
+        end
+      else
+        if v=='(nil)'
+          way_tags.delete k
+        else
+          way_tags[k] = v
+        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]
+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
+end
+
+def add_location name,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
+end
+
+def find_way_by_name s
+  name_way_hash[s.to_s] || name_way_hash[s.to_s.reverse]
+end
+
+def reset_data
+  Dir.chdir TEST_FOLDER do
+    #clear_log
+    #clear_data_files
+  end
+  reset_profile
+  reset_osm
+  @fingerprint = nil
+end
+
+def make_osm_id
+  @osm_id = @osm_id+1
+end
+
+def reset_osm
+  osm_db.clear
+  name_node_hash.clear
+  location_hash.clear
+  name_way_hash.clear
+  @osm_str = nil
+  @osm_hash = nil
+  @osm_id = 0
+end
+
+def clear_data_files
+  File.delete *Dir.glob("#{DATA_FOLDER}/test.*")
+end
+
+def clear_log
+  File.delete *Dir.glob("*.log")
+end
+
+def osm_db
+  @osm_db ||= OSM::Database.new
+end
+
+def name_node_hash
+  @name_node_hash ||= {}
+end
+
+def location_hash
+  @location_hash ||= {}
+end
+
+def name_way_hash
+  @name_way_hash ||= {}
+end
+
+def osm_str
+  return @osm_str if @osm_str
+  @osm_str = ''
+  doc = Builder::XmlMarkup.new :indent => 2, :target => @osm_str
+  doc.instruct!
+  osm_db.to_xml doc, OSM_GENERATOR
+  @osm_str
+end
+
+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}"
+  unless File.exist?("#{@osm_file}.osm")
+    File.open( "#{@osm_file}.osm", 'w') {|f| f.write(osm_str) }
+  end
+end
+
+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}"
+      raise OsmosisError.new $?, "osmosis exited with code #{$?.exitstatus}"
+    end
+    log '', :preprocess
+  end
+end
+
+def extracted?
+  File.exist?("#{@osm_file}.osrm") &&
+  File.exist?("#{@osm_file}.osrm.names") &&
+  File.exist?("#{@osm_file}.osrm.restrictions")
+end
+
+def prepared?
+  File.exist?("#{@osm_file}.osrm.hsgr")
+end
+
+def write_timestamp
+  File.open( "#{@osm_file}.osrm.timestamp", 'w') {|f| f.write(OSM_TIMESTAMP) }
+end
+
+def reprocess
+  use_pbf = true
+  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
+    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
+    end
+    log_preprocess_done
+    write_server_ini
+  end
+end
diff --git a/features/support/env.rb b/features/support/env.rb
new file mode 100644
index 0000000..13a0b0c
--- /dev/null
+++ b/features/support/env.rb
@@ -0,0 +1,18 @@
+require 'rspec/expectations'
+
+DEFAULT_PORT = 5000
+
+
+puts "Ruby version #{RUBY_VERSION}"
+unless RUBY_VERSION =~ /^1.9/
+  raise "*** Please upgrade to Ruby 1.9.x to run the OSRM cucumber tests"
+end
+
+if ENV["OSRM_PORT"]
+  OSRM_PORT = ENV["OSRM_PORT"].to_i
+  puts "Port set to #{OSRM_PORT}"
+else
+  OSRM_PORT = DEFAULT_PORT
+  puts "Using default port #{OSRM_PORT}"
+end
+
diff --git a/features/support/exceptions.rb b/features/support/exceptions.rb
new file mode 100644
index 0000000..22a6868
--- /dev/null
+++ b/features/support/exceptions.rb
@@ -0,0 +1,49 @@
+
+class OSRMError < StandardError
+  attr_accessor :msg, :code, :process
+
+  def initialize process, code, msg, log, lines
+    @process = process
+    @code = code
+    @msg = msg
+    @lines = lines
+    @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"
+    end
+  end
+end
+
+class OsmosisError < OSRMError
+  def initialize code, msg
+    super 'osmosis', code, msg, PREPROCESS_LOG_FILE, 40
+  end
+end
+
+class ExtractError < OSRMError
+  def initialize code, msg
+    super 'osrm-extract', code, msg, PREPROCESS_LOG_FILE, 3
+  end
+end
+
+class PrepareError < OSRMError
+  def initialize code, msg
+    super 'osrm-prepare', code, msg, PREPROCESS_LOG_FILE, 3
+  end
+end
+
+class RoutedError < OSRMError
+  def initialize msg
+    super 'osrm-routed', nil, msg, OSRM_ROUTED_LOG_FILE, 3
+  end
+end
diff --git a/features/support/file.rb b/features/support/file.rb
new file mode 100644
index 0000000..cd8fd14
--- /dev/null
+++ b/features/support/file.rb
@@ -0,0 +1,22 @@
+class File
+  
+  #read last n lines of a file. useful for getting last part of a big log file.
+  def tail(n)
+    buffer = 1024
+    idx = (size - buffer).abs
+    chunks = []
+    lines = 0
+
+    begin
+      seek(idx)
+      chunk = read(buffer)
+      lines += chunk.count("\n")
+      chunks.unshift chunk
+      idx -= buffer
+    end while lines < ( n + 1 ) && pos != 0
+
+    tail_of_file = chunks.join('')
+    ary = tail_of_file.split(/\n/)
+    lines_to_return = ary[ ary.size - n, ary.size - 1 ]
+  end
+end
\ No newline at end of file
diff --git a/features/support/fuzzy.rb b/features/support/fuzzy.rb
new file mode 100644
index 0000000..611d1ef
--- /dev/null
+++ b/features/support/fuzzy.rb
@@ -0,0 +1,30 @@
+
+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
+    elsif want.match /(.*)\s+\+\-(.+)$/    #absolute range: 100 +-5
+      margin = $2.to_f
+      from = $1.to_f-margin
+      to = $1.to_f+margin
+      return got.to_f >= from && got.to_f <= to
+    elsif want =~ /^\/(.*)\/$/             #regex: /a,b,.*/
+      return got =~ /#{$1}/
+    else
+      return false
+    end      
+  end
+  
+  def self.match_location got, want
+    match( got[0], "#{want.lat} ~0.0025%" ) &&
+    match( got[1], "#{want.lon} ~0.0025%" )
+  end
+  
+end
+
diff --git a/features/support/hash.rb b/features/support/hash.rb
new file mode 100644
index 0000000..e37a6f2
--- /dev/null
+++ b/features/support/hash.rb
@@ -0,0 +1,47 @@
+require 'digest/sha1'
+
+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|
+      while !io.eof
+        buf = io.readpartial 1024
+        hash.update buf
+      end
+    end
+  end
+  return hash.hexdigest
+end
+
+
+def profile_hash
+  @@profile_hashes ||= {}
+  @@profile_hashes[@profile] ||= hash_of_files "#{PROFILES_PATH}/#{@profile}.lua"
+end
+
+def osm_hash
+  @osm_hash ||= Digest::SHA1.hexdigest osm_str
+end
+
+def lua_lib_hash
+  @lua_lib_hash ||= hash_of_files Dir.glob("../profiles/lib/*.lua")
+end
+
+def bin_extract_hash
+  @@bin_extract_hash ||= hash_of_files "#{BIN_PATH}/osrm-extract"
+end
+
+def bin_prepare_hash
+  @@bin_prepare_hash ||= hash_of_files "#{BIN_PATH}/osrm-prepare"
+end
+
+def bin_routed_hash
+  @@bin_routed_hash ||= hash_of_files "#{BIN_PATH}/osrm-routed"
+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
new file mode 100644
index 0000000..41f9b3d
--- /dev/null
+++ b/features/support/hooks.rb
@@ -0,0 +1,20 @@
+
+STRESS_TIMEOUT = 300
+
+Before do |scenario|
+  @scenario_title = scenario.title
+  @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
+end
+
+Around('@stress') do |scenario, block|
+ Timeout.timeout(STRESS_TIMEOUT) do
+    block.call
+  end
+end
+
+After do
+end
diff --git a/features/support/launch.rb b/features/support/launch.rb
new file mode 100644
index 0000000..e4252d8
--- /dev/null
+++ b/features/support/launch.rb
@@ -0,0 +1,83 @@
+require 'socket'
+require 'open3'
+
+LAUNCH_TIMEOUT = 2
+SHUTDOWN_TIMEOUT = 2
+OSRM_ROUTED_LOG_FILE = 'osrm-routed.log'
+
+class OSRMLauncher
+  def initialize &block
+    Dir.chdir TEST_FOLDER do
+      begin
+        launch
+        yield
+      ensure
+        shutdown
+      end
+    end
+  end
+
+  private
+  
+  def launch
+    Timeout.timeout(LAUNCH_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
+      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
+    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)
+  end
+
+  def osrm_down
+    if @pid
+      Process.kill 'TERM', @pid
+      wait_for_shutdown
+    end
+  end
+
+  def kill
+    if @pid
+      Process.kill 'KILL', @pid
+    end
+  end
+
+  def wait_for_connection
+    while true
+      begin
+        socket = TCPSocket.new('localhost', OSRM_PORT)
+        return
+      rescue Errno::ECONNREFUSED
+        sleep 0.1
+      end
+    end
+  end
+
+  def wait_for_shutdown
+    while osrm_up?
+      sleep 0.1
+    end
+  end
+end
diff --git a/features/support/log.rb b/features/support/log.rb
new file mode 100644
index 0000000..7aed850
--- /dev/null
+++ b/features/support/log.rb
@@ -0,0 +1,67 @@
+def log s='', type=nil
+  if type == :preprocess
+    file = PREPROCESS_LOG_FILE
+  else
+    file = LOG_FILE
+  end
+  File.open(file, 'a') {|f| f.write("#{s}\n") }
+end
+
+
+def log_scenario_fail_info
+  return if @has_logged_scenario_info
+  log "========================================="
+  log "Failed scenario: #{@scenario_title}"
+  log "Time: #{@scenario_time}"
+  log "Fingerprint: #{@fingerprint}"
+  log "Profile: #{@profile}"
+  log
+  log '```xml' #so output can be posted directly to github comment fields
+  log osm_str.strip
+  log '```'
+  log
+  log
+  @has_logged_scenario_info = true
+end
+
+def log_fail expected,actual,failed
+  log_scenario_fail_info
+  log "== "
+  log "Expected: #{expected}"
+  log "Got:      #{actual}"
+  log
+  failed.each do |fail|
+    log "Attempt: #{fail[:attempt]}"
+    log "Query: #{fail[:query]}"
+    log "Response: #{fail[:response].body}"
+    log
+  end
+end
+
+
+def log_preprocess_info
+  return if @has_logged_preprocess_info
+  log "=========================================", :preprocess
+  log "Preprocessing data for scenario: #{@scenario_title}", :preprocess
+  log "Time: #{@scenario_time}", :preprocess
+  log '', :preprocess
+  log "== OSM data:", :preprocess
+  log '```xml', :preprocess #so output can be posted directly to github comment fields
+  log osm_str, :preprocess
+  log '```', :preprocess
+  log '', :preprocess
+  log "== Profile:", :preprocess
+  log @profile, :preprocess
+  log '', :preprocess
+  @has_logged_preprocess_info = true
+end
+
+def log_preprocess str
+  log_preprocess_info
+  log str, :preprocess
+end
+
+def log_preprocess_done
+end
+
+
diff --git a/features/support/nearest.rb b/features/support/nearest.rb
new file mode 100644
index 0000000..e371307
--- /dev/null
+++ b/features/support/nearest.rb
@@ -0,0 +1,17 @@
+require 'net/http'
+
+def request_nearest_url path
+  @query = path
+  uri = URI.parse "#{HOST}/#{path}"
+  Timeout.timeout(REQUEST_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_nearest a
+  request_nearest_url "nearest?loc=#{a}"
+end
diff --git a/features/support/osm_parser.rb b/features/support/osm_parser.rb
new file mode 100644
index 0000000..ea4e9bd
--- /dev/null
+++ b/features/support/osm_parser.rb
@@ -0,0 +1,23 @@
+require 'OSM/StreamParser'
+
+class OSMTestParserCallbacks < OSM::Callbacks
+  @@locations = nil
+  
+  def self.locations
+    if @@locations
+      @@locations
+    else
+      #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
+    end
+  end
+
+  def node(node)
+    @@locations[node.name] = [node.lat,node.lon]
+  end
+end
\ No newline at end of file
diff --git a/features/support/osmlib.rb b/features/support/osmlib.rb
new file mode 100644
index 0000000..6b03dfa
--- /dev/null
+++ b/features/support/osmlib.rb
@@ -0,0 +1,14 @@
+#monkey-patch osmlib to fix a bug
+
+module OSM
+  class Way
+    def to_xml(xml)
+      xml.way(attributes) do
+        nodes.each do |node|
+          xml.nd(:ref => node)
+        end
+        tags.to_xml(xml)
+      end
+    end
+  end
+end
diff --git a/features/support/route.rb b/features/support/route.rb
new file mode 100644
index 0000000..9cfbbfa
--- /dev/null
+++ b/features/support/route.rb
@@ -0,0 +1,135 @@
+require 'net/http'
+
+HOST = "http://localhost:#{OSRM_PORT}"
+REQUEST_TIMEOUT = 1
+DESTINATION_REACHED = 15      #OSRM instruction code
+
+class Hash
+  def to_param(namespace = nil)
+    collect do |key, value|
+      "#{key}=#{value}"
+    end.sort
+  end
+end
+
+def request_path path, waypoints=[], options={}
+  locs = waypoints.compact.map { |w| "loc=#{w.lat},#{w.lon}" }
+  params = (locs + options.to_param).join('&')
+  params = nil if params==""
+  uri = URI.parse ["#{HOST}/#{path}", params].compact.join('?')
+  Timeout.timeout(REQUEST_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_route waypoints, params={}
+  defaults = { 'output' => 'json', 'instructions' => true, 'alt' => false }
+  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
+    if json['status'] == 0
+      return way_list( json['route_instructions']).empty? == false
+    end
+  end
+  false
+end
+
+def route_status response
+  if response.code == "200" && !response.body.empty?
+    json = JSON.parse response.body
+    if json['status'] == 0
+      if way_list( json['route_instructions']).empty?
+        return 'Empty route'
+      else
+        return 'x'
+      end
+    elsif json['status'] == 207
+      ''
+    else
+      "Status #{json['status']}"
+    end
+  else
+    "HTTP #{response.code}"
+  end
+end
+
+def way_list instructions
+  instructions.reject { |r| r[0].to_s=="#{DESTINATION_REACHED}" }.
+  map { |r| r[1] }.
+  map { |r| r=="" ? '""' : r }.
+  join(',')
+end
+
+def compass_list instructions
+  instructions.reject { |r| r[0].to_s=="#{DESTINATION_REACHED}" }.
+  map { |r| r[6] }.
+  map { |r| r=="" ? '""' : r }.
+  join(',')
+end
+
+def bearing_list instructions
+  instructions.reject { |r| r[0].to_s=="#{DESTINATION_REACHED}" }.
+  map { |r| r[7] }.
+  map { |r| r=="" ? '""' : r }.
+  join(',')
+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(',')
+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
diff --git a/features/support/shortcuts.rb b/features/support/shortcuts.rb
new file mode 100644
index 0000000..20bc3c0
--- /dev/null
+++ b/features/support/shortcuts.rb
@@ -0,0 +1,3 @@
+def shortcuts_hash
+  @shortcuts_hash ||= {}
+end
diff --git a/features/testbot/bad.feature b/features/testbot/bad.feature
new file mode 100644
index 0000000..8fb3703
--- /dev/null
+++ b/features/testbot/bad.feature
@@ -0,0 +1,86 @@
+ at routing @bad
+Feature: Handle bad data in a graceful manner
+	
+	Background:
+		Given the profile "testbot"
+
+	Scenario: Empty dataset
+		Given the node map
+		 |  |
+
+		Given the ways
+		 | nodes |
+		
+		When I preprocess data
+		Then "osrm-extract" should return code 255
+
+	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 |
+    
+    @todo
+	Scenario: Start/end point at the same location
+		Given the node map
+		 | a | b |
+		 | 1 | 2 |
+
+		Given the ways
+		 | nodes |
+		 | ab    |
+
+		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.
+
+		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    |
+
+		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
new file mode 100644
index 0000000..aabdcaa
--- /dev/null
+++ b/features/testbot/basic.feature
@@ -0,0 +1,272 @@
+ at 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    |
+    
+		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 |
diff --git a/features/testbot/bearing.feature b/features/testbot/bearing.feature
new file mode 100644
index 0000000..48ac5bd
--- /dev/null
+++ b/features/testbot/bearing.feature
@@ -0,0 +1,141 @@
+ at 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
diff --git a/features/testbot/bearing_param.feature b/features/testbot/bearing_param.feature
new file mode 100644
index 0000000..24d329d
--- /dev/null
+++ b/features/testbot/bearing_param.feature
@@ -0,0 +1,93 @@
+ at 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    |
+
+		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    |
+
+ 		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 |
+		
+		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     |
diff --git a/features/testbot/bug.feature b/features/testbot/bug.feature
new file mode 100644
index 0000000..6eb1349
--- /dev/null
+++ b/features/testbot/bug.feature
@@ -0,0 +1,23 @@
+ 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/distance.feature b/features/testbot/distance.feature
new file mode 100644
index 0000000..1fb436b
--- /dev/null
+++ b/features/testbot/distance.feature
@@ -0,0 +1,228 @@
+ at 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 |
diff --git a/features/testbot/duration.feature b/features/testbot/duration.feature
new file mode 100644
index 0000000..ab6571c
--- /dev/null
+++ b/features/testbot/duration.feature
@@ -0,0 +1,42 @@
+ at routing @testbot @routes @duration
+Feature: Durations
+
+	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 |
+
+ 		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 |
+
+    	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 |
diff --git a/features/testbot/example.feature b/features/testbot/example.feature
new file mode 100644
index 0000000..699d35c
--- /dev/null
+++ b/features/testbot/example.feature
@@ -0,0 +1,38 @@
+ at 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"
+    
+    Scenario: Testbot - Processing Flow
+    	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     |
+    	 | 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
new file mode 100644
index 0000000..572280c
--- /dev/null
+++ b/features/testbot/fastest.feature
@@ -0,0 +1,38 @@
+ at 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 |
+
+		When I route I should get
+		 | from | to | route     |
+		 | x    | y  | xa,atb,by |
+		 | y    | x  | by,atb,xa |
+
+	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
new file mode 100644
index 0000000..7bd4353
--- /dev/null
+++ b/features/testbot/ferry.feature
@@ -0,0 +1,175 @@
+ at 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    |
+
+        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 |
+    
+    @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 |
+    
+    @todo
+	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 |
+    
+    @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 |
diff --git a/features/testbot/graph.feature b/features/testbot/graph.feature
new file mode 100644
index 0000000..97a5171
--- /dev/null
+++ b/features/testbot/graph.feature
@@ -0,0 +1,22 @@
+ at routing @graph
+Feature: Basic Routing
+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 |
diff --git a/features/testbot/impedance.feature b/features/testbot/impedance.feature
new file mode 100644
index 0000000..0e53623
--- /dev/null
+++ b/features/testbot/impedance.feature
@@ -0,0 +1,96 @@
+ at 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.
+
+Note: With the default grid size of 100m, the diagonals has a length if 141.42m
+
+	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 |
+
+		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 |
+
+ 	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   |        |
+
+ 		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 |
+
+  		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   |
+
+ 	Scenario: Weight should influence neither speed nor travel time. 
+ 		Given the node map
+ 		 | a | b | c |
+ 		 | t |   |   |
+
+ 		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 |
diff --git a/features/testbot/maxspeed.feature b/features/testbot/maxspeed.feature
new file mode 100644
index 0000000..c6b210e
--- /dev/null
+++ b/features/testbot/maxspeed.feature
@@ -0,0 +1,52 @@
+ at 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 |
+
+		And the ways
+		 | nodes | maxspeed |
+		 | ab    |          |
+		 | bc    | 24       |
+		 | cd    | 18       |
+
+		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 |
+
+    @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
diff --git a/features/testbot/mode.feature b/features/testbot/mode.feature
new file mode 100644
index 0000000..3192c48
--- /dev/null
+++ b/features/testbot/mode.feature
@@ -0,0 +1,26 @@
+ at routing @testbot @mode
+Feature: Testbot - Mode flag
+
+	Background:
+		Given the profile "testbot"
+    
+    @todo
+  	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 |       |          |
+
+  		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/opposite.feature b/features/testbot/opposite.feature
new file mode 100644
index 0000000..c242c97
--- /dev/null
+++ b/features/testbot/opposite.feature
@@ -0,0 +1,18 @@
+ at 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
diff --git a/features/testbot/origin.feature b/features/testbot/origin.feature
new file mode 100644
index 0000000..3fe6d97
--- /dev/null
+++ b/features/testbot/origin.feature
@@ -0,0 +1,75 @@
+ at 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    |
+
+		When I route I should get
+		 | from | to | route | distance  |
+		 | b    | c  | abcd  | 100m +-1  |
+		 | c    | b  |       |           |
+
+	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    |
+
+		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   |
+
+		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/penalty.feature b/features/testbot/penalty.feature
new file mode 100644
index 0000000..97d5e6a
--- /dev/null
+++ b/features/testbot/penalty.feature
@@ -0,0 +1,168 @@
+ at 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
diff --git a/features/testbot/planetary.feature b/features/testbot/planetary.feature
new file mode 100644
index 0000000..242ba8b
--- /dev/null
+++ b/features/testbot/planetary.feature
@@ -0,0 +1,86 @@
+ at 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% |
diff --git a/features/testbot/routes.feature b/features/testbot/routes.feature
new file mode 100644
index 0000000..763b347
--- /dev/null
+++ b/features/testbot/routes.feature
@@ -0,0 +1,35 @@
+ at 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 |
+
+		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 |
\ No newline at end of file
diff --git a/features/testbot/snap.feature b/features/testbot/snap.feature
new file mode 100644
index 0000000..bb3156d
--- /dev/null
+++ b/features/testbot/snap.feature
@@ -0,0 +1,154 @@
+ at 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
diff --git a/features/testbot/time.feature b/features/testbot/time.feature
new file mode 100644
index 0000000..b10544f
--- /dev/null
+++ b/features/testbot/time.feature
@@ -0,0 +1,215 @@
+ at 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 |
diff --git a/features/testbot/turns.feature b/features/testbot/turns.feature
new file mode 100644
index 0000000..5a14c9e
--- /dev/null
+++ b/features/testbot/turns.feature
@@ -0,0 +1,123 @@
+ at 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    |
+
+		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  |
+
+		 | 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  |
+
+		 | 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  |
+
+		 | 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  |
+
+		 | 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  |
+
+		 | 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  |
+
+		 | 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  |
+
+		 | 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
new file mode 100644
index 0000000..784bd4c
--- /dev/null
+++ b/features/testbot/utf.feature
@@ -0,0 +1,21 @@
+ at 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 Москва        |
+
+		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
new file mode 100644
index 0000000..5ba8bac
--- /dev/null
+++ b/features/testbot/via.feature
@@ -0,0 +1,52 @@
+ at routing @testbot @via
+Feature: Via points
+
+    Background:
+        Given the profile "testbot"
+
+        Scenario: Simple via point
+            Given the node map
+             | a | b | c |
+
+            And the ways
+             | nodes |
+             | 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 |   |
+
+        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,h | ab,bcd,de,efg,gh |
diff --git a/features/timestamp/timestamp.feature b/features/timestamp/timestamp.feature
new file mode 100644
index 0000000..7886bad
--- /dev/null
+++ b/features/timestamp/timestamp.feature
@@ -0,0 +1,12 @@
+ at 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
+ 		
diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua
new file mode 100644
index 0000000..98d03c8
--- /dev/null
+++ b/profiles/bicycle.lua
@@ -0,0 +1,353 @@
+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	}
+access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestery"] = true }
+access_tag_restricted = { ["destination"] = true, ["delivery"] = true }
+access_tags_hierachy = { "bicycle", "vehicle", "access" }
+cycleway_tags = {["track"]=true,["lane"]=true,["opposite"]=true,["opposite_lane"]=true,["opposite_track"]=true,["share_busway"]=true,["sharrow"]=true,["shared"]=true }
+service_tag_restricted = { ["parking_aisle"] = true }
+restriction_exception_tags = { "bicycle", "vehicle", "access" }
+
+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,
+}
+
+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
+}
+
+platform_speeds = { 
+	["platform"] = walking_speed
+}
+
+amenity_speeds = { 
+	["parking"] = 10,
+	["parking_entrance"] = 10
+}
+
+man_made_speeds = { 
+	["pier"] = walking_speed
+}
+
+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	
+}
+
+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
+-- End of globals
+
+function get_exceptions(vector)
+	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	
+	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
+    
+    -- 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 = 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
+    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
+    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)
+        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
+
+  -- 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
+    end
+    if maxspeed_backward ~= nil and maxspeed_backward > 0 then
+      way.backward_speed = maxspeed_backward
+    end
+
+
+	
+	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
+end
diff --git a/profiles/car.lua b/profiles/car.lua
new file mode 100644
index 0000000..ff7c379
--- /dev/null
+++ b/profiles/car.lua
@@ -0,0 +1,219 @@
+-- Begin of globals
+require("lib/access")
+
+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 }
+access_tag_restricted = { ["destination"] = true, ["delivery"] = true }
+access_tags = { "motorcar", "motor_vehicle", "vehicle" }
+access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" }
+service_tag_restricted = { ["parking_aisle"] = true }
+ignore_in_grid = { ["ferry"] = true }
+restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" }
+
+speed_profile = {
+  ["motorway"] = 90,
+  ["motorway_link"] = 75,
+  ["trunk"] = 85,
+  ["trunk_link"] = 70,
+  ["primary"] = 65,
+  ["primary_link"] = 60,
+  ["secondary"] = 55,
+  ["secondary_link"] = 50,
+  ["tertiary"] = 40,
+  ["tertiary_link"] = 30,
+  ["unclassified"] = 25,
+  ["residential"] = 25,
+  ["living_street"] = 10,
+  ["service"] = 15,
+--  ["track"] = 5,
+  ["ferry"] = 5,
+  ["shuttle_train"] = 10,
+  ["default"] = 50
+}
+
+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
+
+-- End of globals
+
+function get_exceptions(vector)
+	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)
+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
+
+  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
+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
+  end
+
+  -- check if oneway tag is unsupported
+  local oneway = way.tags:Find("oneway")
+  if "reversible" == oneway then
+    return 0
+  end
+
+  -- Check if we are allowed to access the way
+  local access = Access.find_access_tag(way, access_tags_hierachy)
+  if access_tag_blacklist[access] then
+    return 0
+  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
+    if durationIsValid(duration) then
+      way.duration = math.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
+  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
+    else
+      if 0 == maxspeed then
+        maxspeed = math.huge
+      end
+      way.speed = math.min(speed_profile[highway], maxspeed)
+    end
+  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)
+  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
+  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
+  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
+    end
+  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
+  end
+  if maxspeed_backward ~= nil and 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
+
+	way.type = 1
+  return 1
+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
+end
diff --git a/profiles/foot.lua b/profiles/foot.lua
new file mode 100644
index 0000000..6a15fb2
--- /dev/null
+++ b/profiles/foot.lua
@@ -0,0 +1,193 @@
+-- Foot profile
+
+-- Begin of globals
+
+bollards_whitelist = { [""] = true, ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = 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" }
+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
+}
+
+
+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 
+		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
+end
+
+function way_function (way)
+
+  -- 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
+
+	if ignore_areas and ("yes" == area) 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
+	elseif "" ~= name then
+	  way.name = name
+	end
+	
+	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)
+    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
+    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
+    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
+end
diff --git a/profiles/lib/access.lua b/profiles/lib/access.lua
new file mode 100644
index 0000000..094db62
--- /dev/null
+++ b/profiles/lib/access.lua
@@ -0,0 +1,13 @@
+local ipairs = ipairs
+
+module "Access"
+
+function find_access_tag(source,access_tags_hierachy)
+    for i,v in ipairs(access_tags_hierachy) do
+        local tag = source.tags:Find(v)
+        if tag ~= '' then
+            return tag
+        end
+    end
+    return nil
+end
\ No newline at end of file
diff --git a/profiles/testbot.lua b/profiles/testbot.lua
new file mode 100644
index 0000000..f934fea
--- /dev/null
+++ b/profiles/testbot.lua
@@ -0,0 +1,107 @@
+-- Testbot profile
+
+-- 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
+}
+
+-- 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
+
+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
+    end
+    return speed
+end
+
+function node_function (node)
+	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
+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
+end
diff --git a/profiles/turnbot.lua b/profiles/turnbot.lua
new file mode 100644
index 0000000..1a96966
--- /dev/null
+++ b/profiles/turnbot.lua
@@ -0,0 +1,8 @@
+-- Testbot, with turn penalty
+-- Used for testing turn penalties
+
+require 'testbot'
+
+function turn_function (angle)
+    return 200*math.abs(angle)/180 -- penalty 
+end
diff --git a/routed.cpp b/routed.cpp
new file mode 100644
index 0000000..e097bd7
--- /dev/null
+++ b/routed.cpp
@@ -0,0 +1,159 @@
+/*
+    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>
+
+#include "Server/DataStructures/QueryObjectsStorage.h"
+#include "Server/ServerConfiguration.h"
+#include "Server/ServerFactory.h"
+
+#include "Plugins/HelloWorldPlugin.h"
+#include "Plugins/LocatePlugin.h"
+#include "Plugins/NearestPlugin.h"
+#include "Plugins/TimestampPlugin.h"
+#include "Plugins/ViaRoutePlugin.h"
+
+#include "Util/InputFileUtil.h"
+#include "Util/OpenMPWrapper.h"
+
+#ifndef _WIN32
+#include "Util/LinuxStackTrace.h"
+#endif
+
+typedef http::RequestHandler RequestHandler;
+
+#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;
+  }
+}
+#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
+
+    installCrashHandler(argv[0]);
+#endif
+
+	// 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;
+
+#ifndef _WIN32
+        int sig = 0;
+        sigset_t new_mask;
+        sigset_t old_mask;
+        sigfillset(&new_mask);
+        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();
+
+        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")
+                );
+
+        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));
+
+#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);
+#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();
+#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!");
+        }
+
+        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;
+    }
+#ifdef __linux__
+    munlockall();
+#endif
+
+    return 0;
+}
diff --git a/server.ini b/server.ini
new file mode 100644
index 0000000..3fe844a
--- /dev/null
+++ b/server.ini
@@ -0,0 +1,11 @@
+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/.gitignore b/test/.gitignore
new file mode 100644
index 0000000..ea5e38e
--- /dev/null
+++ b/test/.gitignore
@@ -0,0 +1,3 @@
+/server.ini
+/cache
+/speedprofile.ini
diff --git a/test/.stxxl b/test/.stxxl
new file mode 100644
index 0000000..b1765e2
--- /dev/null
+++ b/test/.stxxl
@@ -0,0 +1 @@
+disk=/tmp/stxxl,10,syscall
diff --git a/test/contractor.ini b/test/contractor.ini
new file mode 100644
index 0000000..4da33c7
--- /dev/null
+++ b/test/contractor.ini
@@ -0,0 +1 @@
+Threads = 4
diff --git a/test/extractor.ini b/test/extractor.ini
new file mode 100644
index 0000000..eca8b17
--- /dev/null
+++ b/test/extractor.ini
@@ -0,0 +1 @@
+Memory = 1
diff --git a/typedefs.h b/typedefs.h
new file mode 100644
index 0000000..a962598
--- /dev/null
+++ b/typedefs.h
@@ -0,0 +1,68 @@
+/*
+    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 TYPEDEFS_H_
+#define TYPEDEFS_H_
+
+#include <cmath>
+#include <climits>
+#include <cstdlib>
+
+// To fix long and long long woes
+#include <boost/integer.hpp>
+#include <boost/integer_traits.hpp>
+
+#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
+
+#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);
+}
+#endif
+
+
+typedef unsigned int NodeID;
+typedef unsigned int EdgeID;
+typedef unsigned 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;
+
+#endif /* TYPEDEFS_H_ */
diff --git a/win/createHierarchy.vcproj b/win/createHierarchy.vcproj
new file mode 100644
index 0000000..428c56c
--- /dev/null
+++ b/win/createHierarchy.vcproj
@@ -0,0 +1,459 @@
+<?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
new file mode 100644
index 0000000..2821f87
--- /dev/null
+++ b/win/extractor.vcproj
@@ -0,0 +1,532 @@
+<?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
new file mode 100644
index 0000000..d19c36f
--- /dev/null
+++ b/win/getopt.c
@@ -0,0 +1,1260 @@
+#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
new file mode 100644
index 0000000..455d531
--- /dev/null
+++ b/win/getopt.h
@@ -0,0 +1,189 @@
+#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
new file mode 100644
index 0000000..62634fc
--- /dev/null
+++ b/win/osrm.sln
@@ -0,0 +1,29 @@
+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
new file mode 100644
index 0000000..08d15be
--- /dev/null
+++ b/win/osrm.vsprops
@@ -0,0 +1,39 @@
+<?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
new file mode 100644
index 0000000..8f4c183
--- /dev/null
+++ b/win/routed.vcproj
@@ -0,0 +1,459 @@
+<?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
new file mode 100644
index 0000000..442c158
--- /dev/null
+++ b/win/unistd.h
@@ -0,0 +1,30 @@
+#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