/*********************************************************************
 * This file is part of the cpplibs suite.
 *
 * Copyright (C) 2001 Topi Mäenpää
 * All rights reserved.
 *
 * This program is free software. You can redistribute and/or modify
 * it under the terms of the free software licence found in the
 * accompanying file "COPYING". The licence terms must always be
 * redistributed with this source file. The above copyright notice
 * must be reproduced in all modified and unmodified copies of this
 * source file.
 *
 * $Revision: 1.7 $
 *********************************************************************/

#include "Serialization.h"

#include "StreamTokenizer.h"
#include "Util.h"
#include <memory>

using namespace std;
using namespace util::io;

namespace util
{
	Serializable* Serialization::readObject(istream& in) throw (IOException&)
	{
		StreamTokenizer reader;
		char *wordChars = ":0123456789";
		for (int i=0;i<11;i++)
			reader.attribute(wordChars[i]) = TOKEN_WORD;

		auto_ptr<StreamTokenizer::Token> token(reader.getNextToken(in));
		if (token->getType() != TOKEN_WORD)
			throw IOException("Serialization::readObject(istream&): excepting a class name.");

		char chr;
		in.read(&chr,1);
		string params;
		if (in && chr == '<') //template parameters start
			{
				params += chr;
				int openCount = 1;
				while (openCount)
					{
						in.read(&chr,1);
						if (!in)
							throw IOException("Serialization::readObject(istream&): unexpected end of input when reading template parameters.");
						if (chr == '<')
							openCount++;
						else if (chr == '>')
							openCount--;
						params += chr;
					}
			}

		string word = ((StreamTokenizer::WordToken*)token.get())->getWord();
		string className = _bStripTemplateParams ? word : (word + params);
		Serializer *const * s = get(className);

		if (!s)
			throw IOException("Serialization::readObject(istream&): no serializer found for a class.");

		for (int i=params.size();i--;)
			in.putback(params[i]);
		for (int i=word.size();i--;)
			in.putback(word[i]);

		return (*s)->readFromStream(in);
	}

	void Serialization::writeObject(ostream& out, const Serializable& obj) throw (IOException&)
	{
		string className = _bStripTemplateParams ? Util::stripTemplateParameters(Util::getClassName(obj)) : Util::getClassName(obj);
		Serializer *const * s = get(className);
		if (!s)
			throw IOException("Serialization::writeObject(ostream&,Serializable&): no serializer found for a class.");

		(*s)->writeToStream(out,obj);
	}
}
