diff pkg-src/tree-nx/String.m @ 163:0132846995bd r20-3b8

Import from CVS: tag r20-3b8
author cvs
date Mon, 13 Aug 2007 09:43:35 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkg-src/tree-nx/String.m	Mon Aug 13 09:43:35 2007 +0200
@@ -0,0 +1,376 @@
+//
+//	String.m -- a generic class to simplify manipulation of (char *)'s
+//		Written by Don Yacktman (c) 1993 by Don Yacktman.
+//				Version 1.1.  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;
+}
+
+- initString:(const char *)aString
+{
+	[self init];
+	return [self setString:aString];
+}
+
+- 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;
+	// Note that I could have used NXCopyStringBufferFromZone() here
+	// instead.  This works just as well, but it may be slower...
+	// I haven't checked that out, though.  It might be worth doing.
+	[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);
+	tmpStr = (char *)malloc(_length + 1);
+	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 buffer
+	[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);
+}
+
+- (const char *)strstr:(const char *)subString
+{
+	return strstr(buffer, subString);
+}
+
+- subStringRight:subString
+{
+	const char *sub;
+	if ([subString respondsTo:@selector(stringValue)])
+		sub = [subString stringValue];
+	else return nil;	// error if can't get string value
+	return [[String allocFromZone:[self zone]]
+			initString:strstr(buffer, sub)];
+}
+
+- subStringLeft:subString
+{
+	const char *sub;
+	char *tempString = NXCopyStringBufferFromZone(buffer, [self zone]);
+	char *temp2;
+	id retVal = [String alloc];
+	
+	if ([subString respondsTo:@selector(stringValue)])
+		sub = [subString stringValue];
+	else return nil;	// error if can't get string value
+	temp2 = strstr(tempString, sub); 
+	if (temp2) {
+		temp2[0] = '\0';	// terminate it early
+		[retVal initString:tempString];
+	} else { // substring not found
+		return [self copy];
+	}
+	free(tempString);
+	return retVal;
+}
+
+- (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