/// @file sampleparser.cpp
/// A simple sample parser for use in statistical compression
///
/// @remarks
/// This is a sample parser that can be used as the skeleton for building
///  new parsers.  It is a simple character parser - that is, it builder 256
///  symbols, one for each character plus one for end-of-stream, and just
///  returns the ascii character # it reads.
///
/// @author mouser
/// @date   2003.07.29
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// Application includes
#include "sampleparser.hpp"
// System includes
#include <string>
//---------------------------------------------------------------------------





//---------------------------------------------------------------------------
// PARSER PUBLIC API - MAIN PARSING FUNCTIONS

bool SampleParser::ParseNextSymbolFromInput(bitreader &from, int &symbolnum)
{
	// grab an input stream symbol and set its INDEX (in symbol vector) for symbolnum
	// return false after EOS
	unsigned char c;

	// are we at end of from input - this is the only non-intuitive step
	// the issue is that only the parser knows about end-of-stream symbols, and when it hits and end of input
	// it basically needs to reply TWICE, first with an end-of-stream, and then with a reply saying 'no more symbols'
	if (from.empty())
		{
		// no more symbols left - BUT the question now is, do we return an EOS symbol, or false for no symbols left
		if (senteos)
			{
			// we already sent an EOS so from now on any requests for a symbol returns false saying no more symbols available
			return false;
			}
		else
			{
			// we are going to drop down to return the EOS signal, but we set flag so we don't do it again
			senteos=true;
			}
		// end of stream symbol number
		symbolnum=SampleParser_EndOfStreamSYMBOL;
		}
	else
		{
		// grab an unsigned character from input and assign the symbol # to its ascii number
		from.get(c);
		symbolnum=(int)c;
		}

	// return true, saying we read a symbol
	return true;
}


bool SampleParser::WriteSymbolText(bitwriter &to, int symbolnum,bool &isendofstreamsymbol)
{
	// write the symbol indexed by symbolnum
	// sets isendofostreamsymbol to true or false depending on if the symbol written is the EOS symbol
	// return true on success

	if (symbolnum==SampleParser_EndOfStreamSYMBOL)
		{
		// this is end of stream symbol, so do nothing but set EOS flag
		isendofstreamsymbol=true;
		}
	else
		{
		// not EOS, so write it and set EOS flag false
		to.put((unsigned char)symbolnum);
		isendofstreamsymbol=false;
		}

	// return success
	return true;
}


string SampleParser::LookupSymbolText(int symbolnum)
	{
	// return the string text corresponding to symbol 'symbolnum'
	if (symbolnum==SampleParser_EndOfStreamSYMBOL)
		return "";
	char cstr[2];
	cstr[0]=(unsigned char)symbolnum;
	cstr[1]='\0';
	return string(cstr);
	}
//---------------------------------------------------------------------------



//---------------------------------------------------------------------------
void SampleParser::SynchronizeStateForNewStream()
{
	// synchronize state for a new stream
	// this MUST be called before beginning a new parsing stream
	// reset input buffer and end-of-stream sent flag
	senteos=false;
}
//---------------------------------------------------------------------------
