From cdb6f5149e8d7ec4aa0d5d2eb80c31db11f39eba Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Tue, 6 Jun 2017 18:54:12 +0200
Subject: [PATCH] expose comparison of strings

---
 acompare2/src/StringCompare.cpp | 80 ++++++++++++++++++++++++++++
 acompare2/src/StringCompare.h   | 50 ++++++++++++++++++
 acompare2/src/acompare.cpp      | 92 ++++++++++++++++++---------------
 3 files changed, 181 insertions(+), 41 deletions(-)
 create mode 100644 acompare2/src/StringCompare.cpp
 create mode 100644 acompare2/src/StringCompare.h

diff --git a/acompare2/src/StringCompare.cpp b/acompare2/src/StringCompare.cpp
new file mode 100644
index 0000000000..4946e9c3aa
--- /dev/null
+++ b/acompare2/src/StringCompare.cpp
@@ -0,0 +1,80 @@
+/*
+ * StringCompare.cpp
+ *
+ *  Created on: Apr 4, 2017
+ *      Author: Tomas Pecka
+ */
+
+#include "StringCompare.h"
+
+#include "string/CyclicString.h"
+#include "string/LinearString.h"
+
+bool StringCompare::testCompare ( const string::LinearString < > & a, const string::LinearString < > & b ) {
+	return a.getContent ( ) == b.getContent ( ) && a.getAlphabet ( ) == b.getAlphabet ( );
+}
+
+bool StringCompare::testCompare ( const string::CyclicString < > &, const string::CyclicString < > & ) {
+	throw "NYI";
+}
+
+template < class T >
+void StringCompare::setCompare ( const std::set < T > a, const std::set < T > b ) {
+	std::set < T > aMinusB;
+	std::set_difference ( a.begin ( ), a.end ( ), b.begin ( ), b.end ( ), std::inserter ( aMinusB, aMinusB.begin ( ) ) );
+
+	std::set < T > bMinusA;
+	std::set_difference ( b.begin ( ), b.end ( ), a.begin ( ), a.end ( ), std::inserter ( bMinusA, bMinusA.begin ( ) ) );
+
+	for ( typename std::set < T >::const_iterator iter = aMinusB.begin ( ); iter != aMinusB.end ( ); iter++ )
+		std::cout << "< " << * iter << std::endl;
+
+	std::cout << "---" << std::endl;
+
+	for ( typename std::set < T >::const_iterator iter = bMinusA.begin ( ); iter != bMinusA.end ( ); iter++ )
+		std::cout << "> " << * iter << std::endl;
+}
+
+template < class T >
+void StringCompare::vectorCompare ( const std::vector < T > a, const std::vector < T > b ) {
+	std::vector < T > aMinusB;
+	std::set_difference ( a.begin ( ), a.end ( ), b.begin ( ), b.end ( ), std::inserter ( aMinusB, aMinusB.begin ( ) ) );
+
+	std::vector < T > bMinusA;
+	std::set_difference ( b.begin ( ), b.end ( ), a.begin ( ), a.end ( ), std::inserter ( bMinusA, bMinusA.begin ( ) ) );
+
+	for ( typename std::vector < T >::const_iterator iter = aMinusB.begin ( ); iter != aMinusB.end ( ); iter++ )
+		std::cout << "< " << * iter << std::endl;
+
+	std::cout << "---" << std::endl;
+
+	for ( typename std::vector < T >::const_iterator iter = bMinusA.begin ( ); iter != bMinusA.end ( ); iter++ )
+		std::cout << "> " << * iter << std::endl;
+}
+
+void StringCompare::printCompare ( const string::CyclicString < > &, const string::CyclicString < > & ) {
+	throw "NYI";
+}
+
+void StringCompare::printCompare ( const string::LinearString < > & a, const string::LinearString < > & b ) {
+	std::cout << "StringCompare" << std::endl;
+
+	if ( a.getAlphabet ( ) != b.getAlphabet ( ) ) {
+		std::cout << "Alphabet" << std::endl;
+
+		StringCompare::setCompare ( a.getAlphabet ( ), b.getAlphabet ( ) );
+	}
+
+	if ( a.getContent ( ) != b.getContent ( ) ) {
+		std::cout << "Content" << std::endl;
+
+		StringCompare::vectorCompare ( a.getContent ( ), b.getContent ( ) );
+	}
+}
+
+auto StringCompareLinear = StringCompare::RegistratorWrapper < int, string::LinearString < >, string::LinearString < > > ( StringCompare::compare );
+auto StringCompareCyclic = StringCompare::RegistratorWrapper < int, string::CyclicString < >, string::CyclicString < > > ( StringCompare::compare );
+
+int StringCompare::compare ( const string::String & a, const string::String & b ) {
+	return dispatch ( a.getData ( ), b.getData ( ) );
+}
diff --git a/acompare2/src/StringCompare.h b/acompare2/src/StringCompare.h
new file mode 100644
index 0000000000..221c309c38
--- /dev/null
+++ b/acompare2/src/StringCompare.h
@@ -0,0 +1,50 @@
+/*
+ * StringCompare.h
+ *
+ *  Created on: Apr 4, 2017
+ *      Author: Tomas Pecka
+ */
+
+#ifndef STRING_COMPARE_H_
+#define STRING_COMPARE_H_
+
+#include <core/multipleDispatch.hpp>
+#include <ostream>
+
+#include <string/String.h>
+#include <string/StringFeatures.h>
+
+#include <utility>
+#include <vector>
+
+class StringCompare : public std::DoubleDispatch < StringCompare, int, const string::StringBase &, const string::StringBase & > {
+private:
+	static bool testCompare ( const string::LinearString < > & a, const string::LinearString < > & b );
+	static void printCompare ( const string::LinearString < > & a, const string::LinearString < > & b );
+
+	static bool testCompare ( const string::CyclicString < > & a, const string::CyclicString < > & b );
+	static void printCompare ( const string::CyclicString < > & a, const string::CyclicString < > & b );
+
+	template < class T >
+	static void setCompare ( const std::set < T > a, const std::set < T > b );
+	template < class T >
+	static void vectorCompare ( const std::vector < T > a, const std::vector < T > b );
+
+public:
+	template < class T >
+	static int compare ( const T & a, const T & b );
+
+	static int compare ( const string::String & a, const string::String & b );
+};
+
+template < class T >
+int StringCompare::compare ( const T & a, const T & b ) {
+	if ( !StringCompare::testCompare ( a, b ) ) {
+		StringCompare::printCompare ( a, b );
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+#endif /* GRAMMAR_COMPARE_H_ */
diff --git a/acompare2/src/acompare.cpp b/acompare2/src/acompare.cpp
index 16cf4db6e8..7a21066115 100644
--- a/acompare2/src/acompare.cpp
+++ b/acompare2/src/acompare.cpp
@@ -5,85 +5,95 @@
  *      Author: Jan Travnicek
  */
 
-#include <tclap/CmdLine.h>
 #include <global/GlobalData.h>
 #include <measure>
 #include <sax/FromXMLParserHelper.h>
+#include <tclap/CmdLine.h>
 
-#include "factory/XmlDataFactory.hpp"
 #include "exception/CommonException.h"
+#include "factory/XmlDataFactory.hpp"
 
 #include "AutomatonCompare.h"
 #include "GrammarCompare.h"
+#include "StringCompare.h"
 
-int main(int argc, char** argv) {
+int main ( int argc, char * * argv ) {
 	try {
 		common::GlobalData::argc = argc;
 		common::GlobalData::argv = argv;
 
-		TCLAP::CmdLine cmd("Regexp derivative compute binary", ' ', "0.01");
+		TCLAP::CmdLine cmd ( "Regexp derivative compute binary", ' ', "0.01" );
 
-		TCLAP::UnlabeledValueArg<std::string> input1(	"input1",	"The first input to compare",	true,	"-",		"file");
-		cmd.add( input1 );
+		TCLAP::UnlabeledValueArg < std::string > input1 ( "input1", "The first input to compare", true, "-", "file" );
+		cmd.add ( input1 );
 
-		TCLAP::UnlabeledValueArg<std::string> input2(	"input2",	"The second input to compare",	true,	"-",		"file");
-		cmd.add( input2 );
+		TCLAP::UnlabeledValueArg < std::string > input2 ( "input2", "The second input to compare", true, "-", "file" );
+		cmd.add ( input2 );
 
-		TCLAP::SwitchArg measure(		"m",	"measure",	"Measure times",		false);
-		cmd.add( measure );
+		TCLAP::SwitchArg measure ( "m", "measure", "Measure times", false );
+		cmd.add ( measure );
 
-		TCLAP::SwitchArg verbose(		"v",	"verbose",	"Be verbose",			false);
-		cmd.add( verbose );
+		TCLAP::SwitchArg verbose ( "v", "verbose", "Be verbose", false );
+		cmd.add ( verbose );
 
-		cmd.parse(argc, argv);
+		cmd.parse ( argc, argv );
 
-		if(verbose.isSet())
+		if ( verbose.isSet ( ) )
 			common::GlobalData::verbose = true;
-		if(measure.isSet())
+
+		if ( measure.isSet ( ) )
 			common::GlobalData::measure = true;
 
-		measurements::start("Overal", measurements::Type::OVERALL);
-		measurements::start("Input read", measurements::Type::AUXILIARY);
+		measurements::start ( "Overal", measurements::Type::OVERALL );
+		measurements::start ( "Input read", measurements::Type::AUXILIARY );
 
-		std::deque<sax::Token> tokens1 = sax::FromXMLParserHelper::parseInput(input1);
-		std::deque<sax::Token> tokens2 = sax::FromXMLParserHelper::parseInput(input2);
+		std::deque < sax::Token > tokens1 = sax::FromXMLParserHelper::parseInput ( input1 );
+		std::deque < sax::Token > tokens2 = sax::FromXMLParserHelper::parseInput ( input2 );
 
 		int res;
 
-		if(alib::XmlDataFactory::first<automaton::Automaton>(tokens1) && alib::XmlDataFactory::first<automaton::Automaton>(tokens2)) {
-			automaton::Automaton automaton1 = alib::XmlDataFactory::fromTokens (std::move(tokens1));
-			automaton::Automaton automaton2 = alib::XmlDataFactory::fromTokens (std::move(tokens2));
+		if ( alib::XmlDataFactory::first < automaton::Automaton > ( tokens1 ) && alib::XmlDataFactory::first < automaton::Automaton > ( tokens2 ) ) {
+			automaton::Automaton automaton1 = alib::XmlDataFactory::fromTokens ( std::move ( tokens1 ) );
+			automaton::Automaton automaton2 = alib::XmlDataFactory::fromTokens ( std::move ( tokens2 ) );
+
+			measurements::end ( );
+			measurements::start ( "Compare", measurements::Type::MAIN );
+
+			res = AutomatonCompare::compare ( automaton1, automaton2 );
+		} else if ( alib::XmlDataFactory::first < grammar::Grammar > ( tokens1 ) && alib::XmlDataFactory::first < grammar::Grammar > ( tokens2 ) ) {
+			grammar::Grammar grammar1 = alib::XmlDataFactory::fromTokens ( std::move ( tokens1 ) );
+			grammar::Grammar grammar2 = alib::XmlDataFactory::fromTokens ( std::move ( tokens2 ) );
 
-			measurements::end();
-			measurements::start("Compare", measurements::Type::MAIN);
+			measurements::end ( );
+			measurements::start ( "Compare", measurements::Type::MAIN );
 
-			res = AutomatonCompare::compare(automaton1, automaton2);
-		} else if(alib::XmlDataFactory::first<grammar::Grammar>(tokens1) && alib::XmlDataFactory::first<grammar::Grammar>(tokens2)) {
-			grammar::Grammar grammar1 = alib::XmlDataFactory::fromTokens (std::move(tokens1));
-			grammar::Grammar grammar2 = alib::XmlDataFactory::fromTokens (std::move(tokens2));
+			res = GrammarCompare::compare ( grammar1, grammar2 );
+		} else if ( alib::XmlDataFactory::first < string::String > ( tokens1 ) && alib::XmlDataFactory::first < string::String > ( tokens2 ) ) {
+			string::String string1 = alib::XmlDataFactory::fromTokens ( std::move ( tokens1 ) );
+			string::String string2 = alib::XmlDataFactory::fromTokens ( std::move ( tokens2 ) );
 
-			measurements::end();
-			measurements::start("Compare", measurements::Type::MAIN);
+			measurements::end ( );
+			measurements::start ( "Compare", measurements::Type::MAIN );
 
-			res = GrammarCompare::compare(grammar1, grammar2);
+			res = StringCompare::compare ( string1, string2 );
 		} else {
-			throw exception::CommonException("Only automata and grammars can be compared.");
+			throw exception::CommonException ( "Only automata, grammars and strings can be compared." );
 		}
 
-		measurements::end();
-		measurements::end();
+		measurements::end ( );
+		measurements::end ( );
 
 		return res;
-	} catch (const exception::CommonException& exception) {
-		alib::XmlDataFactory::toStdout(exception);
+	} catch ( const exception::CommonException & exception ) {
+		alib::XmlDataFactory::toStdout ( exception );
 		return 1;
-	} catch(const TCLAP::ArgException& exception) {
-		std::cerr << exception.error() << std::endl;
+	} catch ( const TCLAP::ArgException & exception ) {
+		std::cerr << exception.error ( ) << std::endl;
 		return 2;
-	} catch (const std::exception& exception) {
-		std::cerr << "Exception caught: " << exception.what() << std::endl;
+	} catch ( const std::exception & exception ) {
+		std::cerr << "Exception caught: " << exception.what ( ) << std::endl;
 		return 3;
-	} catch(...) {
+	} catch ( ... ) {
 		std::cerr << "Unknown exception caught." << std::endl;
 		return 127;
 	}
-- 
GitLab