From cabaad4b17ad5168765aa3a39399dec92a2e791b Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 14 Nov 2013 17:16:26 -0500 Subject: [PATCH] replaced contigouos output data with collection of small'ish sub blocks. saves (re-)allocations. also removed a remaining stringstream --- CMakeLists.txt | 2 +- Descriptors/BaseDescriptor.h | 1 + Descriptors/DescriptionFactory.cpp | 24 ++- Descriptors/DescriptionFactory.h | 6 +- Descriptors/GPXDescriptor.h | 26 +-- Descriptors/JSONDescriptor.h | 246 +++++++++++++++-------------- Plugins/HelloWorldPlugin.h | 69 +++++--- Plugins/LocatePlugin.h | 32 ++-- Plugins/NearestPlugin.h | 38 ++--- Plugins/TimestampPlugin.h | 24 +-- Plugins/ViaRoutePlugin.h | 9 +- Server/Connection.h | 167 ++++++++++++-------- Server/Http/Reply.cpp | 13 +- Server/Http/Reply.h | 2 +- Server/RequestHandler.h | 16 +- Server/RequestParser.h | 13 +- Tools/simpleclient.cpp | 8 +- 17 files changed, 391 insertions(+), 305 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 473a49af0..ee81fc4d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/UUID.cpp UUID.cpp.alwaysbuild add_custom_target(UUIDConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/UUID.cpp ) -set(BOOST_COMPONENTS filesystem program_options regex system thread) +set(BOOST_COMPONENTS filesystem iostreams program_options regex system thread) configure_file(Util/GitDescription.cpp.in ${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp) file(GLOB ExtractorGlob Extractor/*.cpp) diff --git a/Descriptors/BaseDescriptor.h b/Descriptors/BaseDescriptor.h index 5cdf4d966..029332527 100644 --- a/Descriptors/BaseDescriptor.h +++ b/Descriptors/BaseDescriptor.h @@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../DataStructures/HashTable.h" #include "../DataStructures/PhantomNodes.h" #include "../DataStructures/RawRouteData.h" +#include "../Server/Http/Reply.h" #include "../Util/StringUtil.h" #include "../typedefs.h" diff --git a/Descriptors/DescriptionFactory.cpp b/Descriptors/DescriptionFactory.cpp index 7fb111c7a..cae651394 100644 --- a/Descriptors/DescriptionFactory.cpp +++ b/Descriptors/DescriptionFactory.cpp @@ -95,21 +95,31 @@ void DescriptionFactory::AppendSegment( void DescriptionFactory::AppendEncodedPolylineString( const bool return_encoded, - std::string & output + std::vector & output ) { + std::string temp; if(return_encoded) { - polyline_compressor.printEncodedString(pathDescription, output); + polyline_compressor.printEncodedString(pathDescription, temp); } else { - polyline_compressor.printUnencodedString(pathDescription, output); + polyline_compressor.printUnencodedString(pathDescription, temp); } + output.push_back(temp); } -void DescriptionFactory::AppendEncodedPolylineString(std::string &output) const { - polyline_compressor.printEncodedString(pathDescription, output); +void DescriptionFactory::AppendEncodedPolylineString( + std::vector &output +) const { + std::string temp; + polyline_compressor.printEncodedString(pathDescription, temp); + output.push_back(temp); } -void DescriptionFactory::AppendUnencodedPolylineString(std::string &output) const { - polyline_compressor.printUnencodedString(pathDescription, output); +void DescriptionFactory::AppendUnencodedPolylineString( + std::vector& output +) const { + std::string temp; + polyline_compressor.printUnencodedString(pathDescription, temp); + output.push_back(temp); } // void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLevel) { diff --git a/Descriptors/DescriptionFactory.h b/Descriptors/DescriptionFactory.h index d1407c6c3..8c8a3c0b3 100644 --- a/Descriptors/DescriptionFactory.h +++ b/Descriptors/DescriptionFactory.h @@ -82,15 +82,15 @@ public: DescriptionFactory(); virtual ~DescriptionFactory(); double GetBearing(const FixedPointCoordinate& C, const FixedPointCoordinate& B) const; - void AppendEncodedPolylineString(std::string &output) const; - void AppendUnencodedPolylineString(std::string &output) const; + void AppendEncodedPolylineString(std::vector &output) const; + void AppendUnencodedPolylineString(std::vector &output) const; void AppendSegment(const FixedPointCoordinate & coordinate, const _PathData & data); void BuildRouteSummary(const double distance, const unsigned time); void SetStartSegment(const PhantomNode & start_phantom); void SetEndSegment(const PhantomNode & start_phantom); void AppendEncodedPolylineString( const bool return_encoded, - std::string & output + std::vector & output ); template diff --git a/Descriptors/GPXDescriptor.h b/Descriptors/GPXDescriptor.h index 84d01295b..3a3ccafc2 100644 --- a/Descriptors/GPXDescriptor.h +++ b/Descriptors/GPXDescriptor.h @@ -49,18 +49,18 @@ public: PhantomNodes &phantomNodes, const DataFacadeT * facade ) { - reply.content += (""); - reply.content += + reply.content.push_back(""); + reply.content.push_back( ""; - reply.content += + "\">"); + reply.content.push_back( "Data (c)" " OpenStreetMap contributors (ODbL)" - ""; - reply.content += ""; + ""); + reply.content.push_back(""); bool found_route = (rawRoute.lengthOfShortestPath != INT_MAX) && (rawRoute.computedShortestPath.size() ); if( found_route ) { @@ -68,12 +68,12 @@ public: phantomNodes.startPhantom.location.lat, tmp ); - reply.content += ""; + reply.content.push_back("lon=\"" + tmp + "\">"); BOOST_FOREACH( const _PathData & pathData, @@ -82,22 +82,22 @@ public: current = facade->GetCoordinateOfNode(pathData.node); convertInternalLatLonToString(current.lat, tmp); - reply.content += ""; + reply.content.push_back("lon=\"" + tmp + "\">"); } convertInternalLatLonToString( phantomNodes.targetPhantom.location.lat, tmp ); - reply.content += ""; + reply.content.push_back("lon=\"" + tmp + "\">"); } - reply.content += ""; + reply.content.push_back(""); } }; #endif // GPX_DESCRIPTOR_H_ diff --git a/Descriptors/JSONDescriptor.h b/Descriptors/JSONDescriptor.h index 4e8d0f387..80d7a7e2d 100644 --- a/Descriptors/JSONDescriptor.h +++ b/Descriptors/JSONDescriptor.h @@ -92,8 +92,8 @@ public: if(raw_route_information.lengthOfShortestPath != INT_MAX) { description_factory.SetStartSegment(phantom_nodes.startPhantom); - reply.content += "0," - "\"status_message\": \"Found route between points\","; + reply.content.push_back("0," + "\"status_message\": \"Found route between points\","); //Get all the coordinates for the computed route BOOST_FOREACH(const _PathData & path_data, raw_route_information.computedShortestPath) { @@ -103,23 +103,23 @@ public: description_factory.SetEndSegment(phantom_nodes.targetPhantom); } else { //We do not need to do much, if there is no route ;-) - reply.content += "207," - "\"status_message\": \"Cannot find route between points\","; + reply.content.push_back("207," + "\"status_message\": \"Cannot find route between points\","); } description_factory.Run(facade, config.zoom_level); - reply.content += "\"route_geometry\": "; + reply.content.push_back("\"route_geometry\": "); if(config.geometry) { description_factory.AppendEncodedPolylineString( config.encode_geometry, reply.content ); } else { - reply.content += "[]"; + reply.content.push_back("[]"); } - reply.content += "," - "\"route_instructions\": ["; + reply.content.push_back("," + "\"route_instructions\": ["); entered_restricted_area_count = 0; if(config.instructions) { BuildTextualDescription( @@ -138,32 +138,32 @@ public: entered_restricted_area_count += (current_instruction != segment.turnInstruction); } } - reply.content += "],"; + reply.content.push_back("],"); description_factory.BuildRouteSummary( description_factory.entireLength, raw_route_information.lengthOfShortestPath - ( entered_restricted_area_count*TurnInstructions.AccessRestrictionPenalty) ); - reply.content += "\"route_summary\":"; - reply.content += "{"; - reply.content += "\"total_distance\":"; - reply.content += description_factory.summary.lengthString; - reply.content += "," - "\"total_time\":"; - reply.content += description_factory.summary.durationString; - reply.content += "," - "\"start_point\":\""; - reply.content += facade->GetEscapedNameForNameID( - description_factory.summary.startName + reply.content.push_back("\"route_summary\":"); + reply.content.push_back("{"); + reply.content.push_back("\"total_distance\":"); + reply.content.push_back(description_factory.summary.lengthString); + reply.content.push_back("," + "\"total_time\":"); + reply.content.push_back(description_factory.summary.durationString); + reply.content.push_back("," + "\"start_point\":\""); + reply.content.push_back( + facade->GetEscapedNameForNameID(description_factory.summary.startName) ); - reply.content += "\"," - "\"end_point\":\""; - reply.content += facade->GetEscapedNameForNameID( - description_factory.summary.destName + reply.content.push_back("\"," + "\"end_point\":\""); + reply.content.push_back( + facade->GetEscapedNameForNameID(description_factory.summary.destName) ); - reply.content += "\""; - reply.content += "}"; - reply.content +=","; + reply.content.push_back("\""); + reply.content.push_back("}"); + reply.content.push_back(","); //only one alternative route is computed at this time, so this is hardcoded @@ -179,7 +179,7 @@ public: alternateDescriptionFactory.Run(facade, config.zoom_level); //give an array of alternative routes - reply.content += "\"alternative_geometries\": ["; + reply.content.push_back("\"alternative_geometries\": ["); if(config.geometry && INT_MAX != raw_route_information.lengthOfAlternativePath) { //Generate the linestrings for each alternative alternateDescriptionFactory.AppendEncodedPolylineString( @@ -187,11 +187,11 @@ public: reply.content ); } - reply.content += "],"; - reply.content += "\"alternative_instructions\":["; + reply.content.push_back("],"); + reply.content.push_back("\"alternative_instructions\":["); entered_restricted_area_count = 0; if(INT_MAX != raw_route_information.lengthOfAlternativePath) { - reply.content += "["; + reply.content.push_back("["); //Generate instructions for each alternative if(config.instructions) { BuildTextualDescription( @@ -207,89 +207,89 @@ public: entered_restricted_area_count += (current_instruction != segment.turnInstruction); } } - reply.content += "]"; + reply.content.push_back("]"); } - reply.content += "],"; - reply.content += "\"alternative_summaries\":["; + reply.content.push_back("],"); + reply.content.push_back("\"alternative_summaries\":["); if(INT_MAX != raw_route_information.lengthOfAlternativePath) { //Generate route summary (length, duration) for each alternative alternateDescriptionFactory.BuildRouteSummary(alternateDescriptionFactory.entireLength, raw_route_information.lengthOfAlternativePath - ( entered_restricted_area_count*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 += facade->GetEscapedNameForNameID(description_factory.summary.startName); - reply.content += "\"," - "\"end_point\":\""; - reply.content += facade->GetEscapedNameForNameID(description_factory.summary.destName); - reply.content += "\""; - reply.content += "}"; + reply.content.push_back("{"); + reply.content.push_back("\"total_distance\":"); + reply.content.push_back(alternateDescriptionFactory.summary.lengthString); + reply.content.push_back("," + "\"total_time\":"); + reply.content.push_back(alternateDescriptionFactory.summary.durationString); + reply.content.push_back("," + "\"start_point\":\""); + reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.startName)); + reply.content.push_back("\"," + "\"end_point\":\""); + reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.destName)); + reply.content.push_back("\""); + reply.content.push_back("}"); } - reply.content += "],"; + reply.content.push_back("],"); //Get Names for both routes RouteNames routeNames; GetRouteNames(shortest_path_segments, alternative_path_segments, facade, 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 += "],"; + reply.content.push_back("\"route_name\":[\""); + reply.content.push_back(routeNames.shortestPathName1); + reply.content.push_back("\",\""); + reply.content.push_back(routeNames.shortestPathName2); + reply.content.push_back("\"]," + "\"alternative_names\":["); + reply.content.push_back("[\""); + reply.content.push_back(routeNames.alternativePathName1); + reply.content.push_back("\",\""); + reply.content.push_back(routeNames.alternativePathName2); + reply.content.push_back("\"]"); + reply.content.push_back("],"); //list all viapoints so that the client may display it - reply.content += "\"via_points\":["; + reply.content.push_back("\"via_points\":["); std::string tmp; if(config.geometry && INT_MAX != raw_route_information.lengthOfShortestPath) { for(unsigned i = 0; i < raw_route_information.segmentEndCoordinates.size(); ++i) { - reply.content += "["; + reply.content.push_back("["); if(raw_route_information.segmentEndCoordinates[i].startPhantom.location.isSet()) convertInternalReversedCoordinateToString(raw_route_information.segmentEndCoordinates[i].startPhantom.location, tmp); else convertInternalReversedCoordinateToString(raw_route_information.rawViaNodeCoordinates[i], tmp); - reply.content += tmp; - reply.content += "],"; + reply.content.push_back(tmp); + reply.content.push_back("],"); } - reply.content += "["; + reply.content.push_back("["); if(raw_route_information.segmentEndCoordinates.back().startPhantom.location.isSet()) convertInternalReversedCoordinateToString(raw_route_information.segmentEndCoordinates.back().targetPhantom.location, tmp); else convertInternalReversedCoordinateToString(raw_route_information.rawViaNodeCoordinates.back(), tmp); - reply.content += tmp; - reply.content += "]"; + reply.content.push_back(tmp); + reply.content.push_back("]"); } - reply.content += "],"; - reply.content += "\"hint_data\": {"; - reply.content += "\"checksum\":"; + reply.content.push_back("],"); + reply.content.push_back("\"hint_data\": {"); + reply.content.push_back("\"checksum\":"); intToString(raw_route_information.checkSum, tmp); - reply.content += tmp; - reply.content += ", \"locations\": ["; + reply.content.push_back(tmp); + reply.content.push_back(", \"locations\": ["); std::string hint; for(unsigned i = 0; i < raw_route_information.segmentEndCoordinates.size(); ++i) { - reply.content += "\""; + reply.content.push_back("\""); EncodeObjectToBase64(raw_route_information.segmentEndCoordinates[i].startPhantom, hint); - reply.content += hint; - reply.content += "\", "; + reply.content.push_back(hint); + reply.content.push_back("\", "); } EncodeObjectToBase64(raw_route_information.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 += "}"; + reply.content.push_back("\""); + reply.content.push_back(hint); + reply.content.push_back("\"]"); + reply.content.push_back("},"); + reply.content.push_back("\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.3)\""); + reply.content.push_back("}"); } // construct routes names @@ -357,10 +357,12 @@ public: } } - inline void WriteHeaderToOutput(std::string & output) { - output += "{" - "\"version\": 0.3," - "\"status\":"; + inline void WriteHeaderToOutput(std::vector & output) { + output.push_back( + "{" + "\"version\": 0.3," + "\"status\":" + ); } //TODO: reorder parameters @@ -389,41 +391,41 @@ public: roundAbout.start_index = prefixSumOfNecessarySegments; } else { if(0 != prefixSumOfNecessarySegments){ - reply.content += ","; + reply.content.push_back(","); } - reply.content += "[\""; + reply.content.push_back("[\""); if(TurnInstructions.LeaveRoundAbout == current_instruction) { intToString(TurnInstructions.EnterRoundAbout, tmpInstruction); - reply.content += tmpInstruction; - reply.content += "-"; + reply.content.push_back(tmpInstruction); + reply.content.push_back("-"); intToString(roundAbout.leave_at_exit+1, tmpInstruction); - reply.content += tmpInstruction; + reply.content.push_back(tmpInstruction); roundAbout.leave_at_exit = 0; } else { intToString(current_instruction, tmpInstruction); - reply.content += tmpInstruction; + reply.content.push_back(tmpInstruction); } - reply.content += "\",\""; - reply.content += facade->GetEscapedNameForNameID(segment.nameID); - reply.content += "\","; + reply.content.push_back("\",\""); + reply.content.push_back(facade->GetEscapedNameForNameID(segment.nameID)); + reply.content.push_back("\","); intToString(segment.length, tmpDist); - reply.content += tmpDist; - reply.content += ","; + reply.content.push_back(tmpDist); + reply.content.push_back(","); intToString(prefixSumOfNecessarySegments, tmpLength); - reply.content += tmpLength; - reply.content += ","; + reply.content.push_back(tmpLength); + reply.content.push_back(","); intToString(segment.duration/10, tmpDuration); - reply.content += tmpDuration; - reply.content += ",\""; + reply.content.push_back(tmpDuration); + reply.content.push_back(",\""); intToString(segment.length, tmpLength); - reply.content += tmpLength; - reply.content += "m\",\""; - reply.content += Azimuth::Get(segment.bearing); - reply.content += "\","; + reply.content.push_back(tmpLength); + reply.content.push_back("m\",\""); + reply.content.push_back(Azimuth::Get(segment.bearing)); + reply.content.push_back("\","); intToString(round(segment.bearing), tmpBearing); - reply.content += tmpBearing; - reply.content += "]"; + reply.content.push_back(tmpBearing); + reply.content.push_back("]"); route_segments_list.push_back( Segment( @@ -440,23 +442,23 @@ public: ++prefixSumOfNecessarySegments; } if(INT_MAX != route_length) { - reply.content += ",[\""; + reply.content.push_back(",[\""); intToString(TurnInstructions.ReachedYourDestination, tmpInstruction); - reply.content += tmpInstruction; - reply.content += "\",\""; - reply.content += "\","; - reply.content += "0"; - reply.content += ","; + reply.content.push_back(tmpInstruction); + reply.content.push_back("\",\""); + reply.content.push_back("\","); + reply.content.push_back("0"); + reply.content.push_back(","); 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 += "]"; + reply.content.push_back(tmpLength); + reply.content.push_back(","); + reply.content.push_back("0"); + reply.content.push_back(",\""); + reply.content.push_back("\",\""); + reply.content.push_back(Azimuth::Get(0.0)); + reply.content.push_back("\","); + reply.content.push_back("0.0"); + reply.content.push_back("]"); } } diff --git a/Plugins/HelloWorldPlugin.h b/Plugins/HelloWorldPlugin.h index 33efb64e0..575f7c94d 100644 --- a/Plugins/HelloWorldPlugin.h +++ b/Plugins/HelloWorldPlugin.h @@ -29,10 +29,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define HELLOWORLDPLUGIN_H_ #include "BasePlugin.h" +#include "../Util/StringUtil.h" -#include +#include class HelloWorldPlugin : public BasePlugin { + private: + std::string temp_string; public: HelloWorldPlugin() : descriptor_string("hello"){} virtual ~HelloWorldPlugin() { } @@ -40,28 +43,56 @@ public: void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) { reply.status = http::Reply::ok; - reply.content.append("Hello World Demonstration Document

