//*****************************************************************************
//
//	EParse.m.  
//		
//		Search a file for a specific pattern of (2)strings which will 
//		identify the next str as a keyword to be captured and returned.
// 
//		by	Felipe A. Rodriguez		
//
//	This code is supplied "as is" the author makes no warranty as to its 
//	suitability for any purpose.  This code is free and may be distributed 
//	in accordance with the terms of the:
//		
//			GNU GENERAL PUBLIC LICENSE
//			Version 2, June 1991
//			copyright (C) 1989, 1991 Free Software Foundation, Inc.
// 			675 Mass Ave, Cambridge, MA 02139, USA
//
//*****************************************************************************

#import "EParse.h"



@implementation EParse

//*****************************************************************************
//
// 		init
//
//*****************************************************************************

- init
{
	[super init];
	expireDefault = 1;

    return self;
}
//*****************************************************************************
//
// 		Open file to parse and search 
//
//*****************************************************************************

- (char *)parseFile:(const char *)filePath
{
NXStream *inFStream;
static char buf[2] = {" \0"};
int nread = 0, i = 0;
char * resultStr = NULL;

	if((inFStream = NXMapFile(filePath, NX_READONLY)) == NULL)
		{
		strcpy(lBuf, "Could not open file: ");
		strcat(lBuf, filePath);
		NXRunAlertPanel(0, lBuf, 0, 0, 0);
		}
	else
		{
		nread = NXRead(inFStream, buf, 1);
		while(!(nread <= 0))					// read while char's in file
			{				// cycle thru file until we find keyword or EOF
			strcpy(lBuf, buf);
			do {					// build a line buffer from file data
				nread = NXRead(inFStream, buf, 1);
				strcat(lBuf, buf);
				i++;
				}
			while((buf[0] != '\n') && (buf[0] != '\r') && (i < MAXPATHLEN) 
																	&& buf[0]);	
			i = 0;
			while(((buf[0] == '\n') || (buf[0] == '\r')) && (!(nread <= 0)))		
				nread = NXRead(inFStream, buf, 1);		// eliminate cr, nl	
			if(resultStr = [self parse:lBuf])			// parse line buffer
				nread = -1; 
			}
		NXCloseMemory(inFStream, NX_FREEBUFFER);
		}

    return resultStr;
}
//*****************************************************************************
//
// 		Specify keywords to be searched for.  Keyword 1 must be found
//		prior to keyword 2.  Ideally, these two should be adjacent in file
//
//*****************************************************************************

- setKey1:(const char *)keyWord
{
	keyOne = keyWord;

    return self;
}
- setKey2:(const char *)keyWord
{
	keyTwo = keyWord;

    return self;
}
//*****************************************************************************
//
// 		set the number of words to ignore once the keys have been found 
//
//*****************************************************************************

- setEscape:(int)numWordsToIgnore
{
	escape = numWordsToIgnore;

    return self;
}
//*****************************************************************************
//
// 		set max number of lines between valid keys 
//
//*****************************************************************************

- setExpire:(int)maxLinesBetweenKeys
{
	expireDefault = maxLinesBetweenKeys;

    return self;
}
//*****************************************************************************
//
// 		Specify file delimiters to be used in parsing.  Once the first keyword
//		is caught the second set of delimiters is used in parsing.
//
//*****************************************************************************

- setDelim1:(const char *)delimiters
{
	delim1 = delimiters;

    return self;
}
- setDelim2:(const char *)delimiters
{
	delim2 = delimiters;

    return self;
}
//*****************************************************************************
//
// 		parses a line of text looking for a set of keywords
//
//		**keyWords + delims must me set before calling this method as follows:
//		keyOne -- should point to first keyword to be caught
//		keyTwo -- should point to second keyword to be caught or NULL
//		delim1 -- should point to first set of delimiters
//		delim2 -- should point to second set of delimiters 
//
//*****************************************************************************

