/****************************************************************************************

	MCStreamBased.h

	Copyright: (c) 2001 Eovia Corp. All rights reserved.

  	Author:	Ray Dream (STRMBASD.H) 
  	Date:	3/2/98

  	Revision History

  	when		who			what & why
	==========	==========	======================================================
	6/10/99		Ian			Array API changes.
	9/25/98		Eml			Removed gSaveVersionNb
	8/3/98		Ian			TMCPtrArray no longer needs * argument.
	5/27/98		Greg		Fixed protection (conflict with old StreamBased.h)
	3/5/98		Greg		Initial conversion

*****************************************************************************************/

#ifndef __MCSTREAMBASED__
#define __MCSTREAMBASED__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "MCBasicTypes.h"

template <class T> class TMCPtrArray;

class TMCiostream;

/// \addtogroup MCCore
/// \{


/// TMCStreamBased handles all the I/O grammar.
/// You must at least override ReadAttribute() and WriteAttributes().
/// Override GetKeyword() if you want to use Write() (see note below).
/// Override InitOnNew() if needed.
/// Call ReadListAttribute() and WriteListAttribute(), and override 
/// ReadListElement() and WriteListElement() if you have
/// a list of abjects as a field.
///
/// Using Write() or DoWriteWithKeyword():
/// Write() is to be used when an object 'knows' its own keyword.
/// However, it is generaly more convenient to use DoWriteWithKeyword(),
/// for the following reason. Say you have an object that has another
/// object as a field. In ReadAttribute(), you catch the field's keyword,
/// instance the object, and call fSubObject->Read(). Fine.
/// In WriteAttributes() you have two choices. If you want to use Write(),
/// you will have to override the GetKeyword() method of the sub-object.
/// The problem with this is that you end up with the field keyword defined
/// at two different places: in the main object's ReadAttribute(), and in
/// the sub-object's GetKeyword().
/// For this reason, it is better to call DoWriteWithKeyword() instead, so
/// the sub-object's keyword is at the same level: in ReadAttribute()
/// and WriteAttributes() of the main object.
///
class TMCStreamBased	
{
	public:

						TMCStreamBased();
	enum
	{
		kStreamKeyWord_List		= '****',
		kStreamKeyWord_Default	= '@@@@'
	};

	protected:

						~TMCStreamBased();

	public:

		virtual void		InitOnNew			();
	
		/// Use this to read the top level of file that don't have begin and end tokens around them
		///
		virtual void		TopLevelRead		(TMCiostream& stream);
			
		
		virtual void		Read				(TMCiostream& stream);
		virtual void		ReadAttribute		(int32 keyword, TMCiostream& stream);
		virtual void		ReadListAttribute	(int32 keyword, TMCiostream& stream, TMCPtrArray<void>* list);
		virtual void		ReadListElement		(int32 keyword, TMCiostream& stream, TMCPtrArray<void>* list);
	
		virtual void		Write				(TMCiostream& stream) const;
		virtual void		WriteAttributes		(TMCiostream& stream) const;
		virtual void		WriteListAttribute	(int32 keyword, TMCiostream& stream, TMCPtrArray<void>* list) const;
		virtual void		WriteListElement	(int32 listKeyword, TMCiostream& stream, TMCPtrArray<void>* list, int32 index) const;
		virtual void		WriteListNbAttribute(int32 keyword, TMCiostream& stream, int32 numElements) const;
	
		void 				DoWriteWithKeyword	(TMCiostream& stream, int32 keyword) const;
		void 				DoReadSkipKeyword	(TMCiostream& stream);

		virtual FourCharT	GetKeyword			() const;

		static boolean sDidSkip;
		static boolean sDoSkip;
};

/// \}

//******************************************************************

// ****************************************************************************
//							CWhileReadingAttribute	
// 
/// Not used in the SDK.
///
class CWhileReadingAttribute	
{
	public:
				CWhileReadingAttribute(boolean DoSkip);
				~CWhileReadingAttribute();

		void 	Clean			();

		boolean DidReadAttribute();
	
		boolean fOldDoSkip;
		boolean fOldDidSkip;
		boolean fDidSkip;
		boolean fCleaned;
};


#endif