#import "MiscString.DExtensions.h"

@implementation MiscString(DExtensions)

#define MISC_OCTAL_REGEX "\\\\[0-9][0-9][0-9]*"

// you could need it to read an .addresses file.
- collapseOctalQuotedDigits
{	int spot,i,val;
	for(i=0;(spot=[self spotOfRegex:MISC_OCTAL_REGEX occurrenceNum:i]) >=0;)
	{	sscanf(buffer+spot+1,"%o",&val);
		if(!val) i++;
		[self replaceRegex:MISC_OCTAL_REGEX withChar:(char)val occurrenceNum:i];
	}
	return self;
}
- collapseBackslashQuotedChars
{	[self replaceEveryOccurrenceOf:"\\n" withChar:'\n'];
	[self replaceEveryOccurrenceOf:"\\t" withChar:'\t'];
	[self replaceEveryOccurrenceOf:"\\r" withChar:'\r'];
	[self replaceEveryOccurrenceOf:"\\\"" withChar:'\"'];
	return self;
}
- collapseHTMLQuotedChars
{	[self replaceEveryOccurrenceOf:"&auml;" withChar:'Ù'];
	[self replaceEveryOccurrenceOf:"&ouml;" withChar:'ð'];
	[self replaceEveryOccurrenceOf:"&uuml;" withChar:'ö'];
	[self replaceEveryOccurrenceOf:"&Auml;" withChar:'…'];
	[self replaceEveryOccurrenceOf:"&Ouml;" withChar:'–'];
	[self replaceEveryOccurrenceOf:"&Uuml;" withChar:'š'];
	[self replaceEveryOccurrenceOf:"&szlig;" withChar:'û'];
	[self replaceEveryOccurrenceOf:"&lt;" withChar:'<'];
	[self replaceEveryOccurrenceOf:"&gt;" withChar:'>'];
	[self replaceEveryOccurrenceOf:"&quot;" withChar:'\"'];
	[self replaceEveryOccurrenceOf:"&amp;" withChar:'&'];
	return self;
}

- expandBackslashQuotedChars
{//	[self replaceEveryOccurrenceOfChar:'\\' with:"\\\\"];
	[self replaceEveryOccurrenceOfChar:'\n' with:"\\n"];
	[self replaceEveryOccurrenceOfChar:'\t' with:"\\t"];
	[self replaceEveryOccurrenceOfChar:'\r' with:"\\r"];
	[self replaceEveryOccurrenceOfChar:'\"' with:"\\\""];
	return self;
}

- expandUnprintableCharsToOctalQuotedDigits
{
#if 0	// not implemented
	while¼
	if(!NXPrint(c)) theStr=[initFromFormat:"\\%o",c],[self replaceCharWithString:theStr
#endif
	return self;
}

- trimLeadChars:(const char*)chars
{	const char *p=buffer;
	while(strchr(chars,*p)) p++;
	if(p != buffer) [self removeFrom:0 length:p-buffer];
	[self recalcLength];
	return self;
}
- trimTrailChars:(const char*)chars respectQuotationBy:(unsigned int) qc
{	char *p=buffer+strlen(buffer);
	while(strchr(chars,*p)  && (*(MAX(p-1,buffer)) != qc)  ) *p--=0;
	[self recalcLength];
	return self;
}
- trimTrailChars:(const char*)chars
{	return [self trimTrailChars:chars respectQuotationBy:0];
}
- trimChars:(const char*)chars
{	[self trimTrailChars:chars respectQuotationBy:0];
	[self  trimLeadChars:chars];
	return self;
}

-(BOOL) unbalancedQuotation:(char)theChar
{	int cnt=[self numOfChar:theChar];
	if(cnt) return cnt&1;
	else	return NO;
}
- tokenize:(const char *)breakChars into:theList fieldsQuotatedBy:(char) theChar
{	List *tokenList=[self tokenize:breakChars into:theList];
	if(!theList) theList=tokenList;
	if(theChar)
	{	int cnt=0;
		MiscString *theStr;
		while(theStr=[theList objectAt:cnt++])
		{	if([theStr unbalancedQuotation:theChar])
			{	MiscString *currStr;
				while(currStr=[theList objectAt:cnt++])
				{	[theStr cat:breakChars],[theStr concatenate:currStr];
					[theList removeObject:currStr],cnt--;
					if([currStr unbalancedQuotation:theChar])
					{	break;
		}	}	}	}
	} return theList;
}
-(BOOL) streq:(char*)thestr
{	return !strcmp(buffer,thestr);
}
-(BOOL) casestreq:(char*)thestr
{	return !strcasecmp(buffer,thestr);
}

- streamPuts:(NXStream *) stream
{	NXPrintf(stream, "%s\n", buffer);
	return self;
}

- extractBracketsContentWithPrefix:(const char *) thePrefix
				positionInsideLeft:(int*) insidePos
					 positionRight:(int*) rightPos
					   leftBracket:(unsigned int) lc
					  rightBracket:(unsigned int) rc
					 deleteContent:(BOOL) doDel
{	MiscString *ret;
	int left,right,lcnt;
	for(lcnt=0,left= *insidePos;(buffer[left] != lc || lcnt> 0) && left;left--)
	{	if(buffer[left] == lc) lcnt--;
		if(buffer[left] == rc) lcnt++;
		if(lcnt<=0 && buffer[left] == lc) break;
	}
	for(lcnt=0, right=*insidePos;(buffer[right] != rc || lcnt> 0) && buffer[right];right++)
	{	if(buffer[right] == rc) lcnt--;
		if(buffer[right] == lc) lcnt++;
		if(lcnt<=0 && buffer[right] == rc){right++; break;}
	}
	if(buffer[left] !=lc || buffer[right] !=rc)
	{	return nil;
	} else ret=[self midFrom:left+1 to:right-1];
	(*rightPos)=right;
	if(doDel)
	{	if(thePrefix && strlen(thePrefix))
		{	if(!strncmp(thePrefix,buffer+left-strlen(thePrefix), strlen(thePrefix)))
				left-=strlen(thePrefix);
		}
		[self removeFrom:left to:right];
		(*insidePos)=left;
	}
	return ret;
}
-(int) spotOfChar:(int)c startingAt:(int)currPos
{	const char *ptr;
	if(length< currPos) return -1;
	if(ptr=strchr(buffer+currPos,c)) return ptr-buffer;
	else return -1;
}
-(BOOL) isWhite
{	int i;
	for(i=0;buffer[i];i++)
	{	if(!NXIsSpace(buffer[i])) return NO;
	} return YES;
}
@end
