This is MiscStringCompat.m in view mode; [Download] [Up]
//
// MiscStringCompat.m
// Written by Don Yacktman (c) 1993 by Don Yacktman.
// Version 1.95 All rights reserved.
// This notice may not be removed from this source code.
//
// This object is included in the MiscKit by permission from the author
// and its use is governed by the MiscKit license, found in the file
// "LICENSE.rtf" in the MiscKit distribution. Please refer to that file
// for a list of all applicable permissions and restrictions.
//
#import <misckit/MiscString.h>
@implementation MiscString(Compat)
// This category includes methods to make the MiscString compatible
// with other existing string classes. This way, you can easily
// replace your crufty old string class with a MiscString without
// having to change the code. Most methods are covers which simply
// call the appropriate existing MiscString function. The majority
// of these methods actually add compatability with the MOString class,
// but there is other stuff in here, too...
// None of the methods in this category add functionality; they are wrappers
// around existing methods which allow programmers to use calls associated
// with other string classes on the MiscString. When I add compatability
// with string classes, if there is a function that adds functionality, I
// write a compatible method and place it into another category. Only
// redundant methods are in this category, which is why they are not
// detailed in the documentation.
// If you have some _other_ string class, and would like to see
// compatibility methods added to the MiscString to support that
// class, too, let us know!
// Most of these methods are derived by Don Yacktman from code written
// by Mike Ferris and David Lehn.
- takeStringValue:sender { return [self takeStringValueFrom:sender]; }
- clear
{
[self freeString];
return self;
}
- ( const char* ) string
{
return [self stringValue];
}
- setString: ( const char *) aString
{
[self setStringValue:aString];
return self;
}
- replaceChar: ( char ) aChar withChar: ( char ) replaceChar
{
return [self replaceEveryInstanceOfChar:aChar withChar:replaceChar];
}
- addToEndOfString: ( const char *) aString
{
[self cat:aString];
return self;
}
- addToFrontOfString: ( const char *) aString
{
[self insert:aString at:0];
return self;
}
- addCharToEndOfString: ( char ) aChar
{
[self addChar:aChar];
return self;
}
- addCharToFrontOfString: ( char ) aChar
{
[self insertChar:aChar at:0];
return self;
}
- ( int ) numberFields
{
return [self numWords];
}
- ( char * ) nthField: ( int ) fieldNumber useAsDelimiter: ( char ) c
{
char * field;
id fieldString = [ self extractPart:(fieldNumber) useAsDelimiter:c ];
if (!fieldString) return NULL;
field = NXZoneMalloc( [ self zone ], [ fieldString length ] + 1 );
strcpy(field, [ fieldString stringValue ]);
[fieldString free];
return field;
}
- ( char * ) nthField: ( int ) fieldNumber
{ // have to do all this garbage to make sure we (1) don't leak memory
// and (2) we don't smash the stringValueAndFree buffer. (Otherwise
// I would just use it, but that would make the MiscString badly
// non-reentrant.) This works, anyway...though the obvious
// implementation would be this:
//
// return [[self wordNum:fieldNumber] stringValueAndFree];
static id tempBuffer = nil; id temp;
if (!tempBuffer) tempBuffer = [MiscString new];
temp = [self wordNum:fieldNumber];
[tempBuffer setStringValue:[temp stringValue]];
[temp free];
return (char *)[tempBuffer stringValue];
}
// this one kind of adds functionality, but by naming conventions it still
// makes sense to put it here.
- ( char * ) nthQuotedField: ( int ) fieldNumber
{
return [ self nthField:fieldNumber*2 useAsDelimiter:'"' ];
}
- ( char * ) lastField
{
char * field;
id str = [ self extractPart:MISC_STRING_LAST useAsDelimiter:' ' ];
field = NXZoneMalloc([self zone], [str length] + 1);
strcpy(field, [str stringValue]);
[str free];
return field;
}
- ( char * ) firstField
{
char * field;
id str = [ self extractPart:MISC_STRING_FIRST useAsDelimiter:' ' ];
field = NXZoneMalloc([self zone], [str length] + 1);
strcpy(field, [str stringValue]);
[str free];
return field;
}
- addStrings: ( const char *) fields, ...
{
va_list ptr;
va_start( ptr, fields );
[self catStrings:fields, ptr];
va_end( ptr );
return self;
}
- replaceEveryInstanceOfChar:(char)aChar withChar:(char)replaceChar
{
return [self replaceEveryOccurrenceOfChar:aChar
withChar:replaceChar caseSensitive:YES];
}
- replaceEveryInstanceOfChar:(char)aChar with:(char)replaceChar
{
return [self replaceEveryOccurrenceOfChar:aChar
withChar:replaceChar caseSensitive:YES];
}
// The rest of the methods here are for compatability with the MOString
// from the MOKit.
// warning: the following MOString methods clash with MiscString methods
// of the same name. You will have to check your code for uses of these
// methods and fix them appropriately to avoid serious problems.
// Group 1: MOString wants string object, MiscString wants char *
// -insert:stringObject at:(int)position
// -cat:stringObject
// Note also that the MiscString doesn't support the unique string
// concept, so it cannot become a unique string. Perhaps in the
// future there will be a MiscUniqueString class; I prefer that approach
// myself. At any rate, this shouldn't affect the functionality when
// using the MiscString compatibly.
- convertToUpper
{
return [self toUpper];
}
- convertToLower
{
return [self toLower];
}
- (size_t)recalcLength
{
length = strlen(buffer);
return length;
}
- (int)replaceAllOccurrencesOfChar:(char)oldChar with:(char)newChar
{
[self replaceEveryOccurrenceOfChar:oldChar withChar:newChar];
return 0; // this information isn't available so we'll just return zero
}
- (char)replaceCharAt:(int)index with:(char)newChar
{
char tempChar = [self charAt:index];
[self replaceCharAt:index withChar:newChar];
return tempChar;
}
- insertStringValue:(const char *)s at:(int)position
{
[self insert:s at:position];
return self;
}
- preCatStringValue:(const char *)s
{
return [self insert:s at:0];
}
- preCat:stringObject
{
return [self insertString:stringObject];
}
- preCatFromFormat:(const char *)format, ...
// Prepends the given format string after formatting before the contents
// of the receiver.
{
va_list param_list;
va_start(param_list, format);
[self insertFromFormat:format, param_list];
va_end(param_list);
return self;
}
- catStringValue:(const char *)s
{
return [self cat:s];
}
- (int)compare:stringObject caseSensitive:(BOOL)flag
{
return [self compare:stringObject caseSensitive:flag
length:-1 withTable:NULL];
}
- (int)compare:stringObject caseSensitive:(BOOL)flag length:(int)len
{
return [self compare:stringObject caseSensitive:flag
length:len withTable:NULL];
}
- (int)compare:stringObject caseSensitive:(BOOL)flag length:(int)len
withTable:(NXStringOrderTable *)table
{
int ret;
NXStringOrderTable *realTable = [self stringOrderTable]; // temp save
[self setStringOrderTable:table];
ret = [self compareTo:stringObject n:len caseSensitive:flag];
[self setStringOrderTable:realTable];
return ret;
}
- (int)compareStr:(const char *)s
{
return [self compareStr:s caseSensitive:YES length:-1 withTable:NULL];
}
- (int)compareStr:(const char *)s caseSensitive:(BOOL)flag
{
return [self compareStr:s caseSensitive:flag length:-1 withTable:NULL];
}
- (int)compareStr:(const char *)s caseSensitive:(BOOL)flag length:(int)len
{
return [self compareStr:s caseSensitive:flag length:len withTable:NULL];
}
- (int)compareStr:(const char *)s caseSensitive:(BOOL)flag length:(int)len
withTable:(NXStringOrderTable *)table
{
id ss = [[self class] newWithString:s];
int ret = [self compare:ss caseSensitive:flag length:len withTable:table];
[ss free];
return ret;
}
- (int)endCompare:stringObject caseSensitive:(BOOL)flag
{
return [self endCompare:stringObject
caseSensitive:flag length:-1 withTable:NULL];
}
- (int)endCompare:stringObject caseSensitive:(BOOL)flag length:(int)len
{
return [self endCompare:stringObject
caseSensitive:flag length:len withTable:NULL];
}
- (int)endCompare:stringObject caseSensitive:(BOOL)flag length:(int)len
withTable:(NXStringOrderTable *)table
{
int ret;
NXStringOrderTable *realTable = [self stringOrderTable]; // temp save
[self setStringOrderTable:table];
ret = [self endCompareTo:stringObject n:len caseSensitive:flag];
[self setStringOrderTable:realTable];
return ret;
}
- (int)endCompareStr:(const char *)s
{
return [self endCompareStr:s caseSensitive:YES
length:-1 withTable:NULL];
}
- (int)endCompareStr:(const char *)s caseSensitive:(BOOL)flag
{
return [self endCompareStr:s caseSensitive:flag
length:-1 withTable:NULL];
}
- (int)endCompareStr:(const char *)s caseSensitive:(BOOL)flag
length:(int)len
{
return [self endCompareStr:s caseSensitive:flag
length:len withTable:NULL];
}
- (int)endCompareStr:(const char *)s caseSensitive:(BOOL)flag
length:(int)len withTable:(NXStringOrderTable *)table
{
id ss = [[self class] newWithString:s];
int ret = [self endCompare:ss caseSensitive:flag
length:len withTable:table];
[ss free];
return ret;
}
- substringFrom:(int)start to:(int)end
{
return [self midFrom:start to:end];
}
- (int)positionOf:(char)aChar nthOccurrence:(int)n
{
if (n<0) return [self rspotOf:aChar occurrenceNum:(-n) caseSensitive:YES];
return [self spotOf:aChar occurrenceNum:n caseSensitive:YES];
}
- (int)countOccurrencesOf:(char)aChar
{
return [self numOfChar:aChar caseSensitive:YES];
}
- (size_t)strlen
{
return length;
}
- (const char *)strcpy:(const char *)s
{
[self setStringValue:s];
return buffer;
}
- (const char *)strncpy:(const char *)s :(size_t)n
{
[self setStringValue:s n:(int)n fromZone:[self zone]];
return buffer;
}
- (const char *)strcat:(const char *)s
{
[self cat:s];
return buffer;
}
- (const char *)strncat:(const char *)s :(size_t)n
{
[self cat:s n:n fromZone:[self zone]];
return buffer;
}
- (int)strcmp:(const char *)s
{
if ((!buffer) || (!s)) return -2;
return strcmp(buffer, s);
}
- (int)strncmp:(const char *)s :(size_t)n
{
if ((!buffer) || (!s)) return -2;
return strncmp(buffer, s, n);
}
- (const char *)strchr:(char)aChar
{
if (buffer) return NULL;
return strchr(buffer, aChar);
}
- (const char *)strrchr:(char)aChar
{
if (!buffer) return NULL;
return strrchr(buffer, aChar);
}
- (const char *)strpbrk:(const char *)breakChars
{
if ((!buffer) || (!breakChars)) return NULL;
return strpbrk(buffer, breakChars);
}
- (size_t)strspn:(const char *)acceptableChars
{
if ((!buffer) || (!acceptableChars)) return -1;
return strspn(buffer, acceptableChars);
}
- (size_t)strcspn:(const char *)breakChars
{
if ((!buffer) || (!breakChars)) return 0;
return strcspn(buffer, breakChars);
}
- initStringValue:(const char *)s
{
return [self initString:s];
}
- initStringValueNoCopy:(char *)s
{ // we still copy it anyway; this could be implemented for effect a speedup
// if it makes that much difference...
return [self initString:s];
}
- initStringValueNoCopy:(char *)s shouldFree:(BOOL)flag
{
id ret = [self initString:s];
if (flag) NX_FREE(s);
return ret;
}
- initStringValueUnique:(const char *)s
{
return [self initString:s];
}
- deepCopy
{
return [self deepCopyFromZone:[self zone]];
}
- deepCopyFromZone:(NXZone *)zone
{ // our copy from zone IS deep already...
return [self copyFromZone:zone];
}
- shallowCopy
{
return [self shallowCopyFromZone:[self zone]];
}
- shallowCopyFromZone:(NXZone *)zone
{ // our copy from zone IS deep already...
return [self copyFromZone:zone];
}
- setStringValueNoCopy:(const char *)s
{ // we set the string value by copying anyway.
return [self setStringValue:s];
}
- setStringValueNoCopy:(char *)s shouldFree:(BOOL)flag
{
id ret = [self setStringValue:s];
if (flag) NX_FREE(s);
return ret;
}
- setStringValueUnique:(const char *)s { return [self setStringValue:s]; }
- setNull { return [self freeString]; }
- makeUnique { return self; } // we don't support this at all.
- setShouldFree:(BOOL)flag { return self; }
- (unsigned int)count { return length; }
- (BOOL)isNull { return [self emptyString]; }
- (BOOL)isEmpty { return [self emptyString]; }
- (BOOL)isUnique { return NO; }
- (BOOL)shouldFree { return YES; }
// MOPathString methods
- (int)numberOfComponents { return [self numberOfPathComponents]; }
- componentAt:(int)index { return [self pathComponentAt:index]; }
- file { return [self fileName]; }
- directory { return [self pathName]; }
- (const char *)path { return [self stringValue]; }
- (BOOL)isRelative { return [self isRelativePath]; }
- (BOOL)isAbsolute { return [self isAbsolutePath]; }
- (BOOL)isDirectory { return [self isFileOfType:Misc_Directory]; }
- (BOOL)isPlainFile { return [self isFileOfType:Misc_PlainFile]; }
- (BOOL)isSymbolicLink { return [self isFileOfType:Misc_SymbolicLink]; }
- (BOOL)isCharacterSpecial { return [self isFileOfType:Misc_CharacterSpecial]; }
- (BOOL)isBlockSpecial { return [self isFileOfType:Misc_BlockSpecial]; }
- (BOOL)isSocket { return [self isFileOfType:Misc_Socket]; }
- setPathSeparator:(char)c { return self; } // NO OP
- setExtensionSeparator:(char)c { return self; } // NO OP
- (char)pathSeparator { return '/'; }
- (char)extensionSeparator { return '.'; }
- setPath:(const char *)path { return [self setStringValue:path]; }
- initPath:(const char *)path { return [self initStringValue:path]; }
- (char *)buffer { return buffer; } // be careful with this! don't muck it up!
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.