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

#pragma once

#include <string/LinearString.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::LinearString < SymbolType > > {
	static string::LinearString < SymbolType > parse ( std::istream & input );
	static bool first ( std::istream & input );
	static void compose ( std::ostream & output, const string::LinearString < SymbolType > & string );
};

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

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

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

} /* namespace core */

