#ifndef BRCHARIT_H
#define BRCHARIT_H
//========================================================================================
//
//     File:		BRCharIt.h
//     Release Version:	$ 1.0d1 $
//
//     Creation Date:	4/2/93
//
//     COPYRIGHT 1993 SYMANTEC CORPORATION. ALL RIGHTS RESERVED. UNPUBLISHED -- RIGHTS
//     RESERVED UNDER THE COPYRIGHT LAWS OF THE UNITED STATES. USE OF COPYRIGHT NOTICE IS
//     PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION OR DISCLOSURE.
//
//     THIS SOFTWARE CONTAINS PROPRIETARY AND CONFIDENTIAL INFORMATION OF SYMANTEC
//     CORPORATION. USE, DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR
//     EXPRESS WRITTEN PERMISSION OF SYMANTEC CORPORATION.
//
//     RESTRICTED RIGHTS LEGEND
//     Use, duplication, or disclosure by the Government is subject to restrictions as set
//     forth in subparagraph (c)(l)(ii) of the Rights in Technical Data and Computer
//     Software clause at DFARS 252.227-7013. Symantec Corporation, 10201 Torre Avenue,
//     Cupertino, CA 95014.
//
//========================================================================================

#ifndef   BRAUTODE_H
#include "BRAutoDe.h"
#endif

#ifndef   BRMATH_H
#include "BRMath.h"
#endif

#ifndef BRPRIDEB_H
#include "BRPriDeb.h"
#endif

//========================================================================================
//							Design Notes for Text Readers
//
//	Text readers are designed to be as fast and light-weight as possible.  We assume
//	that in over 90% of the usage of Text readers, the reader will be used to make
//	one sequential pass through the data structure, operating on one character at a time.
//	The first design goal is therefore:
//		1) Make GetCharacterAndAdvance be as efficient as possible.
//	In order to achieve full efficiency, we need to minimize overhead for error checking
//	for reading past the end of the data structure.  We therefore set this requirement:
//		2) Rely on a clear contract to minimize overhead.  It is not necessary for
//		iterators to fail gracefully when misused.
//	As stated above, in 90% of the cases, the text is read in one forward pass.  However,
//  reading backward through the next is a surprisingly large portion of the remaining
//  10%, and if not supported, significantly reduces the usefulness of readers.  We
//	therefore attempt to achieve this goal:
//		3) Make "put back" a relatively efficient operation.  Make it possible to
//		read backwards through the data structure.
//	Often a client iterating over text will want to note the position of some character
//	or token in the text.  We therefore set another goal:
//		4) Support GetPosition ('tell') and SetPosition ('seek') operations.
//	This last goal implies a specific need to handle the case where a client attempts to
//	seek past the end of the text data structure.  In this case, to achieve efficiency,
//	we invoke 2), by setting this requirement:
//		5) It is acceptable to state in the contract that an attempt to SetPosition to
//		an arbitrary position may fail.  The only guaranteed safe argument to SetPosition
//		is one that was returned from a previous GetPosition.  However, if a client knows
//		the length of the data structure, it is safe to SetPosition to any value greater
//		than or equal to zero, and less than the length of the data structure.
//========================================================================================

//========================================================================================
//	CLASS BR_TTextReader
//
//	A base class for iterators that read over a data structure containing characters.
//========================================================================================

template <class tCharacter>
class BR_TTextReader
{
public:
	~BR_TTextReader();
	BR_TTextReader();
	
	void Advance();
		// Advance by one character.
		
	void Backup();
		// Backup by one character.
	
	tCharacter PeekCharacter();
		// Return the current character without advancing.  Can be used for lookahead.
	
	tCharacter GetCharacterAndAdvance();
		// Get the current character and advance.
	
	tCharacter BackupAndGetCharacter();
		// Backup and get previous character.
	
	BR_CharacterCount GetPosition();
		// Get the current position, where 0 is first character in data structure.

	void SetPosition(BR_CharacterCount position);
		// Set the position to position.
		// The result is undefined if position is outside the bounds of the data structure.

protected:

	virtual void GetNextBuffer() = 0;
		// Get another buffer from text data structure.
		// Updates fStart, fLimit, and fNext.
		// Must ensure that fNext==fStart, fStart<=fLimit

	virtual void GetPreviousBuffer() = 0;
		// Gets previous buffer from text data structure.
		// Updates fStart, fLimit, and fNext.
		// Must ensure that fNext==fLimit, fStart<=fLimit

	void DoGetNextBuffer();
		// Calls GetNextBuffer, and updates fBufferSum.
	
	void DoGetPreviousBuffer();
		// Calls GetPreviousBuffer, and updates fBufferSum.

	const tCharacter	*fStart;		// Start of current buffer
	const tCharacter	*fLimit;		// One past last character of current buffer
	const tCharacter	*fNext;			// Current position in buffer

private:

	BR_CharacterCount	fBufferSum;		// Total characters in previous buffers.
};

//----------------------------------------------------------------------------------------
//	BR_TTextReader<tCharacter>::Advance
//----------------------------------------------------------------------------------------

template <class tCharacter>
void BR_TTextReader<tCharacter>::Advance()
{
	if (++fNext == fLimit)
		DoGetNextBuffer();
}

//----------------------------------------------------------------------------------------
//	BR_TTextReader<tCharacter>::Backup
//----------------------------------------------------------------------------------------

template <class tCharacter>
void BR_TTextReader<tCharacter>::Backup()
{
	if (fNext-- == fStart)
		DoGetPreviousBuffer();
}

