// Copyright 1997-1999 Omni Development, Inc.  All rights reserved.
//
// This software may only be used and reproduced according to the
// terms in the file OmniSourceLicense.html, which should be
// distributed with this project and can also be found at
// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.

#import "NSMutableString-OFExtensions.h"

#import <Foundation/Foundation.h>
#import <OmniBase/OmniBase.h>
#import "OFStringScanner.h"

RCS_ID("$Header: /Network/Developer/Source/CVS/OmniGroup/OmniFoundation/OpenStepExtensions.subproj/NSMutableString-OFExtensions.m,v 1.7 1999/03/30 21:25:45 kc Exp $")

@implementation NSMutableString (OFExtensions)

- (void)replaceAllOccurrencesOfCharactersInSet:(NSCharacterSet *)set
   withString:(NSString *)replaceString;
{
    NSRange                     characterRange, searchRange;
    unsigned int                replaceStringLength;

    searchRange = NSMakeRange(0, [self length]);
    replaceStringLength = [replaceString length];
    while ((characterRange = [self rangeOfCharacterFromSet:set
	    options:NSLiteralSearch range:searchRange]).length) {
	[self replaceCharactersInRange:characterRange
	 withString:replaceString];
	searchRange.location = characterRange.location + replaceStringLength;
	searchRange.length = [self length] - searchRange.location;
	if (searchRange.length == 0)
	    break; /* Might as well save that extra method call. */
    }
}

/* This is similar to the above, but replaces contiguous sequences of
   characters from the pattern set with a single occurrence of
   the replacement string */
- (void)collapseAllOccurrencesOfCharactersInSet:(NSCharacterSet *)set
        toString:(NSString *)replaceString
{
    NSRange                     characterRange, searchRange, replaceRange;
    unsigned int                replaceStringLength, selfLength;

    replaceStringLength = [replaceString length];
    selfLength = [self length];
    
    characterRange = [self rangeOfCharacterFromSet:set
                           options:NSLiteralSearch
                         range:(NSRange){0, selfLength}];
    while (characterRange.length > 0) {
      replaceRange = characterRange;
      searchRange.location = replaceRange.location + replaceRange.length;
      searchRange.length = selfLength - searchRange.location;
      for (;;) {
          characterRange = [self rangeOfCharacterFromSet:set
                            options:NSLiteralSearch range:searchRange];
          if (characterRange.length == 0 ||
              characterRange.location != searchRange.location)
              break;
          replaceRange.length += characterRange.length;
          searchRange.length -= characterRange.length;
          searchRange.location += characterRange.length;
      }
      [self replaceCharactersInRange:replaceRange withString:replaceString];
      characterRange.location += replaceStringLength - replaceRange.length;
      selfLength += replaceStringLength - replaceRange.length;
      OBASSERT(selfLength == [self length]);
    }
}

- (BOOL)replaceAllOccurrencesOfString:(NSString *)oldString
                           withString:(NSString *)newString;
{
    OFStringScanner *scanner;
    NSMutableString *replacementString = nil;
    NSRange partialStringRange;
    unsigned int oldStringLength = 0;
    unsigned int lastPosition = 0;

    scanner = [[OFStringScanner alloc] initWithString:self];

    while ([scanner scanUpToString:oldString]) {
        if (!replacementString) {
            oldStringLength = [oldString length];
            replacementString = [[NSMutableString alloc] init];
        }

        partialStringRange = NSMakeRange(lastPosition, [scanner scanLocation] - lastPosition);
        [replacementString appendString:[self substringWithRange:partialStringRange]];
        [replacementString appendString:newString];
        lastPosition += partialStringRange.length + oldStringLength;
        [scanner skipCharacters:oldStringLength];
    }

    if (replacementString) {
        partialStringRange = NSMakeRange(lastPosition, [scanner scanLocation] - lastPosition);
        [replacementString appendString:[self substringWithRange:partialStringRange]];
        [self setString:replacementString];
        [replacementString release];
        [scanner release];

        return YES;
    }
    
    return NO;
}


@end