Hello, World!

"); - std::stringstream content; - content << "
";
-        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 << "
"; - content << "Number of locations: " << routeParameters.coordinates.size() << "\n"; + reply.content.push_back("Hello World Demonstration Document

Hello, World!

"); + reply.content.push_back("
");
+        reply.content.push_back("zoom level: ");
+        intToString(routeParameters.zoomLevel, temp_string);
+        reply.content.push_back(temp_string);
+        reply.content.push_back("\nchecksum: ");
+        intToString(routeParameters.checkSum, temp_string);
+        reply.content.push_back(temp_string);
+        reply.content.push_back("\ninstructions: ");
+        reply.content.push_back((routeParameters.printInstructions ? "yes" : "no"));
+        reply.content.push_back(temp_string);
+        reply.content.push_back("\ngeometry: ");
+        reply.content.push_back((routeParameters.geometry ? "yes" : "no"));
+        reply.content.push_back("\ncompression: ");
+        reply.content.push_back((routeParameters.compression ? "yes" : "no"));
+        reply.content.push_back("\noutput format: ");
+        reply.content.push_back(routeParameters.outputFormat);
+        reply.content.push_back("\njson parameter: ");
+        reply.content.push_back(routeParameters.jsonpParameter);
+        reply.content.push_back("\nlanguage: ");
+        reply.content.push_back(routeParameters.language);
+        reply.content.push_back("\nNumber of locations: ");
+        intToString(routeParameters.coordinates.size(), temp_string);
+        reply.content.push_back(temp_string);
+        reply.content.push_back("\n");
         for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
