
/*
	General search-and-replace mechanism to convert given substrings
	Original Source: <http://cocoa.karelia.com/Foundation_Categories/NSString/String_Replace.m>
	(See copyright notice at <http://cocoa.karelia.com>)
*/


/*"	General search-and-replace mechanism to convert given substrings.  Pass in a dictionary with the keys of "from" strings, and the values of what to convert them to.  This goes in an undefined order, so if one replacement might affect future substitutions, you just don't know what will happen. "*/

- (NSString *) replaceAllTextFromDictionary:(NSDictionary *)inDict
															   options:(unsigned)inMask range:(NSRange)inSearchRange
{
	NSEnumerator *theEnum = [inDict keyEnumerator];
	id searchString;
	NSRange range = inSearchRange;	// this gets modified as string changes size
	NSMutableString *buf = [NSMutableString stringWithString:self];
	// we will be modifying buf once for each pass through.

	while (nil != (searchString = [theEnum nextObject]) )
	{
		NSString *replaceString = [inDict objectForKey:searchString];

		NSString *source = buf;	// transfer what we had before into our source
		buf = [NSMutableString string];		// and clean out our buffer

		NSRange beforeSearchRange = NSMakeRange(0,range.location);
		[buf appendString:[source substringWithRange:beforeSearchRange]];

		// Now loop through; looking.
		while (range.length != 0)
		{
			NSRange foundRange = [source rangeOfString:searchString options:inMask range:range];

			if (foundRange.location != NSNotFound)
			{
				// First, append what was the search range and the found range -- before match -- to output

				NSRange beforeRange = NSMakeRange(range.location, foundRange.location - range.location);
				NSString *before = [source substringWithRange:beforeRange];
				[buf appendString:before];

				// Now, append replacement.  Make sure it's a string
				[buf appendString:[replaceString description]];

				// Now, update things and move on.
				range.length = NSMaxRange(range) - NSMaxRange(foundRange);
				range.location = NSMaxRange(foundRange);
			}
			else
			{
				NSString *after = [source substringWithRange:range];
				[buf appendString:after];
				// Now, update to be past the range, to finish up.
				range.location = NSMaxRange(range);
				range.length = 0;
			}
		}
		// Finally, append stuff after the search range

		int newTop = [buf length];
		NSRange afterSearchRange = NSMakeRange(range.location, [source length] - range.location);
		[buf appendString:[source substringWithRange:afterSearchRange]];

		// Adjust range so that it reflects the substitutions we just did.
		range.length = newTop - inSearchRange.location;
		range.location = inSearchRange.location;

	}
	return buf;
}


/*"	Find and replace strings with the given options inMask.  The inMask parameter is the same as is passed to #{[NSString rangeOfString:options:range:]}.
"*/

- (NSString *) replaceAllTextFromDictionary:(NSDictionary *)inDict options:(unsigned)inMask

{
	return [self replaceAllTextFromDictionary:inDict options:inMask range:NSMakeRange(0,[self length])];
}

/*"	Find and replace strings with the default options.
"*/

- (NSString *) replaceAllTextFromDictionary:(NSDictionary *)inDict
{
	return [self replaceAllTextFromDictionary:inDict options:0];
}