/*
 * CyclicString.h
 *
 * Created on: Sep 27, 2017
 * Author: Jan Travnicek
 */

#ifndef _STRING_CYCLIC_STRING_H_
#define _STRING_CYCLIC_STRING_H_

#include <string/CyclicString.h>
#include <core/stringApi.hpp>

#include <string/StringFromStringLexer.h>

#include <string/string/common/StringFromStringParserCommon.h>
#include <string/string/common/StringToStringComposerCommon.h>

namespace core {

template<class SymbolType >
struct stringApi < string::CyclicString < SymbolType > > {
	static string::CyclicString < SymbolType > parse ( std::istream & input );
	static bool first ( std::istream & input );
	static void compose ( std::ostream & output, const string::CyclicString < SymbolType > & string );
};

template<class SymbolType >
string::CyclicString < SymbolType > stringApi < string::CyclicString < SymbolType > >::parse ( std::istream & input ) {
	string::StringFromStringLexer::Token token = string::StringFromStringLexer::next ( input );
	if ( token.type == string::StringFromStringLexer::TokenType::LESS ) {
		ext::vector < SymbolType > data = string::StringFromStringParserCommon::parseContent < SymbolType > ( input );
		token = string::StringFromStringLexer::next(input);
		if ( token.type == string::StringFromStringLexer::TokenType::GREATER ) {
			return string::CyclicString < SymbolType > ( data );
		} else {
			throw exception::CommonException ( "Invalid linear string terminating character" );
		}
	} else {
		throw exception::CommonException ( "Unrecognised CyclicString token." );
	}
}

template<class SymbolType >
bool stringApi < string::CyclicString < SymbolType > >::first ( std::istream & input ) {
	string::StringFromStringLexer::Token token = string::StringFromStringLexer::next ( input );
	bool res = token.type == string::StringFromStringLexer::TokenType::LESS;
	string::StringFromStringLexer::putback ( input, token );
	return res;
}

template<class SymbolType >
void stringApi < string::CyclicString < SymbolType > >::compose ( std::ostream & output, const string::CyclicString < SymbolType > & string ) {
	output << "<";
	string::StringToStringComposerCommon::composeContent ( output, string.getContent ( ) );
	output << ">";
}

} /* namespace core */

#endif /* _STRING_CYCLIC_STRING_H_ */
