/*
 *
 * @APPLE_LICENSE_HEADER_START@
 *
 * Copyright (c) 1999-2001 Apple Computer, Inc.  All Rights Reserved. The
 * contents of this file constitute Original Code as defined in and are
 * subject to the Apple Public Source License Version 1.2 (the 'License').
 * You may not use this file except in compliance with the License.  Please
 * obtain a copy of the License at http://www.apple.com/publicsource and
 * read it before using this file.
 *
 * This Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.  Please
 * see the License for the specific language governing rights and
 * limitations under the License.
 *
 *
 * @APPLE_LICENSE_HEADER_END@
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "playlist_SimpleParse.h"


SimpleString::SimpleString(char *theString)
{	
	fTheString = theString;
	if (theString == NULL)
		fLen = 0;
	else
		fLen = strlen(theString);
}

void SimpleString::Init()
{
	fTheString = NULL;
	fLen = 0;

}

void SimpleString::SetString(char *theString, SInt32 len)
{	
	fTheString = theString;
	fLen = len;
}

SInt32 SimpleString::GetString(char *theString, SInt32 len)
{
	SInt32 copyLen = fLen + 1;
	if (len < copyLen ) copyLen = len;
	if (copyLen > 0)
	{	memcpy(theString,fTheString,copyLen);
		theString[copyLen -1] = 0;
	}
	
	return copyLen;
}

SInt32 SimpleString::GetInt()
{
    SInt32 result = 0;

    if (fTheString == NULL|| fLen == 0 || fLen > 32)
        return result;

    char* buff = new char[fLen +1];
    memcpy (buff, fTheString,fLen);
    buff[fLen] = 0;

    result = strtol(buff, NULL, 0);
    delete [] buff;
   
    return result;
}

void SimpleString::Print()
{
    char* buff = new char[fLen +1];
    memcpy (buff, fTheString,fLen);
    buff[fLen] = 0;
    printf("SimpleString( len=%ld str=>%s< )\n",fLen,buff);
    delete [] buff;
}


char SimpleParser::sWordDelimeters[] = "=:/\t \r\n";
char SimpleParser::sLineDelimeters[] = "\r\n";

bool SimpleParser::Compare(SimpleString *str1Ptr, SimpleString *str2Ptr)
{
	bool result = false;
	
	do 
	{	
		if (NULL == str1Ptr) break;
		if (NULL == str2Ptr) break;
	
		if (NULL == str1Ptr->fTheString) break;
		if (NULL == str2Ptr->fTheString) break;

		if (str1Ptr->fLen != str2Ptr->fLen)
			break;
		
		int test = strncmp(str1Ptr->fTheString, str2Ptr->fTheString,str1Ptr->fLen);
		if (test != 0) break;
		
		result = true;
	} while (false);
	
	
	return result;
}

bool SimpleParser::FindString( SimpleString *sourcePtr,  SimpleString *findPtr, SimpleString *resultStringPtr)
{
	bool result = false;
	
	do
	{
		if (NULL == sourcePtr) break;
		if (NULL == findPtr) break;
				
		if (NULL == sourcePtr->fTheString) break;
		if (NULL == findPtr->fTheString) break;

		if (findPtr->fLen > sourcePtr->fLen)
			break;
					
		char *start = strstr(sourcePtr->fTheString, findPtr->fTheString);		
		if (start == NULL) break;
			
		if (NULL != resultStringPtr)
		{	
			SInt32 len = (PointerSizedInt) start - (PointerSizedInt) sourcePtr->fTheString;
			if (len > sourcePtr->fLen) break;
			
			resultStringPtr->SetString(start, findPtr->fLen);
		}
		
		result = true;
	} while (false);

	return result;
}

bool SimpleParser::FindNextString( SimpleString *sourcePtr,  SimpleString *currentPtr,  SimpleString *findPtr, SimpleString *resultStringPtr)
{
	bool result = false;
	SInt32 length = 0;

	
	do 
	{
		if (NULL == sourcePtr) break;
		if (NULL == currentPtr) break;
		if (NULL == findPtr) break;
		if (NULL == sourcePtr->fTheString) break;
		if (NULL == currentPtr->fTheString) break;
		
		SimpleString tempSource(NULL);	
		

		length =  currentPtr->fTheString - sourcePtr->fTheString;
		if (length < 0) break;
		if (length > sourcePtr->fLen) break;

		length = sourcePtr->fLen - (length + currentPtr->fLen); // the remaining length to search
		tempSource.SetString(&currentPtr->fTheString[currentPtr->fLen], length); // step past the end of current with remaining length
		
		result = FindString(&tempSource, findPtr, resultStringPtr);
	
	} while (false);

	return result;

}


bool SimpleParser::GetString( SimpleString *sourcePtr,  SimpleString *findPtr, SimpleString *resultStringPtr)
{
	bool result = false;
	
	result = FindString(sourcePtr, findPtr, resultStringPtr);
	
	if (result)
	{	resultStringPtr->fLen = (PointerSizedInt) resultStringPtr->fTheString -(PointerSizedInt) sourcePtr->fTheString;
		resultStringPtr->fTheString = sourcePtr->fTheString;
	}
	
	return result;
}

bool SimpleParser::FindDelimeter( SimpleString *sourcePtr, char *findChars, SimpleString *resultStringPtr)
{
	bool result = false;
	
	do
	{
		if (NULL == sourcePtr) break;
		if (NULL == findChars) break;
		if (NULL == resultStringPtr) break;
					
		SInt32 	charCount = 0;
		char*	charOffset = sourcePtr->fTheString;
		char*	foundChar = NULL;
		
		if ( (NULL == sourcePtr->fTheString) || (0 == sourcePtr->fLen) )
		{	//printf("NULL string in FindDelimeter \n");
			break;
		}
		
		// skip past any delimeters
		while ( (*charOffset != 0) && (charCount <= sourcePtr->fLen) )  
		{	foundChar = strchr(findChars, *charOffset);
			if (NULL == foundChar) break; // found non delimeter char
			charOffset ++; charCount ++;
		}
		
		char *theChar = charOffset; // start past delimeters
		
		while ( (*theChar != 0) && (charCount <= sourcePtr->fLen) )  
		{
			foundChar = strchr(findChars, *theChar);
			if (NULL != foundChar) break; // found delimeter
			charCount++;
			theChar++;
		}			
		if (NULL == foundChar) break; // we didn't find a delimeter;
			
		
		if (NULL != resultStringPtr)
		{	UInt32 theLen = ((PointerSizedInt) theChar - (PointerSizedInt)charOffset); 
			resultStringPtr->SetString(charOffset, theLen); // start is charOffset
			if (theLen == 0) break;
		}
	
		result = true;
	} while (false);
	
	if (!result) 
		resultStringPtr->SetString(NULL, 0); // start is charOffset

	return result;
}


int SimpleParser::CountDelimeters( SimpleString *sourcePtr, char *delimeters)
{
	short count = 0;
	if (sourcePtr && delimeters)
	{
		SimpleString currentString = *sourcePtr;
		currentString.fLen = 0;
		
		while (GetNextThing(sourcePtr,&currentString, delimeters, &currentString))
		{	count ++;
		} 
	}
	return count;
}


		
bool SimpleParser::GetWord( SimpleString *sourcePtr, SimpleString *resultStringPtr)
{
	bool result = false;
	char delimeter[] = " :/"; // space or colon or /
	result = FindDelimeter(sourcePtr, delimeter,resultStringPtr);
	return result;
}

bool SimpleParser::GetLine(SimpleString *sourcePtr, SimpleString *resultStringPtr)
{
	bool result = false;
	char delimeter[] = "\r\n"; 
	result = FindDelimeter(sourcePtr, delimeter,resultStringPtr);
	return result;
}

bool SimpleParser::GetNextThing(SimpleString *sourcePtr, SimpleString *currentPtr, char *findChars, SimpleString *resultStringPtr)
{
	bool result = false;

	do 
	{
		if (NULL == sourcePtr) break;
		if (NULL == currentPtr) break;
		if (NULL == findChars) break;
		
		if ( (PointerSizedInt) currentPtr->fTheString < (PointerSizedInt) sourcePtr->fTheString) 
			break;
			
		if (NULL ==  sourcePtr->fTheString) 
		{	//printf("NULL sourcePtr->fTheString in GetNextThing \n");
			break;
		}
		if (NULL ==  currentPtr->fTheString) 
		{	//printf("NULL currentPtr->fTheString in GetNextThing \n");
			break;
		}
		
		PointerSizedInt endSource =  (PointerSizedInt) &sourcePtr->fTheString[sourcePtr->fLen];
		PointerSizedInt endCurrent = (PointerSizedInt) &currentPtr->fTheString[currentPtr->fLen];

		if (endCurrent > endSource) break;
		
		SimpleString tempSource(NULL);	
		
		
		UInt32 searchLen = endSource - endCurrent;
		
		tempSource.SetString(&currentPtr->fTheString[currentPtr->fLen], searchLen); // step past the end of current with remaining length
		
		result = FindDelimeter(&tempSource, findChars,resultStringPtr);
	
	} while (false);

	return result;
}

bool SimpleParser::GetNextWord( SimpleString *sourcePtr, SimpleString *currentWord, SimpleString *resultStringPtr)
{
	bool result = false;
	char *findChars = sWordDelimeters;// 
	result = GetNextThing(sourcePtr,currentWord, findChars, resultStringPtr);
	return result;
}

bool SimpleParser::GetNextLine( SimpleString *sourcePtr, SimpleString *currentLine, SimpleString *resultStringPtr)
{
	bool result = false;
	char *findChars = sLineDelimeters;//"\r\n"; 
	result = GetNextThing(sourcePtr,currentLine, findChars, resultStringPtr);
	return result;
}
