/******************************************************************************
 JInterpolate.cc

	JInterpolate does the interpolation of replacement strings for JRegex.

	A summary of the default behavior is as follows.  The replacement
	metacharacter is '$', which marks the beginning of a replacement token.
	'Unclean' replacement patterns are patterns which contain a
	metacharacter not immediately followed either by a second metacharacter
	or by an optional sign ('-' or '+') preceding one or more decimal
	digits.  All other patterns are 'clean'.  Clean patterns will be
	replaced by their corresponding match value, while unclean patterns are
	left intact except their '$' is removed; to insert a literal '$'
	preface it with a backslash.

	In other words, the only clean replacement tokens are those of the form
	'$[+-]?[0-9]+', and a replacement pattern is clean unless it contains
	at least one unclean replacement token.

	BASE CLASS = public JSubstitute

	Copyright © 1998 by Dustin Laurence.  All rights reserved.
	
	Base code generated by Codemill v0.1.0

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

//Class Header
#include <JInterpolate.h>

#include <jAssert.h>
#include <jTypes.h>
#include <JString.h>

#include <JRegex.h>

	const JCharacter* varPattern = "[+-]?[0-9]+";

/******************************************************************************
 Constructor

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

JInterpolate::JInterpolate
	()
	:
	JSubstitute(),
	itsSource(NULL),
	itsMatchList(NULL)
{
	DefineVariables(varPattern);
}

JInterpolate::JInterpolate
	(
	const JCharacter*          source,
	const JArray<JIndexRange>* matchList
	)
	:
	JSubstitute(),
	itsSource(source),
	itsMatchList(matchList)
{
	DefineVariables(varPattern);
}

/******************************************************************************
 Destructor

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

JInterpolate::~JInterpolate()
{
}

/******************************************************************************
 GetValue (virtual protected)

	The default is to return an empty value.  It can't be pure virtual
	because one shouldn't have to create a derived class if one only has
	literal variable names.

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

JBoolean
JInterpolate::GetValue
	(
	const JString&	name,
	JString*		value
	)
	const
{
	JInteger matchNumber;
	const JBoolean wasNumber = name.ConvertToInteger(&matchNumber);
	assert(wasNumber /* JInterpolate::GetValue didn't receive a number! */);

	if (itsSource == NULL || itsMatchList == NULL)
		{
		// We have to assume ContainsError() was called.  Since the
		// above assert() didn't fail, we accept it.
		return kTrue;
		}

	const JSize matchCount = itsMatchList->GetElementCount();

	if (matchNumber < 0) // Wrap so negatives count from the end
		{
		matchNumber += matchCount;
		}

	const JIndex matchIndex = matchNumber + 1; // Convert To a 1-based JArray index

	if (1 <= matchIndex && matchIndex <= matchCount)
		{
		const JIndexRange thisRange = itsMatchList->GetElement(matchIndex);
		value->Set(itsSource + thisRange.first - 1, thisRange.GetLength() );
		}
	else
		{
		value->Clear();
		}

	// We accept *any* number.
	return kTrue;
}