-            content << "  [" << i << "] " << routeParameters.coordinates[i].lat/COORDINATE_PRECISION << "," << routeParameters.coordinates[i].lon/COORDINATE_PRECISION << "\n";
+            reply.content.push_back( "  [");
+            intToString(i, temp_string);
+            reply.content.push_back(temp_string);
+            reply.content.push_back("] ");
+            doubleToString(routeParameters.coordinates[i].lat/COORDINATE_PRECISION, temp_string);
+            reply.content.push_back(temp_string);
+            reply.content.push_back(",");
+            doubleToString(routeParameters.coordinates[i].lon/COORDINATE_PRECISION, temp_string);
+            reply.content.push_back(temp_string);
+            reply.content.push_back("\n");
         }
-        content << "Number of hints: " << routeParameters.hints.size() << "\n";
+        reply.content.push_back( "Number of hints: ");
+        intToString(routeParameters.hints.size(), temp_string);
+        reply.content.push_back(temp_string);
+        reply.content.push_back("\n");
         for(unsigned i = 0; i < routeParameters.hints.size(); ++i) {
-            content << "  [" << i << "] " << routeParameters.hints[i] << "\n";
+            reply.content.push_back( "  [");
+            intToString(i, temp_string);
+            reply.content.push_back(temp_string);
+            reply.content.push_back("] ");
+            reply.content.push_back(routeParameters.hints[i]);
+            reply.content.push_back("\n");
         }