- (char *)parse:(char *)buffer
{
char *str, *result = NULL;
static BOOL found = NO;			// set if first keyword found in prev line
static int expire;

	if(expire-- <= 0)							
		found = NO;
	str = strtok(buffer, delim1);						// Parse string 
	while(str != NULL)								
		{										// did we catch keyOne str?
		if(strcmp(str, keyOne) == 0)		
			{
			found = YES;						// first keyword has been found
			expire = expireDefault;
			}
		if(found)		
			{
			if((strcmp(str, keyTwo) == 0) || *keyTwo == '\0')
				{
				if(str = strtok(NULL, delim2))	// this must be the grail
					found = NO;	
				}
						// found was reset so we've found result once
						// we've escaped any noise 
			if(!found)
				{									// escape noise words
				while((escape-- > 0) && (str != NULL))		
					str = strtok(NULL, delim2);
				if(str != NULL)						// return search result
					result = NXCopyStringBuffer(str);
				else
					result = NXCopyStringBuffer(" "); // blank found
				}
			}
		if(str != NULL)						
			str = strtok(NULL, delim1);
		}

    return result;										// non NULL if success
}
//*****************************************************************************
//
// 		replace found text with supplied text 
//
//*****************************************************************************

- replaceWith:(const char *)buffer
{
	if(replace)					// found was reset so we found it
		free(replace);
	replace = NXCopyStringBuffer(buffer);	// return search 

    return self;									// keyword not found
}
//*****************************************************************************
//
// 		Open file to parse and edit 
//
//*****************************************************************************

- (char *)editFile:(const char *)filePath
{
NXStream *inFStream, *MemoryStream = NULL; 
static char buf[2] = {" \0"};
int nread = 0, i = 0;
static int start, end;
char * resultStr = NULL;

	if((inFStream = NXMapFile(filePath, NX_READONLY)) == NULL)
		{
		strcpy(lBuf, "Could not open file: ");
		strcat(lBuf, filePath);
		NXRunAlertPanel(0, lBuf, 0, 0, 0);
		}
	else
		{
		nread = NXRead(inFStream, buf, 1);
		while(!(nread <= 0))					// read while char's in file
			{				// cycle thru file until we find keyword or EOF
			strcpy(lBuf, buf);
start = inFStream->buf_left;
			do {					// build a line buffer from file data
				nread = NXRead(inFStream, buf, 1);
				strcat(lBuf, buf);
				i++;
				}
			while((buf[0] != '\n') && (buf[0] != '\r') && (i < MAXPATHLEN) 
																	&& buf[0]);	
			i = 0;
			while(((buf[0] == '\n') || (buf[0] == '\r')) && (!(nread <= 0)))		
				nread = NXRead(inFStream, buf, 1);		// eliminate cr, nl	
end = inFStream->buf_left;
			if(resultStr = [self parse:lBuf])			// parse line buffer
				{
//				[self openMemoryStream];
	if(!(MemoryStream = NXOpenMemory(NULL, 0, NX_READWRITE)))		
			NXRunAlertPanel(0, "Could not open Memory Stream", 0, 0, 0);

				NXSeek(inFStream, 0, NX_FROMSTART);			// rewind	
				nread = 1;		
				while((nread > 0) && (inFStream->buf_left > (start + 1)))
					{		
					nread = NXRead(inFStream, buf, 1);		// eliminate cr, nl	
					NXWrite(MemoryStream, buf, 1);		// eliminate cr, nl	
					}
				NXPrintf(MemoryStream, "%s\r\n", replace);
				NXSeek(inFStream, ((-1 * end) - 1), NX_FROMEND);	// rewind			
				while(inFStream->buf_left > 0)
					{		
					nread = NXRead(inFStream, buf, 1);		// eliminate cr, nl	
					NXWrite(MemoryStream, buf, 1);		// eliminate cr, nl	
					}
				nread = 0;									// end loop
				}
			}
		NXCloseMemory(inFStream, NX_FREEBUFFER);
		if(resultStr)
			{
			NXFlush(MemoryStream);
			if(NXSaveToFile(MemoryStream, filePath) == -1)
				NXRunAlertPanel(0, "Error saving memory stream", 0, 0, 0);
			else
				NXCloseMemory(MemoryStream, NX_FREEBUFFER);
			}
		}

    return resultStr;
}

@end
