//-----------------------------------------------------------------------------
//
//  $Logfile:: /Quake 2 Engine/Sin/code/game/archive.h                        $
// $Revision:: 9                                                              $
//   $Author:: Jimdose                                                        $
//     $Date:: 11/12/98 2:31a                                                 $
//
// Copyright (C) 1997 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source is may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
// $Log:: /Quake 2 Engine/Sin/code/game/archive.h                             $
// 
// 9     11/12/98 2:31a Jimdose
// Added ReadFile.  Archives now read from pak files
// 
// 8     10/25/98 11:52p Jimdose
// added EXPORT_TEMPLATE
// 
// 7     10/07/98 11:41p Jimdose
// Got savegames working!!!
// Rewrote event archiving
// 
// 6     9/21/98 10:15p Markd
// Putting archiving and unarchiving functions in
// 
// 5     9/21/98 4:21p Markd
// Put in archive functions and rewrote all archive routines
// 
// 4     5/24/98 4:48p Jimdose
// Made char *'s const
// 
// 3     5/08/98 2:50p Jimdose
// Base archivable class is now Class instead of Listener
// 
// 2     5/07/98 10:39p Jimdose
// created file
// 
// 1     5/06/98 8:19p Jimdose
// 
// DESCRIPTION:
// Class for archiving objects
// 

#ifndef __ARCHIVE_H__
#define __ARCHIVE_H__

#include "g_local.h"
#include "str.h"

#define ARCHIVE_NULL_POINTER ( -654321 )
#define ARCHIVE_POINTER_VALID ( 0 )
#define ARCHIVE_POINTER_NULL ( ARCHIVE_NULL_POINTER )
#define ARCHIVE_POINTER_SELF_REFERENTIAL ( -123456 )

enum
	{
   pointer_fixup_normal,
   pointer_fixup_safe
	};

typedef struct
   {
   void **ptr;
   int  index;
   int  type;
   } pointer_fixup_t;

#ifdef EXPORT_TEMPLATE
template class Container<Class *>;
template class Container<pointer_fixup_t *>;
#endif

class ReadFile : public Class
	{
	protected:
		str				filename;
      size_t         length;
      byte           *buffer;
      byte           *pos;

	public:
      CLASS_PROTOTYPE( ReadFile );

							ReadFile();
							~ReadFile();
		void				Close( void );
      const char     *Filename( void );
      size_t         Length( void );
      size_t         Pos( void );
      qboolean       Seek( size_t newpos );
      qboolean       Open( const char *name );
      qboolean       Read( void *dest, size_t size );
	};

class Archiver : public Class
	{
   private:
      Container<Class *>         classpointerList;
      Container<pointer_fixup_t *> fixupList;

	protected:
		str				filename;
		qboolean			fileerror;
		FILE				*file;
      ReadFile       readfile;
		int				archivemode;
      int            numclassespos;

		void				CheckRead( void );
		void				CheckType( int type );
		int            ReadType( void );
		size_t			ReadSize( void );
		void				CheckSize( int type, size_t size );
		void				ReadData( int type, void *data, size_t size );

		void				CheckWrite( void );
		void				WriteType( int type );
		void				WriteSize( size_t size );
		void				WriteData( int type, const void *data, size_t size );

	public:
      CLASS_PROTOTYPE( Archiver );

							Archiver();
							~Archiver();
		void				FileError( const char *fmt, ... );
		void				Close( void );

		void				Read( str &name );
		void				Read( const char *name );

      //
      // return methods
      //
		Vector			ReadVector( void );
		Quat			   ReadQuat( void );
		int				ReadInteger( void );
		unsigned			ReadUnsigned( void );
		byte				ReadByte( void );
		char				ReadChar( void );
		short				ReadShort( void );
		unsigned short	ReadUnsignedShort( void );
		float				ReadFloat( void );
		double			ReadDouble( void );
		qboolean			ReadBoolean( void );
		str				ReadString( void );
		Event 			ReadEvent( void );
      //
      // ptr methods
      //
		void  			ReadVector( Vector * vec );
		void  			ReadQuat( Quat * quat );
		void				ReadInteger( int * num );
		void  			ReadUnsigned( unsigned * unum);
		void				ReadByte( byte * num );
		void				ReadChar( char * ch );
		void				ReadShort( short * num );
		void           ReadUnsignedShort( unsigned short * num );
		void           ReadFloat( float * num );
		void			   ReadDouble( double * num );
		void  			ReadBoolean( qboolean * bBool );
		void  			ReadString( str * string );
		void           ReadObjectPointer( Class ** ptr );
		void           ReadSafePointer( SafePtrBase * ptr );
		void           ReadEvent( Event * ev );

		void				ReadRaw( void *data, size_t size );
		Class				*ReadObject( void );
		Class				*ReadObject( Class *obj );

		void				Create( str &name );
		void				Create( const char *name );
		void				WriteVector( Vector &v );
		void  			WriteQuat( Quat &quat );
		void				WriteInteger( int v );
		void				WriteUnsigned( unsigned v );
		void				WriteByte( byte v );
		void				WriteChar( char v );
		void				WriteShort( short v );
		void				WriteUnsignedShort( unsigned short v );
		void				WriteFloat( float v );
		void				WriteDouble( double v );
		void				WriteBoolean( qboolean v );
		void				WriteRaw( const void *data, size_t size );
		void				WriteString( str &string );
		void				WriteObject( Class *obj );
		void           WriteObjectPointer( Class * ptr );
		void           WriteSafePointer( Class * ptr );
		void           WriteEvent( Event &ev );
	};

inline void Archiver::Read
   (
   str &name
   )

   {
   Read( name.c_str() );
   }

inline void Archiver::Create
   (
   str &name
   )

   {
   Create( name.c_str() );
   }

#endif /* archive.h */
