From c25d64145f4b597533bcd6c3f5b5aee05773da75 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Radovan=20=C4=8Cerven=C3=BD?= <radovan.cerveny@gmail.com>
Date: Mon, 21 Mar 2016 22:56:06 +0100
Subject: [PATCH] basic html output

---
 .../processor/MeasurementProcessorOutput.cpp  | 116 +++++++++++++-----
 .../processor/MeasurementProcessorOutput.hpp  |  15 ++-
 2 files changed, 96 insertions(+), 35 deletions(-)

diff --git a/alib2measurepp/src/processor/MeasurementProcessorOutput.cpp b/alib2measurepp/src/processor/MeasurementProcessorOutput.cpp
index d882df5037..164ef54a2e 100644
--- a/alib2measurepp/src/processor/MeasurementProcessorOutput.cpp
+++ b/alib2measurepp/src/processor/MeasurementProcessorOutput.cpp
@@ -3,6 +3,7 @@
  */
 
 #include "MeasurementProcessorOutput.hpp"
+#include "sax/SaxComposeInterface.h"
 #include <set>
 #include <iostream>
 
@@ -49,18 +50,88 @@ void MeasurementProcessorOutput::outputStats ( std::ostream & os, const Measurem
 }
 
 void MeasurementProcessorOutput::outputCsv ( std::ostream & os, const MeasurementProvisionerResults & mpr, const MeasurementProcessorOutput & mpo ) {
+	for ( const Table & table : MeasurementProcessorOutput::getTableRepresentation ( mpr, mpo ) ) {
+		os << "# " << table.description << std::endl;
 
-	struct Row {
-		std::string					input;
-		std::vector < std::string > data;
-	};
+		for ( auto it = table.header.begin ( ); it != table.header.end ( ); ++it ) {
+			if ( it != table.header.begin ( ) ) os << ",";
 
-	struct Table {
-		std::string					description;
-		std::vector < std::string > header;
-		std::vector < Row >			rows;
-	};
+			os << * it;
+		}
+
+		os << std::endl;
+
+		for ( const Row & row : table.rows ) {
+			os << row.input;
+
+			for ( const std::string & datum : row.data )
+				os << "," << datum;
+
+			os << std::endl;
+		}
+	}
+}
+
+void MeasurementProcessorOutput::outputHtml ( std::ostream & os, const MeasurementProvisionerResults & mpr, const MeasurementProcessorOutput & mpo ) {
+	std::deque < sax::Token > tokens;
+
+	tokens.emplace_back ( "html", sax::Token::TokenType::START_ELEMENT );
+	tokens.emplace_back ( "head", sax::Token::TokenType::START_ELEMENT );
+	tokens.emplace_back ( "style", sax::Token::TokenType::START_ELEMENT );
+	tokens.emplace_back ( "table { border-collapse: collapse; background-color: #aaa } th, td { padding: 0.25rem; text-align: left; border: 1px solid #ccc; } tbody tr:nth-child(odd) { background: #ddd; }", sax::Token::TokenType::CHARACTER );
+	tokens.emplace_back ( "style", sax::Token::TokenType::END_ELEMENT );
+	tokens.emplace_back ( "title", sax::Token::TokenType::START_ELEMENT );
+	tokens.emplace_back ( "Measurement results", sax::Token::TokenType::CHARACTER );
+	tokens.emplace_back ( "title", sax::Token::TokenType::END_ELEMENT );
+	tokens.emplace_back ( "head", sax::Token::TokenType::END_ELEMENT );
+	tokens.emplace_back ( "body", sax::Token::TokenType::START_ELEMENT );
+
+	for ( const Table & table : MeasurementProcessorOutput::getTableRepresentation ( mpr, mpo ) ) {
+
+		tokens.emplace_back ( "div", sax::Token::TokenType::START_ELEMENT );
+		tokens.emplace_back ( "h3", sax::Token::TokenType::START_ELEMENT );
+		tokens.emplace_back ( table.description, sax::Token::TokenType::CHARACTER );
+		tokens.emplace_back ( "h3", sax::Token::TokenType::END_ELEMENT );
+
+		tokens.emplace_back ( "table", sax::Token::TokenType::START_ELEMENT );
+
+		tokens.emplace_back ( "tr", sax::Token::TokenType::START_ELEMENT );
+
+		for ( const std::string & head : table.header ) {
+			tokens.emplace_back ( "th", sax::Token::TokenType::START_ELEMENT );
+			tokens.emplace_back ( head, sax::Token::TokenType::CHARACTER );
+			tokens.emplace_back ( "th", sax::Token::TokenType::END_ELEMENT );
+		}
+
+		tokens.emplace_back ( "tr", sax::Token::TokenType::END_ELEMENT );
+
+		for ( const Row & row : table.rows ) {
+			tokens.emplace_back ( "tr", sax::Token::TokenType::START_ELEMENT );
+
+			tokens.emplace_back ( "td", sax::Token::TokenType::START_ELEMENT );
+			tokens.emplace_back ( row.input, sax::Token::TokenType::CHARACTER );
+			tokens.emplace_back ( "td", sax::Token::TokenType::END_ELEMENT );
 
+			for ( const std::string & datum : row.data ) {
+				tokens.emplace_back ( "td", sax::Token::TokenType::START_ELEMENT );
+				tokens.emplace_back ( datum, sax::Token::TokenType::CHARACTER );
+				tokens.emplace_back ( "td", sax::Token::TokenType::END_ELEMENT );
+			}
+
+			tokens.emplace_back ( "tr", sax::Token::TokenType::END_ELEMENT );
+		}
+
+		tokens.emplace_back ( "table", sax::Token::TokenType::END_ELEMENT );
+		tokens.emplace_back ( "div", sax::Token::TokenType::END_ELEMENT );
+	}
+
+	tokens.emplace_back ( "body", sax::Token::TokenType::END_ELEMENT );
+	tokens.emplace_back ( "html", sax::Token::TokenType::END_ELEMENT );
+
+	sax::SaxComposeInterface::printStream ( os, tokens );
+}
+
+std::vector < MeasurementProcessorOutput::Table > MeasurementProcessorOutput::getTableRepresentation ( const MeasurementProvisionerResults & mpr, const MeasurementProcessorOutput & mpo ) {
 	 // this starts to get ugly
 	std::vector < std::string > masterHeader {
 		"input"
@@ -96,29 +167,7 @@ void MeasurementProcessorOutput::outputCsv ( std::ostream & os, const Measuremen
 		}
 	}
 
-	for ( const Table & table : tables ) {
-		os << "# " << table.description << std::endl;
-
-		for ( auto it = table.header.begin ( ); it != table.header.end ( ); ++it ) {
-			if ( it != table.header.begin ( ) ) os << ",";
-
-			os << * it;
-		}
-
-		os << std::endl;
-
-		for ( const Row & row : table.rows ) {
-			os << row.input;
-
-			for ( const std::string & datum : row.data )
-				os << "," << datum;
-
-			os << std::endl;
-		}
-	}
-}
-
-void MeasurementProcessorOutput::outputHtml ( std::ostream &, const MeasurementProvisionerResults &, const MeasurementProcessorOutput & ) {
+	return tables;
 }
 
 std::string MeasurementProcessorOutput::getData ( const MeasurementFrame & frame, const MeasurementProcessorOutput & mpo ) {
@@ -132,11 +181,10 @@ std::string MeasurementProcessorOutput::getData ( const MeasurementFrame & frame
 		return std::to_string ( frame.memory.highWatermark - frame.memory.startHeapUsage );
 
 	case OutputEngine::COUNTER:
+
 		 // FIXME
 		return "";
 	}
-
-	return "";
 }
 
 }
