/**********************************************************************
 *<
	FILE: appio.h

	DESCRIPTION:  General chunk-ifying code: useful for writing 
	   hierarchical data structures to a linear stream, such as
	   an AppData block.

	CREATED BY: Dan Silva

	HISTORY: created 3/24/97

 *>	Copyright (c) 1994, All Rights Reserved.
 **********************************************************************/

#ifndef __APPIO__H
#define __APPIO__H

#include "maxheap.h"
#include <strbasic.h>

//------------------------------------------------------------------------
// AppSave will write hierarchical chunks into a private buffer, enlarging 
//  it as needed.  When completed, use the methods BufferPtr() and 
// NBytesWritten() to get at this buffer. ( AppSave will delete the buffer in 
// its DeleteThis() method , so you need to copy the buffer to save the data.)

// The chunk hierarchy should always have a single highest level chunk.
// Chunks can be nested to any depth.
// A Chunk can contain either sub-chunks, or data, but not both.

//   For example:
//
//	AppSave *asave = NewAppSave(1000);
//	asave->BeginChunk(MAIN_CHUNK);
//	   asave->BeginChunk(CHUNK1);
//      .. write data 
//	   asave->EndChunk();
//
//	   asave->BeginChunk(CHUNK2);
//      .. write data 
//	   asave->EndChunk();
//
//	   asave->BeginChunk(CHUNK3);
//      .. write data 
//	   asave->EndChunk();
//	asave->EndChunk();  // end MAIN_CHUNK


class AppSave: public MaxHeapOperators {
	protected:
		~AppSave() {}
	public:
		virtual void DeleteThis()=0;
		
		// After saving, use this to get pointer to the buffer created.
		virtual BYTE *BufferPtr()=0;

		// This tells how many bytes were written in the buffer.
		virtual int NBytesWritten()=0;
		
		// Begin a chunk.
		virtual void BeginChunk(USHORT id)=0;

		// End a chunk, and back-patch the length.
		virtual void EndChunk()=0;

		virtual int CurChunkDepth()=0;  // for checking balanced BeginChunk/EndChunk

		// write a block of bytes to the output stream.
		virtual IOResult Write(const void  *buf, ULONG nbytes, ULONG *nwrit)=0;

		// Write character strings
		virtual IOResult WriteWString(const char *str)=0;
		virtual IOResult WriteWString(const mwchar_t *str)=0;
		virtual IOResult WriteCString(const char *str)=0;
		virtual IOResult WriteCString(const mwchar_t *str)=0;

		};

//------------------------------------------------------------------------
// AppLoad takes a chunk-ified data stream, and provides routines for 
// decoding it. 

class AppLoad: public MaxHeapOperators {
	protected:
		~AppLoad() {};
	public:
		virtual void DeleteThis()=0;
			
		// if OpenChunk returns IO_OK, use following 3 function to get the 
		// info about the chunk. IO_END indicates no more chunks at this level
		virtual IOResult OpenChunk()=0;

		// These give info about the most recently opened chunk
		virtual USHORT CurChunkID()=0;
		virtual ChunkType CurChunkType()=0;
		virtual	ULONG CurChunkLength()=0;  // chunk length NOT including header
		virtual	int CurChunkDepth()=0;  // for checking balanced OpenChunk/CloseChunk

		// close the currently opened chunk, and position at the next chunk
		//  return of IO_ERROR indicates there is no open chunk to close
		virtual IOResult CloseChunk()=0;

		// Look at the next chunk ID without opening it.
		// returns 0 if no more chunks
		virtual	USHORT PeekNextChunkID()=0;

		// Read a block of bytes from the output stream.
		virtual IOResult Read(void  *buf, ULONG nbytes, ULONG *nread )=0;

		// Read a string from a string chunk assumes chunk is already open, 
		// it will NOT close the chunk. Sets buf to point
		// to a char string.  Don't delete buf: ILoad will take care of it.

		//   Read a string that was stored as Wide chars. 
		virtual IOResult ReadWStringChunk(char** buf)=0;
		virtual IOResult ReadWStringChunk(mwchar_t** buf)=0;

		//   Read a string that was stored as single byte chars
		virtual IOResult ReadCStringChunk(char** buf)=0;
		virtual IOResult ReadCStringChunk(mwchar_t** buf)=0;


	};


// Create a new AppLoad for reading chunks out of buf:
// bufSize specifies the number of bytes that are valid in
// buf.. 
CoreExport AppLoad *NewAppLoad(BYTE *buf, int bufSize);

// Create a new AppSave for writing chunks
// InitbufSize is the initial size the internal buffer is allocated to.
// It will be enlarged if necessary.
CoreExport AppSave *NewAppSave(int initBufSize);

#endif