//----------------------------------------------------------------------------------------
//	BR_TTextReader<tCharacter>::PeekCharacter
//----------------------------------------------------------------------------------------

template <class tCharacter>
tCharacter BR_TTextReader<tCharacter>::PeekCharacter()
{
	return *fNext;
}

//----------------------------------------------------------------------------------------
//	BR_TTextReader<tCharacter>::GetCharacterAndAdvance
//----------------------------------------------------------------------------------------

template <class tCharacter>
tCharacter BR_TTextReader<tCharacter>::GetCharacterAndAdvance()
{
	register tCharacter temp = PeekCharacter();
	Advance();
	return temp;
}

//----------------------------------------------------------------------------------------
//	BR_TTextReader<tCharacter>::BackupAndGetCharacter
//----------------------------------------------------------------------------------------

template <class tCharacter>
tCharacter BR_TTextReader<tCharacter>::BackupAndGetCharacter()
{
	Backup();
	return PeekCharacter();
}

//----------------------------------------------------------------------------------------
//	BR_TTextReader<tCharacter>::GetPosition
//----------------------------------------------------------------------------------------

template <class tCharacter>
BR_CharacterCount BR_TTextReader<tCharacter>::GetPosition()
{
	return fBufferSum + (fNext - fStart);
}

//----------------------------------------------------------------------------------------
//	BR_TTextReader<tCharacter>::DoGetNextBuffer
//----------------------------------------------------------------------------------------

template <class tCharacter>
void BR_TTextReader<tCharacter>::DoGetNextBuffer()
{
	fBufferSum += (fLimit - fStart);
	GetNextBuffer();
}

//----------------------------------------------------------------------------------------
//	BR_TTextReader<tCharacter>::DoGetPreviousBuffer
//----------------------------------------------------------------------------------------

template <class tCharacter>
void BR_TTextReader<tCharacter>::DoGetPreviousBuffer()
{
	GetPreviousBuffer();
	fBufferSum -= (fLimit - fStart);
}

//========================================================================================
//	CLASS BR_TTextWriter
//
//	TextWriters are (intentionally) kept simpler than TextReaders.  We assume that there
//	is no need to allow backing up in order to rewrite.  This results in a smaller and
//	simpler interface.
//========================================================================================

enum BR_TextWriterMode {BR_kTextWriteOver, BR_kTextAppend};

template <class tCharacter>
class BR_TTextWriter : public _BR_CAutoDestructObject
{
public:
	
	virtual ~BR_TTextWriter();
		// Flush the current buffer.
		// Writer destructors must do whatever may be necessary to restore text structure
		// to valid state, e.g. restore NUL termination, cached length member, etc.

	BR_TTextWriter();

	void PutCharacterAndAdvance(tCharacter character);
		// Write the character into the data structure and advance to next position.

	BR_CharacterCount GetPosition();
		// Get the current position.

protected:

	virtual void FlushAndGetNextBuffer() = 0;
		// Flush the current buffer.
		// Get another buffer from text data structure, update fNext and fLimit.
	
	void DoFlushAndGetNextBuffer();
		// Calls FlushAndGetNextBuffer and updates fBufferSum.

	tCharacter	*fLimit;		// One past last character of current buffer
	tCharacter	*fNext;			// Current position in buffer

private:

	BR_CharacterCount	fBufferSum;	// Total characters flushed in previous buffers.
};

//----------------------------------------------------------------------------------------
//	BR_TTextWriter<tCharacter>::PutCharacterAndAdvance
//----------------------------------------------------------------------------------------

template <class tCharacter>
void BR_TTextWriter<tCharacter>::PutCharacterAndAdvance(tCharacter character)
{
	if (fNext >= fLimit)
		DoFlushAndGetNextBuffer();
	*fNext++ = character;
}

//----------------------------------------------------------------------------------------
//	BR_TTextWriter<tCharacter>::GetPosition
//----------------------------------------------------------------------------------------

template <class tCharacter>
BR_CharacterCount BR_TTextWriter<tCharacter>::GetPosition()
{
	return fBufferSum - (fLimit - fNext);
}

//----------------------------------------------------------------------------------------
//	BR_TTextWriter<tCharacter>::DoFlushAndGetNextBuffer
//----------------------------------------------------------------------------------------

template <class tCharacter>
void BR_TTextWriter<tCharacter>::DoFlushAndGetNextBuffer()
{
	FlushAndGetNextBuffer();
	fBufferSum += (fLimit - fNext);
}

//========================================================================================
//	CLASS BR_TTextFilter
//
//	A base class for iterators that can modify a text data structure in place.  This
//	class provides a protocol for any text filter that operates independently
//	(i.e. context-free) on each character in the data structure.
//========================================================================================

template <class tCharacter>
class BR_TTextFilter : public BR_TTextReader<tCharacter>
{
public:

	~BR_TTextFilter();
	BR_TTextFilter();
	
	void PutCharacterAndAdvance(tCharacter character);
		// Write the character over the character in the current position and advance.
};

//----------------------------------------------------------------------------------------
//	BR_TTextFilter<tCharacter>::PutCharacterAndAdvance
//----------------------------------------------------------------------------------------

template <class tCharacter>
void BR_TTextFilter<tCharacter>::PutCharacterAndAdvance(tCharacter character)
{
	// Intentionally cast away const.
	*(tCharacter *)fNext = character;
	Advance();
}

#endif