-        content << "
"; - reply.content.append(content.str()); - reply.content.append(""); + reply.content.push_back( "
"); } private: std::string descriptor_string; diff --git a/Plugins/LocatePlugin.h b/Plugins/LocatePlugin.h index 561abc292..4f5374a4b 100644 --- a/Plugins/LocatePlugin.h +++ b/Plugins/LocatePlugin.h @@ -63,38 +63,38 @@ public: //json if(!routeParameters.jsonpParameter.empty()) { - reply.content += routeParameters.jsonpParameter; - reply.content += "("; + reply.content.push_back(routeParameters.jsonpParameter); + reply.content.push_back("("); } reply.status = http::Reply::ok; - reply.content += ("{"); - reply.content += ("\"version\":0.3,"); + reply.content.push_back ("{"); + reply.content.push_back ("\"version\":0.3,"); if( !facade->LocateClosestEndPointForCoordinate( routeParameters.coordinates[0], result ) ) { - reply.content += ("\"status\":207,"); - reply.content += ("\"mapped_coordinate\":[]"); + reply.content.push_back ("\"status\":207,"); + reply.content.push_back ("\"mapped_coordinate\":[]"); } else { //Write coordinate to stream reply.status = http::Reply::ok; - reply.content += ("\"status\":0,"); - reply.content += ("\"mapped_coordinate\":"); + reply.content.push_back ("\"status\":0,"); + reply.content.push_back ("\"mapped_coordinate\":"); convertInternalLatLonToString(result.lat, tmp); - reply.content += "["; - reply.content += tmp; + reply.content.push_back("["); + reply.content.push_back(tmp); convertInternalLatLonToString(result.lon, tmp); - reply.content += ","; - reply.content += tmp; - reply.content += "]"; + reply.content.push_back(","); + reply.content.push_back(tmp); + reply.content.push_back("]"); } - reply.content += ",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\""; - reply.content += ("}"); + reply.content.push_back(",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\""); + reply.content.push_back("}"); reply.headers.resize(3); if(!routeParameters.jsonpParameter.empty()) { - reply.content += ")"; + reply.content.push_back( ")"); reply.headers[1].name = "Content-Type"; reply.headers[1].value = "text/javascript"; reply.headers[2].name = "Content-Disposition"; diff --git a/Plugins/NearestPlugin.h b/Plugins/NearestPlugin.h index c715a98ac..0ef18a10d 100644 --- a/Plugins/NearestPlugin.h +++ b/Plugins/NearestPlugin.h @@ -70,40 +70,40 @@ public: //json if("" != routeParameters.jsonpParameter) { - reply.content += routeParameters.jsonpParameter; - reply.content += "("; + reply.content.push_back(routeParameters.jsonpParameter); + reply.content.push_back("("); } reply.status = http::Reply::ok; - reply.content += ("{"); - reply.content += ("\"version\":0.3,"); - reply.content += ("\"status\":"); + reply.content.push_back("{"); + reply.content.push_back("\"version\":0.3,"); + reply.content.push_back("\"status\":"); if(UINT_MAX != result.edgeBasedNode) { - reply.content += "0,"; + reply.content.push_back("0,"); } else { - reply.content += "207,"; + reply.content.push_back("207,"); } - reply.content += ("\"mapped_coordinate\":"); - reply.content += "["; + reply.content.push_back("\"mapped_coordinate\":"); + reply.content.push_back("["); if(UINT_MAX != result.edgeBasedNode) { convertInternalLatLonToString(result.location.lat, temp_string); - reply.content += temp_string; + reply.content.push_back(temp_string); convertInternalLatLonToString(result.location.lon, temp_string); - reply.content += ","; - reply.content += temp_string; + reply.content.push_back(","); + reply.content.push_back(temp_string); } - reply.content += "],"; - reply.content += "\"name\":\""; + reply.content.push_back("],"); + reply.content.push_back("\"name\":\""); if(UINT_MAX != result.edgeBasedNode) { facade->GetName(result.nodeBasedEdgeNameID, temp_string); - reply.content += temp_string; + reply.content.push_back(temp_string); } - reply.content += "\""; - reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\""; - reply.content += ("}"); + reply.content.push_back("\""); + reply.content.push_back(",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\""); + reply.content.push_back("}"); reply.headers.resize(3); if( !routeParameters.jsonpParameter.empty() ) { - reply.content += ")"; + reply.content.push_back(")"); reply.headers[1].name = "Content-Type"; reply.headers[1].value = "text/javascript"; reply.headers[2].name = "Content-Disposition"; diff --git a/Plugins/TimestampPlugin.h b/Plugins/TimestampPlugin.h index 80ac92290..d47f84a6f 100644 --- a/Plugins/TimestampPlugin.h +++ b/Plugins/TimestampPlugin.h @@ -42,23 +42,23 @@ public: //json if("" != routeParameters.jsonpParameter) { - reply.content += routeParameters.jsonpParameter; - reply.content += "("; + reply.content.push_back(routeParameters.jsonpParameter); + reply.content.push_back("("); } reply.status = http::Reply::ok; - reply.content += ("{"); - reply.content += ("\"version\":0.3,"); - reply.content += ("\"status\":"); - reply.content += "0,"; - reply.content += ("\"timestamp\":\""); - reply.content += facade->GetTimestamp(); - reply.content += "\""; - reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON timestamp (v0.3)\""; - reply.content += ("}"); + reply.content.push_back("{"); + reply.content.push_back("\"version\":0.3,"); + reply.content.push_back("\"status\":"); + reply.content.push_back("0,"); + reply.content.push_back("\"timestamp\":\""); + reply.content.push_back(facade->GetTimestamp()); + reply.content.push_back("\""); + reply.content.push_back(",\"transactionId\":\"OSRM Routing Engine JSON timestamp (v0.3)\""); + reply.content.push_back("}"); reply.headers.resize(3); if("" != routeParameters.jsonpParameter) { - reply.content += ")"; + reply.content.push_back(")"); reply.headers[1].name = "Content-Type"; reply.headers[1].value = "text/javascript"; reply.headers[2].name = "Content-Disposition"; diff --git a/Plugins/ViaRoutePlugin.h b/Plugins/ViaRoutePlugin.h index 7c46034f5..40b02e46e 100644 --- a/Plugins/ViaRoutePlugin.h +++ b/Plugins/ViaRoutePlugin.h @@ -140,8 +140,8 @@ public: //TODO: Move to member as smart pointer BaseDescriptor * desc; if("" != routeParameters.jsonpParameter) { - reply.content += routeParameters.jsonpParameter; - reply.content += "("; + reply.content.push_back(routeParameters.jsonpParameter); + reply.content.push_back("("); } DescriptorConfig descriptorConfig; @@ -172,15 +172,12 @@ public: PhantomNodes phantomNodes; phantomNodes.startPhantom = rawRoute.segmentEndCoordinates[0].startPhantom; -// SimpleLogger().Write() << "Start location: " << phantomNodes.startPhantom.location; phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom; -// SimpleLogger().Write() << "TargetLocation: " << phantomNodes.targetPhantom.location; -// SimpleLogger().Write() << "Number of segments: " << rawRoute.segmentEndCoordinates.size(); desc->SetConfig(descriptorConfig); desc->Run(reply, rawRoute, phantomNodes, facade); if("" != routeParameters.jsonpParameter) { - reply.content += ")\n"; + reply.content.push_back(")\n"); } reply.headers.resize(3); reply.headers[0].name = "Content-Length"; diff --git a/Server/Connection.h b/Server/Connection.h index e0017cc90..bd7d3e879 100644 --- a/Server/Connection.h +++ b/Server/Connection.h @@ -37,11 +37,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include +#include #include #include -#include +// #include + +#include #include namespace http { @@ -92,7 +96,7 @@ private: request_handler.handle_request(request, reply); Header compression_header; - std::vector compressed_output; + std::vector compressed_output; std::vector output_buffer; switch(compression_type) { case deflateRFC1951: @@ -102,11 +106,10 @@ private: reply.headers.begin(), compression_header ); - compressCharArray( - reply.content.c_str(), - reply.content.length(), - compressed_output, - compression_type + compressBufferCollection( + reply.content, + compression_type, + compressed_output ); reply.setSize(compressed_output.size()); output_buffer = reply.HeaderstoBuffers(); @@ -132,11 +135,10 @@ private: reply.headers.begin(), compression_header ); - compressCharArray( - reply.content.c_str(), - reply.content.length(), - compressed_output, - compression_type + compressBufferCollection( + reply.content, + compression_type, + compressed_output ); reply.setSize(compressed_output.size()); output_buffer = reply.HeaderstoBuffers(); @@ -210,71 +212,100 @@ private: } } + void compressBufferCollection( + std::vector uncompressed_data, + CompressionType compression_type, + std::vector & compressed_data + ) { + boost::iostreams::gzip_params compression_parameters; + + compression_parameters.level = boost::iostreams::zlib::best_speed; + if ( deflateRFC1951 == compression_type ) { + compression_parameters.noheader = true; + } + + BOOST_ASSERT( compressed_data.empty() ); + boost::iostreams::filtering_ostream compressing_stream; + + compressing_stream.push( + boost::iostreams::gzip_compressor(compression_parameters) + ); + compressing_stream.push( + boost::iostreams::back_inserter(compressed_data) + ); + + BOOST_FOREACH( const std::string & line, uncompressed_data) { + compressing_stream << line; + } + + compressing_stream.reset(); + } + // Big thanks to deusty who explains how to use gzip compression by // the right call to deflateInit2(): // http://deusty.blogspot.com/2007/07/gzip-compressiondecompression.html - void compressCharArray( - const char * in_data, - size_t in_data_size, - std::vector & buffer, - CompressionType type - ) { - const size_t BUFSIZE = 128 * 1024; - unsigned char temp_buffer[BUFSIZE]; + // void compressCharArray( + // const char * in_data, + // size_t in_data_size, + // std::vector & 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; + // 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: - deflateInit2( - &strm, - Z_DEFAULT_COMPRESSION, - Z_DEFLATED, - (15+16), - 9, - Z_DEFAULT_STRATEGY - ); - break; - default: - BOOST_ASSERT_MSG(false, "should not happen"); - break; - } + // switch(type){ + // case deflateRFC1951: + // deflateInit(&strm, Z_BEST_SPEED); + // break; + // case gzipRFC1952: + // deflateInit2( + // &strm, + // Z_DEFAULT_COMPRESSION, + // Z_DEFLATED, + // (15+16), + // 9, + // Z_DEFAULT_STRATEGY + // ); + // break; + // default: + // BOOST_ASSERT_MSG(false, "should not happen"); + // break; + // } - int deflate_res = Z_OK; - do { - if ( 0 == strm.avail_out ) { - buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE); - strm.next_out = temp_buffer; - strm.avail_out = BUFSIZE; - } - deflate_res = deflate(&strm, Z_FINISH); + // int deflate_res = Z_OK; + // do { + // if ( 0 == strm.avail_out ) { + // 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); + // } while (deflate_res == Z_OK); - BOOST_ASSERT_MSG( - deflate_res == Z_STREAM_END, - "compression not properly finished" - ); + // BOOST_ASSERT_MSG( + // deflate_res == Z_STREAM_END, + // "compression not properly finished" + // ); - buffer.insert( - buffer.end(), - temp_buffer, - temp_buffer + BUFSIZE - strm.avail_out - ); - deflateEnd(&strm); - } + // 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 TCP_socket; diff --git a/Server/Http/Reply.cpp b/Server/Http/Reply.cpp index 1bad643a1..c3c82d295 100644 --- a/Server/Http/Reply.cpp +++ b/Server/Http/Reply.cpp @@ -41,15 +41,16 @@ void Reply::setSize(const unsigned size) { std::vector Reply::toBuffers(){ std::vector buffers; buffers.push_back(ToBuffer(status)); - for (std::size_t i = 0; i < headers.size(); ++i) { - Header& h = headers[i]; + BOOST_FOREACH(const Header & h, headers) { buffers.push_back(boost::asio::buffer(h.name)); buffers.push_back(boost::asio::buffer(seperators)); buffers.push_back(boost::asio::buffer(h.value)); buffers.push_back(boost::asio::buffer(crlf)); } buffers.push_back(boost::asio::buffer(crlf)); - buffers.push_back(boost::asio::buffer(content)); + BOOST_FOREACH(const std::string & line, content) { + buffers.push_back(boost::asio::buffer(line)); + } return buffers; } @@ -70,7 +71,8 @@ std::vector Reply::HeaderstoBuffers(){ Reply Reply::StockReply(Reply::status_type status) { Reply rep; rep.status = status; - rep.content = ToString(status); + rep.content.clear(); + rep.content.push_back( ToString(status) ); rep.headers.resize(3); rep.headers[0].name = "Access-Control-Allow-Origin"; rep.headers[0].value = "*"; @@ -85,7 +87,6 @@ Reply Reply::StockReply(Reply::status_type status) { return rep; } - std::string Reply::ToString(Reply::status_type status) { switch (status) { case Reply::ok: @@ -110,7 +111,7 @@ boost::asio::const_buffer Reply::ToBuffer(Reply::status_type status) { Reply::Reply() : status(ok) { - content.reserve(2 << 20); + } } diff --git a/Server/Http/Reply.h b/Server/Http/Reply.h index 7757729e0..bb4f074c8 100644 --- a/Server/Http/Reply.h +++ b/Server/Http/Reply.h @@ -59,7 +59,7 @@ const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Erro std::vector
headers; std::vector toBuffers(); std::vector HeaderstoBuffers(); - std::string content; + std::vector content; static Reply StockReply(status_type status); void setSize(const unsigned size); Reply(); diff --git a/Server/RequestHandler.h b/Server/RequestHandler.h index bb7dc9ef0..37802fe49 100644 --- a/Server/RequestHandler.h +++ b/Server/RequestHandler.h @@ -85,16 +85,18 @@ public: const 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 += "
";
-                rep.content += request;
-                rep.content += tmp_position_string;
-                rep.content += "
"; + rep.content.push_back( + "Input seems to be malformed close to position " + "
"
+                );
+                rep.content.push_back( request );
+                rep.content.push_back(tmp_position_string);
+                rep.content.push_back("
"); const unsigned end = std::distance(request.begin(), it); for(unsigned i = 0; i < end; ++i) { - rep.content += " "; + rep.content.push_back(" "); } - rep.content += "^
"; + rep.content.push_back("^
"); } else { //parsing done, lets call the right plugin to handle the request BOOST_ASSERT_MSG( diff --git a/Server/RequestParser.h b/Server/RequestParser.h index 03be891cf..9fdbc1d90 100644 --- a/Server/RequestParser.h +++ b/Server/RequestParser.h @@ -42,10 +42,19 @@ public: RequestParser(); void Reset(); - boost::tuple Parse(Request& req, char* begin, char* end, CompressionType * compressionType); + boost::tuple Parse( + Request& req, + char* begin, + char* end, + CompressionType * compressionType + ); private: - boost::tribool consume(Request& req, char input, CompressionType * compressionType); + boost::tribool consume( + Request& req, + char input, + CompressionType * compressionType + ); inline bool isChar(int c); diff --git a/Tools/simpleclient.cpp b/Tools/simpleclient.cpp index 9f5f31c91..f617b462a 100644 --- a/Tools/simpleclient.cpp +++ b/Tools/simpleclient.cpp @@ -98,12 +98,14 @@ int main (int argc, const char * argv[]) { routing_machine.RunQuery(route_parameters, osrm_reply); - std::cout << osrm_reply.content << std::endl; - //attention: super-inefficient hack below: std::stringstream ss; - ss << osrm_reply.content; + BOOST_FOREACH(const std::string & line, osrm_reply.content) { + std::cout << line; + ss << line; + } + std::cout << std::endl; boost::property_tree::ptree pt; boost::property_tree::read_json(ss, pt);