/*
* Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
* Source License Version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License."
*
* @APPLE_LICENSE_HEADER_END@
*/
#import "AMString.h"
#import <string.h>
#import <stdlib.h>
#import <stdio.h>
#import <stdarg.h>
static String **_strings;
static int _nstrings;
@implementation String
+ (String *)uniqueString:(char *)s
{
unsigned int top, bot, mid, range;
int comp, i;
if (s == NULL) return NULL;
if (_nstrings == 0)
{
_strings = (String **)malloc(sizeof(String *));
_strings[_nstrings] = [[String alloc] initWithChars:s];
_nstrings++;
return _strings[_nstrings - 1];
}
top = _nstrings - 1;
bot = 0;
mid = top / 2;
range = top - bot;
while (range > 1)
{
comp = strcmp(s, [_strings[mid] value]);
if (comp == 0) return [_strings[mid] retain];
else if (comp < 0) top = mid;
else bot = mid;
range = top - bot;
mid = bot + (range / 2);
}
if (strcmp(s, [_strings[top] value]) == 0) return [_strings[top] retain];
if (strcmp(s, [_strings[bot] value]) == 0) return [_strings[bot] retain];
if (strcmp(s, [_strings[bot] value]) < 0) mid = bot;
else if (strcmp(s, [_strings[top] value]) > 0) mid = top + 1;
else mid = top;
_nstrings++;
_strings = (String **)realloc(_strings, sizeof(String *) * _nstrings);
for (i = _nstrings - 1; i > mid; i--) _strings[i] = _strings[i - 1];
_strings[mid] = [[String alloc] initWithChars:s];
return _strings[mid];
}
- (String *)initWithChars:(char *)s
{
[super init];
len = strlen(s);
val = malloc(len + 1);
bcopy(s, val, len);
val[len] = '\0';
return self;
}
- (String *)initWithInteger:(int)i
{
char s[64];
[super init];
sprintf(s, " len = strlen(s);
val = malloc(len + 1);
bcopy(s, val, len);
val[len] = '\0';
return self;
}
+ (String *)stringWithInteger:(int)n
{
char s[64];
sprintf(s, " return [String uniqueString:s];
}
static unsigned int uniqueStringIndex(char *s)
{
unsigned int top, bot, mid, range;
int comp;
if (_nstrings == 0) return IndexNull;
top = _nstrings - 1;
bot = 0;
mid = top / 2;
range = top - bot;
while (range > 1)
{
comp = strcmp(s, [_strings[mid] value]);
if (comp == 0) return mid;
else if (comp < 0) top = mid;
else bot = mid;
range = top - bot;
mid = bot + (range / 2);
}
if (strcmp(s, [_strings[top] value]) == 0) return top;
if (strcmp(s, [_strings[bot] value]) == 0) return bot;
return IndexNull;
}
- (void)dealloc
{
unsigned int i, where;
where = uniqueStringIndex(val);
free(val);
if (where == IndexNull) return;
for (i = where + 1; i < _nstrings; i++) _strings[i-1] = _strings[i];
_nstrings--;
if (_nstrings == 0)
{
free(_strings);
_strings = NULL;
}
else
{
_strings = (String **)realloc(_strings, sizeof(String *) * _nstrings);
}
[super dealloc];
}
- (String *)prefix:(char)c
{
int i;
char *t;
String *x;
for (i = 0; ((val[i] != '\0') && (val[i] != c)); i++);
if (i == 0) return nil;
if (val[i] == '\0')
{
x = [String uniqueString:val];
return x;
}
t = malloc(i + 1);
bcopy(val, t, i);
t[i] = '\0';
x = [String uniqueString:t];
free(t);
return x;
}
- (String *)postfix:(char)c
{
int i, l;
char *t;
String *x;
for (i = 0; ((val[i] != '\0') && (val[i] != c)); i++);
if (val[i] == '\0') return nil;
l = strlen(val) - i;
if (l == 1) return nil;
t = malloc(l);
l--;
bcopy((val + i + 1), t, l);
t[l] = '\0';
x = [String uniqueString:t];
free(t);
return x;
}
- (String *)presuffix:(char)c
{
int i;
char *t;
String *x;
for (i = len - 1; ((i >= 0) && (val[i] != c)); i--);
if (i == 0) return nil;
if (val[0] == '\0') return nil;
t = malloc(i + 1);
bcopy(val, t, i);
t[i] = '\0';
x = [String uniqueString:t];
free(t);
return x;
}
- (String *)suffix:(char)c
{
int i, l;
char *t;
String *x;
l = len;
for (i = len - 1; ((i >= 0) && (val[i] != c)); i--);
if (i == 0) return nil;
l -= i;
if (l == 1) return nil;
t = malloc(l);
l--;
bcopy((val + i + 1), t, l);
t[l] = '\0';
x = [String uniqueString:t];
free(t);
return x;
}
- (String *)lowerCase
{
int i;
char *t;
String *x;
t = malloc(len + 1);
for (i = 0; val[i] != '\0'; i++)
{
if ((val[i] >= 'A') && (val[i] <= 'Z'))
t[i] = val[i] + 32;
else
t[i] = val[i];
}
t[i] = '\0';
x = [String uniqueString:t];
free(t);
return x;
}
- (String *)upperCase
{
int i;
char *t;
String *x;
t = malloc(len + 1);
for (i = 0; val[i] != '\0'; i++)
{
if ((val[i] >= 'a') && (val[i] <= 'z'))
t[i] = val[i] - 32;
else
t[i] = val[i];
}
t[i] = '\0';
x = [String uniqueString:t];
free(t);
return x;
}
- (Array *)explode:(char)c
{
Array *l;
String *x;
unsigned int p;
l = [[Array alloc] init];
p = 0;
x = [self explode:c pos:&p];
while (x != nil)
{
[l addObject:x];
[x release];
x = [self explode:c pos:&p];
}
return l;
}
- (String *)explode:(char)c pos:(unsigned int *)where
{
String *x;
char *p, *t;
int i, n;
if ((*where) >= len) return nil;
p = val + (*where);
while (p[0] != '\0')
{
for (i = 0; ((p[i] != '\0') && p[i] != c); i++);
n = i;
t = malloc(n + 1);
for (i = 0; i < n; i++) t[i] = p[i];
t[n] = '\0';
x = [String uniqueString:t];
free(t);
*where += n;
if (p[i] == c) *where += 1;
return x;
}
return nil;
}
- (char *)value
{
return val;
}
- (int)intValue
{
return atoi(val);
}
- (char *)copyValue
{
char *t;
t = malloc(len + 1);
bcopy(val, t, len);
return t;
}
+ (String *)concatStrings:(String *)s :(String *)t
{
int l;
char *n;
String *x;
if (s == nil) return t;
if (t == nil) return s;
l = [s length] + [t length] + 1;
n = malloc(l);
sprintf(n, " x = [String uniqueString:n];
free(n);
return x;
}
/* compare self with s */
- (int)compare:(String *)s
{
/* define nil as the smallest value string */
if (s == nil) return 1;
if (self == s) return 0;
return strcmp(val, [s value]);
}
/* compare self with s */
- (BOOL)equal:(String *)s
{
if (s == nil) return NO;
if (self == s) return YES;
if (strcmp(val, [s value]) == 0) return YES;
return NO;
}
- (unsigned int)length
{
return len;
}
/*
* returns pointer to next instance of char following position p
*/
- (char *)scan:(char)c pos:(int *)p
{
if (*p >= len) return NULL;
(*p)++;
while ((*p < len) && (val[*p] != c)) (*p)++;
if (*p >= len)
{
*p = len;
return NULL;
}
return val + (*p);
}
@end