// MOStringComparing.m
//
// by Mike Ferris
// Part of MOKit
// Copyright 1993, all rights reserved.

// ABOUT MOKit
// by Mike Ferris (mike@lorax.com)
//
// MOKit is a collection of useful and general objects.  Permission is 
// granted by the author to use MOKit in your own programs in any way 
// you see fit.  All other rights pertaining to the kit are reserved by the 
// author including the right to sell these objects as objects,  as part 
// of a LIBRARY, or as SOURCE CODE.  In plain English, I wish to retain 
// rights to these objects as objects, but allow the use of the objects 
// as pieces in a fully functional program.  Permission is also granted to 
// redistribute the source code of MOKit for FREE as long as this copyright 
// notice is left intact and unchanged.  NO WARRANTY is expressed or implied.  
// The author will under no circumstances be held responsible for ANY 
// consequences from the use of these objects.  Since you don't have to pay 
// for them, and full source is provided, I think this is perfectly fair.

#import "MOString.h"

extern char *MOBuildStringFromFormatV(const char *formatStr, 
			va_list param_list);

@implementation MOString(Comparing)

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// =-=-=-=-=-=-=-=-=-=-=-=-=- Comparing MOStrings -=-=-=-=-=-=-=-=-=-=-=-=-=
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

- (int)compare:stringObject
// Calls compareStr:[stringObject stringValue] caseSensitive:YES length:-1 
// withTable:NULL.
// See the comment for that method.
{
	if (!stringObject)  {
		return [self compareStr:NULL caseSensitive:YES length:-1 
					withTable:NULL];
	}  else  {
		return [self compareStr:[stringObject stringValue] caseSensitive:YES 
					length:-1 withTable:NULL];
	}
}

- (int)compare:stringObject caseSensitive:(BOOL)flag
// Calls compareStr:[stringObject stringValue] caseSensitive:flag length:-1 
// withTable:NULL.
// See the comment for that method.
{
	if (!stringObject)  {
		return [self compareStr:NULL caseSensitive:flag length:-1 
					withTable:NULL];
	}  else  {
		return [self compareStr:[stringObject stringValue] caseSensitive:flag 
					length:-1 withTable:NULL];
	}
}

- (int)compare:stringObject caseSensitive:(BOOL)flag length:(int)length
// Calls compareStr:[stringObject stringValue] caseSensitive:flag length:length 
// withTable:NULL.
// See the comment for that method.
{
	if (!stringObject)  {
		return [self compareStr:NULL caseSensitive:flag length:length 
					withTable:NULL];
	}  else  {
		return [self compareStr:[stringObject stringValue] caseSensitive:flag 
					length:length withTable:NULL];
	}
}

- (int)compare:stringObject caseSensitive:(BOOL)flag length:(int)length 
			withTable:(NXStringOrderTable *)table
// Calls compareStr:[stringObject stringValue] caseSensitive:flag length:length 
// withTable:table.
// See the comment for that method.
{
	if (!stringObject)  {
		return [self compareStr:NULL caseSensitive:flag length:length 
					withTable:table];
	}  else  {
		return [self compareStr:[stringObject stringValue] caseSensitive:flag 
					length:length withTable:table];
	}
}

- (int)compareStr:(const char *)s
// Calls compareStr:s caseSensitive:YES length:-1 withTable:NULL.
// See the comment for that method.
{
	return [self compareStr:s caseSensitive:YES length:-1 withTable:NULL];
}

- (int)compareStr:(const char *)s caseSensitive:(BOOL)flag
// Calls compareStr:s caseSensitive:flag length:-1 withTable:NULL.
// See the comment for that method.
{
	return [self compareStr:s caseSensitive:flag length:-1 withTable:NULL];
}

- (int)compareStr:(const char *)s caseSensitive:(BOOL)flag length:(int)length
// Calls compareStr:s caseSensitive:flag length:length withTable:NULL.
// See the comment for that method.
{
	return [self compareStr:s caseSensitive:flag length:length withTable:NULL];
}

- (int)compareStr:(const char *)s caseSensitive:(BOOL)flag length:(int)length
			withTable:(NXStringOrderTable *)table
// Returns 1, 0, or -1 meaning that the receiver's string is greater than,
// equal to, or less than the given char string.  
// Returns -2 if len is too big for either string.  NULL strings are less 
// than any other string.  Two null strings are equal.  flag determines 
// whether case is significant.  len sets a limit on the number of characters
// from each string to use for comparison.  A length of -1 means the whole 
// string.  table is a string order table.  A NULL table means use the 
// default string table.
{
	// Null strings are the "least"
	if ((!(isUnique?uStr:str)) && (!s))  {
		return 0;
	}  else if (!(isUnique?uStr:str))  {
		return -1;
	}  else if (!s)  {
		return 1;
	}
	
	// len greater than the length of either string is a no-no.
	if ((length > (int)len) || (length > (int)strlen(s)))  {
		return -2;
	}
	
	return NXOrderStrings((isUnique?uStr:str), s, flag, length, table);
}

