//.............................................................................
//
// $(pluginName) layer
//

import "doc_Plugin.jnc"

//.............................................................................

class $(layerClass): 
	doc.Layer,
	log.Converter
{
protected:
	jnc.Recognizer m_txScanner;
	jnc.Recognizer m_rxScanner;

	log.Writer* m_writer;
	uint64_t m_timestamp;
	uint_t m_recordCode;
	void const* m_p;
	size_t m_offset;
	
public:
	construct (doc.PluginHost* pluginHost);

	override bool convert (
		log.Writer* writer,
		uint64_t timestamp,
		uint_t recordCode,
		void const* p,
		size_t size
		);	

protected:
	jnc.AutomatonResult automaton scanStream (jnc.Recognizer* recognizer);
	
	writeOriginalData (jnc.Recognizer* recognizer);
}

//. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

$(layerClass).construct (doc.PluginHost* pluginHost)
{
	basetype1.construct (pluginHost);
	m_txScanner.construct (scanStream);
	m_rxScanner.construct (scanStream);

	pluginHost.m_log.attachConverter (this, $(logRepresenterFunc));
}

bool $(layerClass).convert (
	log.Writer* writer,
	uint64_t timestamp,
	uint_t recordCode,
	void const* p,
	size_t size
	)
{
	jnc.Recognizer* recognizer;

	switch (recordCode)
	{
	case log.StdRecordCode.Tx:
		recognizer = &m_txScanner;
		break;

	case log.StdRecordCode.Rx:
		recognizer = &m_rxScanner;
		break;

	default:
		return false; // don't convert other records
	}

	// prepare context for scanner automaton

	m_writer = writer;
	m_timestamp = timestamp;
	m_recordCode = recordCode;
	m_p = p;
	m_offset = recognizer.m_currentOffset;
	
	try recognizer.write (p, size);

	// write the rest of original data

	writeOriginalData (recognizer);	
	return true;
}

$(layerClass).writeOriginalData (jnc.Recognizer* recognizer)
{
	size_t chunkLength = recognizer.m_currentOffset - m_offset;
	if (!chunkLength)
		return;
		
	m_writer.write (m_timestamp, m_recordCode, m_p, chunkLength);

	m_p += chunkLength;
	m_offset += chunkLength;
}

jnc.AutomatonResult automaton $(layerClass).scanStream (jnc.Recognizer* recognizer)
{
	%% '<' [^>]* '>'
		// write original data first...

		writeOriginalData (recognizer);
		
		// ...and then the decoded in-band command
		
		m_writer.write (
			m_timestamp, 
			$(logRecordCodeEnum).InBandCommand, 
			recognizer.m_lexeme + 1, 
			recognizer.m_lexemeLength - 2
			);
	
	%% .
		// ignore the rest		
}

//.............................................................................