diff --git a/alib2measurepp/src/processor/MeasurementProcessorOutput.hpp b/alib2measurepp/src/processor/MeasurementProcessorOutput.hpp
index 40637bc6c0..f6bdbeab93 100644
--- a/alib2measurepp/src/processor/MeasurementProcessorOutput.hpp
+++ b/alib2measurepp/src/processor/MeasurementProcessorOutput.hpp
@@ -28,7 +28,20 @@ struct MeasurementProcessorOutput {
 	static void outputCsv ( std::ostream &, const MeasurementProvisionerResults &, const MeasurementProcessorOutput & );
 	static void outputHtml ( std::ostream &, const MeasurementProvisionerResults &, const MeasurementProcessorOutput & );
 
-	static std::string getData ( const MeasurementFrame &, const MeasurementProcessorOutput & );
+private:
+	struct Row {
+		std::string					input;
+		std::vector < std::string > data;
+	};
+
+	struct Table {
+		std::string					description;
+		std::vector < std::string > header;
+		std::vector < Row >			rows;
+	};
+
+	static std::vector < Table > getTableRepresentation ( const MeasurementProvisionerResults &, const MeasurementProcessorOutput & );
+	static std::string			 getData ( const MeasurementFrame &, const MeasurementProcessorOutput & );
 };
 
 }
-- 
GitLab