home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula
/
nebula.bin
/
SourceCode
/
Classes
/
String
/
String.m
< prev
next >
Wrap
Text File
|
1993-01-30
|
7KB
|
332 lines
//
// String.m -- a generic class to simplify manipulation of (char *)'s
// Written by Don Yacktman (c) 1993 by Don Yacktman.
// All rights reserved.
//
// You may use and copy this class freely as long as you
// comply with the following terms:
// (1) If you use this class in an application which you
// intend to sell commercially, as shareware, or otherwise,
// you may only do so with express written permission
// of the author. Use in applications which will
// be distributed free of charge is encouraged.
// (2) You must include the source code to this object and
// all accompanying documentation with your application,
// or provide it to users if requested, free of charge.
// (3) Do not remove the author's name or any of the
// copyright notices
//
#import "String.h"
#import <strings.h>
#import <appkit/appkit.h>
@implementation String
- init
{
[super init];
[self setStringOrderTable:NXDefaultStringOrderTable()];
buffer = NULL;
length = 0;
_length = 0;
return self;
}
- setStringOrderTable:(NXStringOrderTable *)table
{
orderTable = table;
return self;
}
- (NXStringOrderTable *)stringOrderTable
{
return orderTable;
}
- allocateBuffer:(int)size
{
return [self allocateBuffer:size fromZone:[self zone]];
}
- allocateBuffer:(int)size fromZone:(NXZone *)zone
{
if(size <= _length) return self;
[self freeString];
buffer = (char *)NXZoneMalloc(zone, size);
buffer[0] = 0;
_length = size;
return self;
}
- setString:(const char *)aString
{
return [self setString:aString fromZone:[self zone]];
}
- setString:(const char *)aString fromZone:(NXZone *)zone
{
if(!aString) return self;
[self allocateBuffer:strlen(aString)+1 fromZone:zone];
strcpy(buffer, aString);
length = strlen(buffer);
return self;
}
- setStringValue:sender
{
if (![sender respondsTo:@selector(stringValue)]) return self;
return [self setString:[sender stringValue] fromZone:[self zone]];
}
- setStringValue:sender fromZone:(NXZone *)zone
{
if (![sender respondsTo:@selector(stringValue)]) return self;
return [self setString:[sender stringValue] fromZone:zone];
}
- (const char *)stringValue
{
return buffer;
}
- read:(NXTypedStream *)stream
{
char *tmpStr;
[super read:stream];
NXReadType(stream, "i", &_length);
[self allocateBuffer:_length fromZone:[self zone]];
NXReadType(stream, "*", &tmpStr);
[self setString:tmpStr fromZone:[self zone]];
free(tmpStr);
return self;
}
- write:(NXTypedStream *)stream
{
[super write:stream];
NXWriteTypes(stream, "i*", &_length, &buffer);
return self;
}
- copyFromZone:(NXZone *)zone
{
String *myCopy = [super copyFromZone:zone];
// force child to have it's own copy of the string
[myCopy _unhookBuffer];
[myCopy allocateBuffer:_length fromZone:zone];
[myCopy setString:buffer fromZone:zone];
return myCopy;
}
- _unhookBuffer
{ // used by the copy method so that we don't free the buffer from orig.
buffer = NULL; _length = 0;
return self;
}
- freeString
{
if(buffer) free(buffer);
buffer = NULL;
length = 0;
_length = 0;
return self;
}
- free
{
[self freeString];
return [super free];
}
- cat:(const char *)aString
{
return [self cat:aString
n:strlen(aString)
fromZone:[self zone]];
}
- cat:(const char *)aString n:(int)n
{
return [self cat:aString n:n fromZone:[self zone]];
}
- cat:(const char *)aString fromZone:(NXZone *)zone
{
return [self cat:aString n:strlen(aString) fromZone:zone];
}
- cat:(const char *)aString n:(int)n fromZone:(NXZone *)zone
{
char *newBuffer; int newSize;
newSize = length + n + 1;
if (newSize > _length) {
newBuffer = (char *)NXZoneMalloc(zone, newSize);
_length = newSize;
newBuffer[0] = '\0';
strcat(newBuffer, buffer);
strncat(newBuffer, aString, n);
free(buffer);
buffer = newBuffer;
} else strncat(buffer, aString, n);
length = strlen(buffer);
return self;
}
- concatenate:sender
{
if (![sender respondsTo:@selector(stringValue)]) return self;
return [self cat:[sender stringValue]
n:strlen([sender stringValue])
fromZone:[self zone]];
}
- concatenate:sender n:(int)n
{
if (![sender respondsTo:@selector(stringValue)]) return self;
return [self cat:[sender stringValue] n:n fromZone:[self zone]];
}
- concatenate:sender fromZone:(NXZone *)zone
{
if (![sender respondsTo:@selector(stringValue)]) return self;
return [self cat:[sender stringValue]
n:strlen([sender stringValue]) fromZone:zone];
}
- concatenate:sender n:(int)n fromZone:(NXZone *)zone
{
if (![sender respondsTo:@selector(stringValue)]) return self;
return [self cat:[sender stringValue] n:n fromZone:zone];
}
- (const char *)rindex:(char)aChar
{
return rindex(buffer, aChar);
}
- (const char *)index:(char)aChar
{
return index(buffer, aChar);
}
- (int)length
{
return length;
}
- (BOOL)isEqual:anObject
{
if (anObject == self) return YES;
// doesn't have to be a String object to be equal...
if ([anObject respondsTo:@selector(stringValue)]) {
if (!NXOrderStrings(buffer, [anObject stringValue],
YES, -1, orderTable)) return YES;
}
return NO;
}
- (int)compareTo:sender
{
return [self compareTo:sender n:(-1) caseSensitive:YES];
}
- (int)compareTo:sender n:(int)n
{
return [self compareTo:sender n:n caseSensitive:YES];
}
- (int)cmp:(const char *)aString
{
return strcmp(buffer, aString);
}
- (int)cmp:(const char *)aString n:(int)n
{
return strncmp(buffer, aString, n);
}
- (int)compareTo:sender caseSensitive:(BOOL)sense
{
return [self compareTo:sender n:(-1) caseSensitive:sense];
}
- (int)compareTo:sender n:(int)n caseSensitive:(BOOL)sense
{
if (![sender respondsTo:@selector(stringValue)]) return 1; // !=
return NXOrderStrings(buffer, [sender stringValue], sense, n, orderTable);
}
- (int)casecmp:(const char *)aString
{
return strcasecmp(buffer, aString);
}
- (int)casecmp:(const char *)aString n:(int)n
{
return strncasecmp(buffer, aString, n);
}
- left:(int)count
{
return [self left:count fromZone:[self zone]];
}
- right:(int)count
{
return [self right:count fromZone:[self zone]];
}
- midFrom:(int)start to:(int)end
{
return [self midFrom:start to:end fromZone:[self zone]];
}
- midFrom:(int)start length:(int)len
{
return [self midFrom:start length:len fromZone:[self zone]];
}
- left:(int)count fromZone:(NXZone *)zone
{
char smash = buffer[count];
id newString = [[String allocFromZone:zone] init];
buffer[count] = '\0';
[newString setString:buffer fromZone:zone];
buffer[count] = smash;
return newString;
}
- right:(int)count fromZone:(NXZone *)zone
{
id newString = [[String allocFromZone:zone] init];
[newString setString:&buffer[length - count] fromZone:zone];
return newString;
}
- midFrom:(int)start to:(int)end fromZone:(NXZone *)zone
{
char smash = buffer[end];
id newString = [[String allocFromZone:zone] init];
buffer[end] = '\0'; // inclusive; end-1 is not.
[newString setString:&buffer[start - 1] fromZone:zone];
buffer[end] = smash;
return newString;
}
- midFrom:(int)start length:(int)len fromZone:(NXZone *)zone
{
register int spot = start + len - 1;
char smash = buffer[spot];
id newString = [[String allocFromZone:zone] init];
buffer[spot] = '\0';
[newString setString:&buffer[start - 1] fromZone:zone];
buffer[spot] = smash;
return newString;
}
@end