- (int)endCompare:stringObject
// Calls endCompareStr:[stringObject stringValue] caseSensitive:YES length:-1 
// withTable:NULL.
// See the comment for that method.
{
	if (!stringObject)  {
		return [self endCompareStr:NULL caseSensitive:YES length:-1 
					withTable:NULL];
	}  else  {
		return [self endCompareStr:[stringObject stringValue] 
					caseSensitive:YES length:-1 withTable:NULL];
	}
}

- (int)endCompare:stringObject caseSensitive:(BOOL)flag
// Calls endCompareStr:[stringObject stringValue] caseSensitive:flag length:-1 
// withTable:NULL.
// See the comment for that method.
{
	if (!stringObject)  {
		return [self endCompareStr:NULL caseSensitive:flag length:-1 
					withTable:NULL];
	}  else  {
		return [self endCompareStr:[stringObject stringValue] 
					caseSensitive:flag length:-1 withTable:NULL];
	}
}

- (int)endCompare:stringObject caseSensitive:(BOOL)flag length:(int)length
// Calls endCompareStr:[stringObject stringValue] caseSensitive:flag 
// length:length withTable:NULL.
// See the comment for that method.
{
	if (!stringObject)  {
		return [self endCompareStr:NULL caseSensitive:flag length:length 
					withTable:NULL];
	}  else  {
		return [self endCompareStr:[stringObject stringValue] 
					caseSensitive:flag length:length withTable:NULL];
	}
}

- (int)endCompare:stringObject caseSensitive:(BOOL)flag length:(int)length 
			withTable:(NXStringOrderTable *)table
// Calls endCompareStr:[stringObject stringValue] caseSensitive:flag 
// length:length withTable:table.
// See the comment for that method.
{
	if (!stringObject)  {
		return [self endCompareStr:NULL caseSensitive:flag length:length 
					withTable:table];
	}  else  {
		return [self endCompareStr:[stringObject stringValue] 
					caseSensitive:flag length:length withTable:table];
	}
}

- (int)endCompareStr:(const char *)s
// Calls endCompareStr:s caseSensitive:YES length:-1 withTable:NULL.
// See the comment for that method.
{
	return [self endCompareStr:s caseSensitive:YES 
				length:-1 withTable:NULL];
}

- (int)endCompareStr:(const char *)s caseSensitive:(BOOL)flag
// Calls endCompareStr:s caseSensitive:flag length:-1 withTable:NULL.
// See the comment for that method.
{
	return [self endCompareStr:s caseSensitive:flag 
				length:-1 withTable:NULL];
}

- (int)endCompareStr:(const char *)s caseSensitive:(BOOL)flag 
			length:(int)length
// Calls endCompareStr:s caseSensitive:flag length:length withTable:NULL.
// See the comment for that method.
{
	return [self endCompareStr:s caseSensitive:flag 
				length:length withTable:NULL];
}

- (int)endCompareStr:(const char *)s caseSensitive:(BOOL)flag 
			length:(int)length withTable:(NXStringOrderTable *)table
// Both s and the MOString's contents must be non-null and non-empty.
// The last length characters of s are compared to the last length 
// characters of the string's contents (str).  If length is -1, then s 
// must be no longer than str and the strlen of s is used for the length.
// Returns 1, 0 or -1 meaning that the receiver's string is greater than, 
// equal to or less than s.  Returns -2 if there are length problems.
// flag determines if case is considered significant for the comparison.
// table is an optional string order table.  If it is NULL, the default
// order table will be used.
{
	const char *strIndex, *sIndex;
	int sLen;
	
	// No null or empty strings allowed for end comparison
	if ((!s) || (!*s) || (!(isUnique?uStr:str)) || (!(isUnique?*uStr:*str)))  {
		return -2;
	}
	
	sLen = strlen(s);
	// If no length is provided use strlen(s)
	if (length == -1)  {
		length = sLen;
	}
	
	// length must be no longer than either string
	if ((length > len) || (length > sLen))  {
		return -2;
	}
	
	// Figure out where to start on both strings
	strIndex = ((isUnique?uStr:str) + len - length);
	sIndex = (s + sLen - length);
	
	return NXOrderStrings(strIndex, sIndex, flag, length, table);
}

@end

