1995-03-12 19:54:14 +00:00
|
|
|
/* Implementation of GNUSTEP string class
|
1997-01-06 21:01:32 +00:00
|
|
|
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
|
1995-03-12 19:54:14 +00:00
|
|
|
|
1996-04-17 20:17:45 +00:00
|
|
|
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
1995-03-12 19:54:14 +00:00
|
|
|
Date: January 1995
|
1997-05-03 18:05:21 +00:00
|
|
|
|
|
|
|
Unicode implementation by Stevo Crvenkovski
|
|
|
|
<stevoc@lotus.mpt.com.mk>
|
|
|
|
Date: February 1997
|
|
|
|
|
1996-05-12 00:56:10 +00:00
|
|
|
This file is part of the GNUstep Base Library.
|
1995-03-12 19:54:14 +00:00
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
1997-05-03 18:05:21 +00:00
|
|
|
|
1995-03-12 19:54:14 +00:00
|
|
|
You should have received a copy of the GNU Library General Public
|
|
|
|
License along with this library; if not, write to the Free
|
|
|
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
1997-05-03 18:05:21 +00:00
|
|
|
*/
|
1995-03-12 19:54:14 +00:00
|
|
|
|
1995-04-03 01:35:42 +00:00
|
|
|
/* Caveats:
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
Some implementations will need to be changed.
|
1996-09-02 13:20:20 +00:00
|
|
|
Does not support all justification directives for `%@' in format strings
|
|
|
|
on non-GNU-libc systems.
|
1995-04-03 01:35:42 +00:00
|
|
|
*/
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
/* Initial implementation of Unicode. Version 0.0.0 :)
|
1997-09-01 21:59:51 +00:00
|
|
|
Locales not yet supported.
|
1997-05-03 18:05:21 +00:00
|
|
|
Limited choice of default encodings.
|
|
|
|
*/
|
|
|
|
|
1997-11-06 00:51:23 +00:00
|
|
|
#include <config.h>
|
1996-04-17 15:34:35 +00:00
|
|
|
#include <gnustep/base/preface.h>
|
1996-04-17 15:23:00 +00:00
|
|
|
#include <gnustep/base/Coding.h>
|
1995-04-17 21:13:20 +00:00
|
|
|
#include <Foundation/NSString.h>
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
#include <Foundation/NSArray.h>
|
|
|
|
#include <Foundation/NSCharacterSet.h>
|
1996-03-26 19:35:47 +00:00
|
|
|
#include <Foundation/NSException.h>
|
1996-02-22 15:18:57 +00:00
|
|
|
#include <Foundation/NSValue.h>
|
1996-10-31 17:03:44 +00:00
|
|
|
#include <Foundation/NSDictionary.h>
|
1996-11-24 21:04:24 +00:00
|
|
|
#include <Foundation/NSUserDefaults.h>
|
1996-04-17 15:23:00 +00:00
|
|
|
#include <gnustep/base/IndexedCollection.h>
|
1997-09-01 21:59:51 +00:00
|
|
|
#include <Foundation/NSData.h>
|
1996-04-17 15:23:00 +00:00
|
|
|
#include <gnustep/base/IndexedCollectionPrivate.h>
|
1995-04-03 01:35:42 +00:00
|
|
|
#include <limits.h>
|
1996-07-15 18:41:44 +00:00
|
|
|
#include <string.h> // for strstr()
|
1996-10-31 17:03:44 +00:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
#include <gnustep/base/MallocAddress.h>
|
|
|
|
#include <gnustep/base/behavior.h>
|
|
|
|
|
|
|
|
#include <gnustep/base/NSGSequence.h>
|
|
|
|
#include <gnustep/base/Unicode.h>
|
|
|
|
|
|
|
|
|
|
|
|
// Choose default encoding
|
|
|
|
// xxx Should be install time option, not compile time
|
|
|
|
#define DEFAULT_ENCODING NSNEXTSTEPStringEncoding
|
|
|
|
// #define DEFAULT_ENCODING NSASCIIStringEncoding
|
|
|
|
// #define DEFAULT_ENCODING NSISOLatin1StringEncoding
|
|
|
|
// #define DEFAULT_ENCODING NSCyrillicStringEncoding
|
|
|
|
|
1997-09-13 17:52:31 +00:00
|
|
|
#if defined(__WIN32__) || defined(_WIN32)
|
|
|
|
|
|
|
|
#define PATH_COMPONENT @"\\"
|
|
|
|
#define PATH_COMPONENT_LEN 1
|
|
|
|
#define PATH_COMPONENT2 @"/"
|
|
|
|
#define PATH_COMPONENT_LEN2 1
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#define PATH_COMPONENT @"/"
|
|
|
|
#define PATH_COMPONENT_LEN 1
|
|
|
|
|
|
|
|
#endif /* Path components */
|
1995-03-12 19:54:14 +00:00
|
|
|
|
|
|
|
@implementation NSString
|
1995-04-03 01:35:42 +00:00
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
/* For unichar strings. */
|
1995-08-09 16:07:19 +00:00
|
|
|
static Class NSString_concrete_class;
|
|
|
|
static Class NSMutableString_concrete_class;
|
|
|
|
|
|
|
|
/* For CString's */
|
|
|
|
static Class NSString_c_concrete_class;
|
|
|
|
static Class NSMutableString_c_concrete_class;
|
|
|
|
|
|
|
|
+ (void) _setConcreteClass: (Class)c
|
|
|
|
{
|
|
|
|
NSString_concrete_class = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (void) _setConcreteCClass: (Class)c
|
|
|
|
{
|
|
|
|
NSString_c_concrete_class = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (void) _setMutableConcreteClass: (Class)c
|
|
|
|
{
|
|
|
|
NSMutableString_concrete_class = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (void) _setMutableConcreteCClass: (Class)c
|
|
|
|
{
|
|
|
|
NSMutableString_c_concrete_class = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (Class) _concreteClass
|
|
|
|
{
|
|
|
|
return NSString_concrete_class;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (Class) _concreteCClass
|
|
|
|
{
|
|
|
|
return NSString_c_concrete_class;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (Class) _mutableConcreteClass
|
|
|
|
{
|
|
|
|
return NSMutableString_concrete_class;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (Class) _mutableConcreteCClass
|
|
|
|
{
|
|
|
|
return NSMutableString_c_concrete_class;
|
|
|
|
}
|
|
|
|
|
1996-01-23 23:30:05 +00:00
|
|
|
#if HAVE_REGISTER_PRINTF_FUNCTION
|
1996-01-23 23:41:02 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <printf.h>
|
|
|
|
#include <stdarg.h>
|
1996-05-06 18:59:01 +00:00
|
|
|
|
1996-07-15 18:41:44 +00:00
|
|
|
/* <sattler@volker.cs.Uni-Magdeburg.DE>, with libc-5.3.9 thinks this
|
|
|
|
flag PRINTF_ATSIGN_VA_LIST should be 0, but for me, with libc-5.0.9,
|
1997-09-01 21:59:51 +00:00
|
|
|
it crashes. -mccallum
|
|
|
|
|
|
|
|
Apparently GNU libc 2.xx needs this to be 0 also, along with Linux
|
|
|
|
libc versions 5.2.xx and higher (including libc6, which is just GNU
|
|
|
|
libc). -chung */
|
1996-07-15 18:41:44 +00:00
|
|
|
#define PRINTF_ATSIGN_VA_LIST \
|
|
|
|
(defined(_LINUX_C_LIB_VERSION_MINOR) \
|
|
|
|
&& _LINUX_C_LIB_VERSION_MAJOR <= 5 \
|
|
|
|
&& _LINUX_C_LIB_VERSION_MINOR < 2)
|
1996-05-07 01:14:54 +00:00
|
|
|
|
|
|
|
#if ! PRINTF_ATSIGN_VA_LIST
|
1996-05-06 18:59:01 +00:00
|
|
|
static int
|
1997-09-01 21:59:51 +00:00
|
|
|
arginfo_func (const struct printf_info *info, size_t n, int *argtypes)
|
|
|
|
{
|
1996-05-06 18:59:01 +00:00
|
|
|
*argtypes = PA_POINTER;
|
|
|
|
return 1;
|
|
|
|
}
|
1996-07-15 18:41:44 +00:00
|
|
|
#endif /* !PRINTF_ATSIGN_VA_LIST */
|
1996-05-06 18:59:01 +00:00
|
|
|
|
|
|
|
static int
|
1996-01-23 23:41:02 +00:00
|
|
|
handle_printf_atsign (FILE *stream,
|
|
|
|
const struct printf_info *info,
|
1996-05-07 01:14:54 +00:00
|
|
|
#if PRINTF_ATSIGN_VA_LIST
|
|
|
|
va_list *ap_pointer)
|
1997-09-01 21:59:51 +00:00
|
|
|
#elif defined(_LINUX_C_LIB_VERSION_MAJOR) \
|
|
|
|
&& _LINUX_C_LIB_VERSION_MAJOR < 6
|
1996-05-07 01:14:54 +00:00
|
|
|
const void **const args)
|
1997-09-01 21:59:51 +00:00
|
|
|
#else /* GNU libc needs the following. */
|
|
|
|
const void *const *args)
|
1996-05-07 01:14:54 +00:00
|
|
|
#endif
|
1996-01-23 23:30:05 +00:00
|
|
|
{
|
1996-05-07 01:14:54 +00:00
|
|
|
#if ! PRINTF_ATSIGN_VA_LIST
|
1996-05-06 18:59:01 +00:00
|
|
|
const void *ptr = *args;
|
1996-05-07 01:14:54 +00:00
|
|
|
#endif
|
1996-01-23 23:30:05 +00:00
|
|
|
id string_object;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
/* xxx This implementation may not pay pay attention to as much
|
|
|
|
of printf_info as it should. */
|
|
|
|
|
1996-05-07 01:14:54 +00:00
|
|
|
#if PRINTF_ATSIGN_VA_LIST
|
|
|
|
string_object = va_arg (*ap_pointer, id);
|
|
|
|
#else
|
1996-07-15 18:41:44 +00:00
|
|
|
string_object = *((id*) ptr);
|
1996-05-07 01:14:54 +00:00
|
|
|
#endif
|
1996-01-23 23:30:05 +00:00
|
|
|
len = fprintf(stream, "%*s",
|
|
|
|
(info->left ? - info->width : info->width),
|
1997-05-03 17:05:57 +00:00
|
|
|
[[string_object description] cStringNoCopy]);
|
1996-01-23 23:30:05 +00:00
|
|
|
return len;
|
|
|
|
}
|
|
|
|
#endif /* HAVE_REGISTER_PRINTF_FUNCTION */
|
|
|
|
|
1995-04-03 01:35:42 +00:00
|
|
|
+ (void) initialize
|
|
|
|
{
|
1996-11-24 17:20:45 +00:00
|
|
|
if (self == [NSString class])
|
1995-04-03 01:35:42 +00:00
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
NSString_concrete_class = [NSGString class];
|
1995-08-09 16:07:19 +00:00
|
|
|
NSString_c_concrete_class = [NSGCString class];
|
1997-05-03 18:05:21 +00:00
|
|
|
NSMutableString_concrete_class = [NSGMutableString class];
|
1995-08-09 16:07:19 +00:00
|
|
|
NSMutableString_c_concrete_class = [NSGMutableCString class];
|
1996-01-23 23:30:05 +00:00
|
|
|
|
|
|
|
#if HAVE_REGISTER_PRINTF_FUNCTION
|
1996-01-23 23:41:02 +00:00
|
|
|
if (register_printf_function ('@',
|
1997-09-01 21:59:51 +00:00
|
|
|
handle_printf_atsign,
|
1996-05-07 01:14:54 +00:00
|
|
|
#if PRINTF_ATSIGN_VA_LIST
|
|
|
|
0))
|
|
|
|
#else
|
1997-09-01 21:59:51 +00:00
|
|
|
arginfo_func))
|
1996-05-07 01:14:54 +00:00
|
|
|
#endif
|
1996-03-26 19:35:47 +00:00
|
|
|
[NSException raise: NSGenericException
|
|
|
|
format: @"register printf handling of %%@ failed"];
|
1996-01-23 23:30:05 +00:00
|
|
|
#endif /* HAVE_REGISTER_PRINTF_FUNCTION */
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1995-11-19 20:29:39 +00:00
|
|
|
+ allocWithZone: (NSZone*)z
|
|
|
|
{
|
1997-05-03 17:05:57 +00:00
|
|
|
if ([self class] == [NSString class])
|
|
|
|
return NSAllocateObject ([self _concreteClass], 0, z);
|
|
|
|
return [super allocWithZone:z];
|
1995-11-19 20:29:39 +00:00
|
|
|
}
|
|
|
|
|
1995-04-03 01:35:42 +00:00
|
|
|
// Creating Temporary Strings
|
|
|
|
|
1997-05-03 17:05:57 +00:00
|
|
|
+ (NSString*) string
|
|
|
|
{
|
|
|
|
return [[[self alloc] init] autorelease];
|
|
|
|
}
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
+ (NSString*) stringWithCharacters: (const unichar*)chars
|
|
|
|
length: (unsigned int)length
|
|
|
|
{
|
|
|
|
return [[[self alloc]
|
|
|
|
initWithCharacters:chars length:length]
|
|
|
|
autorelease];
|
|
|
|
}
|
|
|
|
|
1995-04-03 01:35:42 +00:00
|
|
|
+ (NSString*) stringWithCString: (const char*) byteString
|
|
|
|
{
|
1995-11-19 20:29:39 +00:00
|
|
|
return [[[self alloc] initWithCString:byteString]
|
1995-04-03 01:35:42 +00:00
|
|
|
autorelease];
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (NSString*) stringWithCString: (const char*)byteString
|
|
|
|
length: (unsigned int)length
|
|
|
|
{
|
1995-11-19 20:29:39 +00:00
|
|
|
return [[[self alloc]
|
1995-08-09 16:07:19 +00:00
|
|
|
initWithCString:byteString length:length]
|
1995-04-03 01:35:42 +00:00
|
|
|
autorelease];
|
|
|
|
}
|
|
|
|
|
1997-03-03 20:07:35 +00:00
|
|
|
+ (NSString*) stringWithContentsOfFile:(NSString *)path
|
|
|
|
{
|
|
|
|
return [[[self alloc]
|
|
|
|
initWithContentsOfFile: path] autorelease];
|
|
|
|
}
|
|
|
|
|
1995-04-03 01:35:42 +00:00
|
|
|
+ (NSString*) stringWithFormat: (NSString*)format,...
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
id ret;
|
|
|
|
|
|
|
|
va_start(ap, format);
|
1995-11-19 20:29:39 +00:00
|
|
|
ret = [[[self alloc] initWithFormat:format arguments:ap]
|
1995-04-03 01:35:42 +00:00
|
|
|
autorelease];
|
|
|
|
va_end(ap);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (NSString*) stringWithFormat: (NSString*)format
|
|
|
|
arguments: (va_list)argList
|
|
|
|
{
|
1995-11-19 20:29:39 +00:00
|
|
|
return [[[self alloc]
|
1995-08-09 16:07:19 +00:00
|
|
|
initWithFormat:format arguments:argList]
|
1995-04-03 01:35:42 +00:00
|
|
|
autorelease];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
// Initializing Newly Allocated Strings
|
1995-04-03 01:35:42 +00:00
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
/* This is the designated initializer for Unicode Strings. */
|
|
|
|
- (id) initWithCharactersNoCopy: (unichar*)chars
|
1995-04-03 01:35:42 +00:00
|
|
|
length: (unsigned int)length
|
|
|
|
freeWhenDone: (BOOL)flag
|
|
|
|
{
|
1995-08-09 16:26:44 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-03 01:35:42 +00:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) initWithCharacters: (const unichar*)chars
|
|
|
|
length: (unsigned int)length
|
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
unichar *s;
|
|
|
|
OBJC_MALLOC(s, unichar, length+1);
|
|
|
|
if (chars)
|
|
|
|
memcpy(s, chars,2*length);
|
|
|
|
s[length] = (unichar)0;
|
|
|
|
return [self initWithCharactersNoCopy:s length:length freeWhenDone:YES];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
/* This is the designated initializer for CStrings. */
|
|
|
|
- (id) initWithCStringNoCopy: (char*)byteString
|
1995-04-03 01:35:42 +00:00
|
|
|
length: (unsigned int)length
|
|
|
|
freeWhenDone: (BOOL)flag
|
|
|
|
{
|
1995-08-09 16:26:44 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-03 01:35:42 +00:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
- (id) initWithCString: (const char*)byteString length: (unsigned int)length
|
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
OBJC_MALLOC(s, char, length+1);
|
|
|
|
if (byteString)
|
|
|
|
memcpy(s, byteString, length);
|
|
|
|
s[length] = '\0';
|
|
|
|
return [self initWithCStringNoCopy:s length:length freeWhenDone:YES];
|
|
|
|
}
|
1997-01-09 16:24:07 +00:00
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
- (id) initWithCString: (const char*)byteString
|
|
|
|
{
|
|
|
|
return [self initWithCString:byteString
|
|
|
|
length:(byteString ? strlen(byteString) : 0)];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
- (id) initWithString: (NSString*)string
|
1995-04-03 01:35:42 +00:00
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
unichar *s;
|
|
|
|
OBJC_MALLOC(s, unichar, [string length]+1);
|
|
|
|
[string getCharacters:s];
|
|
|
|
s[[string length]] = (unichar)0;
|
|
|
|
return [self initWithCharactersNoCopy:s length:[string length] freeWhenDone:YES];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (id) initWithFormat: (NSString*)format,...
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, format);
|
|
|
|
self = [self initWithFormat:format arguments:ap];
|
|
|
|
va_end(ap);
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* xxx Change this when we have non-CString classes */
|
|
|
|
- (id) initWithFormat: (NSString*)format
|
1996-07-15 18:41:44 +00:00
|
|
|
arguments: (va_list)arg_list
|
1995-04-03 01:35:42 +00:00
|
|
|
{
|
|
|
|
#if HAVE_VSPRINTF
|
1996-05-31 16:12:24 +00:00
|
|
|
const char *format_cp = [format cStringNoCopy];
|
1996-05-31 15:10:53 +00:00
|
|
|
int format_len = strlen (format_cp);
|
1996-07-15 18:41:44 +00:00
|
|
|
/* xxx horrible disgusting BUFFER_EXTRA arbitrary limit; fix this! */
|
1997-01-09 16:01:52 +00:00
|
|
|
#define BUFFER_EXTRA 1024*500
|
1996-07-15 18:41:44 +00:00
|
|
|
char buf[format_len + BUFFER_EXTRA];
|
|
|
|
int printed_len = 0;
|
|
|
|
|
|
|
|
#if ! HAVE_REGISTER_PRINTF_FUNCTION
|
|
|
|
/* If the available libc doesn't have `register_printf_function()', then
|
|
|
|
the `%@' printf directive isn't available with printf() and friends.
|
|
|
|
Here we make a feable attempt to handle it. */
|
|
|
|
{
|
|
|
|
/* We need a local copy since we change it. (Changing and undoing
|
|
|
|
the change doesn't work because some format strings are constant
|
|
|
|
strings, placed in a non-writable section of the executable, and
|
1996-09-02 13:20:20 +00:00
|
|
|
writing to them will cause a segfault.) */
|
1996-07-15 18:41:44 +00:00
|
|
|
char format_cp_copy[format_len+1];
|
1996-09-25 13:45:31 +00:00
|
|
|
char *atsign_pos; /* points to a location inside format_cp_copy */
|
1996-07-15 18:41:44 +00:00
|
|
|
char *format_to_go = format_cp_copy;
|
|
|
|
strcpy (format_cp_copy, format_cp);
|
|
|
|
/* Loop once for each `%@' in the format string. */
|
|
|
|
while ((atsign_pos = strstr (format_to_go, "%@")))
|
|
|
|
{
|
|
|
|
const char *cstring;
|
1997-09-01 21:59:51 +00:00
|
|
|
char *formatter_pos; // Position for formatter.
|
|
|
|
|
1996-07-15 18:41:44 +00:00
|
|
|
/* If there is a "%%@", then do the right thing: print it literally. */
|
|
|
|
if ((*(atsign_pos-1) == '%')
|
|
|
|
&& atsign_pos != format_cp_copy)
|
|
|
|
continue;
|
|
|
|
/* Temporarily terminate the string before the `%@'. */
|
|
|
|
*atsign_pos = '\0';
|
|
|
|
/* Print the part before the '%@' */
|
1996-10-31 18:27:04 +00:00
|
|
|
printed_len += VSPRINTF_LENGTH (vsprintf (buf+printed_len,
|
|
|
|
format_to_go, arg_list));
|
1997-09-01 21:59:51 +00:00
|
|
|
/* Skip arguments used in last vsprintf(). */
|
|
|
|
while ((formatter_pos = strchr(format_to_go, '%')))
|
|
|
|
{
|
|
|
|
char *spec_pos; // Position of conversion specifier.
|
|
|
|
|
|
|
|
if (*(formatter_pos+1) == '%')
|
|
|
|
{
|
|
|
|
format_to_go = formatter_pos+2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* Specifiers from K&R C 2nd ed. */
|
|
|
|
spec_pos = strpbrk(formatter_pos+1, "dioxXucsfeEgGpn\0");
|
|
|
|
switch (*spec_pos)
|
|
|
|
{
|
|
|
|
case 'd': case 'i': case 'o':
|
|
|
|
case 'x': case 'X': case 'u': case 'c':
|
|
|
|
va_arg(arg_list, int);
|
|
|
|
break;
|
|
|
|
case 's':
|
1997-09-18 14:56:47 +00:00
|
|
|
if (*(spec_pos - 1) == '*')
|
|
|
|
va_arg(arg_list, int*);
|
1997-09-01 21:59:51 +00:00
|
|
|
va_arg(arg_list, char*);
|
|
|
|
break;
|
|
|
|
case 'f': case 'e': case 'E': case 'g': case 'G':
|
|
|
|
va_arg(arg_list, double);
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
va_arg(arg_list, void*);
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
va_arg(arg_list, int*);
|
|
|
|
break;
|
|
|
|
case '\0':
|
|
|
|
/* Make sure loop exits on next iteration. */
|
|
|
|
spec_pos--;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
format_to_go = spec_pos+1;
|
|
|
|
}
|
1996-07-15 18:41:44 +00:00
|
|
|
/* Get a C-string (char*) from the String object, and print it. */
|
1997-09-01 21:59:51 +00:00
|
|
|
cstring = [[(id) va_arg (arg_list, id) description] cStringNoCopy];
|
1996-07-15 18:41:44 +00:00
|
|
|
strcat (buf+printed_len, cstring);
|
|
|
|
printed_len += strlen (cstring);
|
|
|
|
/* Skip over this `%@', and look for another one. */
|
|
|
|
format_to_go = atsign_pos + 2;
|
|
|
|
}
|
|
|
|
/* Print the rest of the string after the last `%@'. */
|
1996-10-31 18:27:04 +00:00
|
|
|
printed_len += VSPRINTF_LENGTH (vsprintf (buf+printed_len,
|
|
|
|
format_to_go, arg_list));
|
1996-07-15 18:41:44 +00:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
/* The available libc has `register_printf_function()', so the `%@'
|
|
|
|
printf directive is handled by printf and friends. */
|
1996-10-31 18:27:04 +00:00
|
|
|
printed_len = VSPRINTF_LENGTH (vsprintf (buf, format_cp, arg_list));
|
1996-07-15 18:41:44 +00:00
|
|
|
#endif /* !HAVE_REGISTER_PRINTF_FUNCTION */
|
1996-05-31 15:10:53 +00:00
|
|
|
|
1996-07-15 18:41:44 +00:00
|
|
|
/* Raise an exception if we overran our buffer. */
|
1996-05-31 15:10:53 +00:00
|
|
|
NSParameterAssert (printed_len < format_len + BUFFER_EXTRA - 1);
|
1995-04-03 01:35:42 +00:00
|
|
|
return [self initWithCString:buf];
|
1996-07-15 18:41:44 +00:00
|
|
|
#else /* HAVE_VSPRINTF */
|
|
|
|
[self notImplemented: _cmd];
|
1995-04-03 01:35:42 +00:00
|
|
|
return self;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) initWithFormat: (NSString*)format
|
|
|
|
locale: (NSDictionary*)dictionary
|
|
|
|
{
|
|
|
|
[self notImplemented:_cmd];
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) initWithFormat: (NSString*)format
|
|
|
|
locale: (NSDictionary*)dictionary
|
|
|
|
arguments: (va_list)argList
|
|
|
|
{
|
|
|
|
[self notImplemented:_cmd];
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
- (id) initWithData: (NSData*)data
|
|
|
|
encoding: (NSStringEncoding)encoding
|
1995-04-03 01:35:42 +00:00
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
if((encoding==[NSString defaultCStringEncoding])
|
|
|
|
|| (encoding==NSASCIIStringEncoding))
|
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
int count;
|
|
|
|
|
|
|
|
int len=[data length];
|
|
|
|
const char *b=[data bytes];
|
|
|
|
OBJC_MALLOC(s, char, len+1);
|
|
|
|
for(count=0;count<len;count++)
|
|
|
|
s[count]=b[count];
|
|
|
|
s[count]=0;
|
|
|
|
return [self initWithCStringNoCopy:s length:count freeWhenDone:YES];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unichar *u;
|
|
|
|
int count;
|
|
|
|
|
|
|
|
int len=[data length];
|
|
|
|
const unsigned char *b=[data bytes];
|
|
|
|
OBJC_MALLOC(u, unichar, len+1);
|
|
|
|
|
|
|
|
count=len/2;
|
|
|
|
if(encoding==NSUnicodeStringEncoding)
|
|
|
|
if((b[0]==0xFE)&(b[1]==0xFF))
|
|
|
|
for(count=0;count<len;count+=2)
|
|
|
|
u[count/2]=256*b[count]+b[count+1];
|
|
|
|
else
|
|
|
|
for(count=0;count<len;count+=2)
|
|
|
|
u[count/2]=256*b[count+1]+b[count];
|
|
|
|
else
|
|
|
|
count = encode_strtoustr(u,b,len,encoding);
|
|
|
|
|
|
|
|
u[count]=(unichar)0;
|
|
|
|
return [self initWithCharactersNoCopy:u length:count freeWhenDone:YES];
|
|
|
|
}
|
1997-05-03 18:05:21 +00:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) initWithContentsOfFile: (NSString*)path
|
|
|
|
{
|
|
|
|
/* xxx Maybe this should use StdioStream? */
|
1997-09-13 17:52:31 +00:00
|
|
|
#if defined(__WIN32__) || defined(_WIN32)
|
1997-05-03 18:05:21 +00:00
|
|
|
NSMutableString *s = [NSMutableString stringWithCString:""];
|
|
|
|
DWORD dwread;
|
|
|
|
char bytes[1024];
|
|
|
|
BOOL res, done = NO;
|
|
|
|
HANDLE fd = CreateFile([path cString], GENERIC_READ, FILE_SHARE_READ,
|
|
|
|
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
|
1997-09-13 17:52:31 +00:00
|
|
|
if (fd == -1)
|
|
|
|
return nil;
|
1997-05-03 18:05:21 +00:00
|
|
|
|
|
|
|
while (!done)
|
|
|
|
{
|
|
|
|
res = ReadFile(fd, bytes, 1023, &dwread, NULL);
|
|
|
|
bytes[dwread] = '\0';
|
|
|
|
if ((res) && (dwread == 0))
|
|
|
|
done = YES;
|
|
|
|
else
|
|
|
|
[s appendString: [NSString stringWithCString: bytes]];
|
|
|
|
}
|
|
|
|
CloseHandle(fd);
|
|
|
|
[self initWithString: s];
|
|
|
|
[s release];
|
|
|
|
return self;
|
|
|
|
#else
|
|
|
|
int fd = open([path cString], O_RDONLY);
|
|
|
|
struct stat fstat_buf;
|
|
|
|
char* bytes = NULL;
|
|
|
|
|
|
|
|
if((fd == -1) || (fstat(fd, &fstat_buf) == -1))
|
|
|
|
return nil;
|
|
|
|
|
|
|
|
OBJC_MALLOC(bytes, char, fstat_buf.st_size + 1);
|
|
|
|
if (read(fd, bytes, fstat_buf.st_size) != fstat_buf.st_size) {
|
|
|
|
OBJC_FREE(bytes);
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
close(fd);
|
|
|
|
bytes[fstat_buf.st_size] = '\0';
|
|
|
|
return [self initWithCStringNoCopy:bytes length:fstat_buf.st_size
|
|
|
|
freeWhenDone:YES];
|
|
|
|
#endif
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
// xxx check this
|
|
|
|
- (id) init
|
|
|
|
{
|
|
|
|
return [self initWithCString:""];
|
|
|
|
}
|
1995-04-03 01:35:42 +00:00
|
|
|
|
|
|
|
// Getting a String's Length
|
|
|
|
|
|
|
|
- (unsigned int) length
|
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
|
|
|
return 0;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Accessing Characters
|
|
|
|
|
|
|
|
- (unichar) characterAtIndex: (unsigned int)index
|
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
|
|
|
return (unichar)0;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Inefficient. Should be overridden */
|
|
|
|
- (void) getCharacters: (unichar*)buffer
|
|
|
|
{
|
|
|
|
[self getCharacters:buffer range:((NSRange){0,[self length]})];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Inefficient. Should be overridden */
|
|
|
|
- (void) getCharacters: (unichar*)buffer
|
|
|
|
range: (NSRange)aRange
|
|
|
|
{
|
|
|
|
int i;
|
1996-09-02 13:38:19 +00:00
|
|
|
for (i = 0; i < aRange.length; i++)
|
1995-04-03 01:35:42 +00:00
|
|
|
{
|
1996-09-02 13:38:19 +00:00
|
|
|
buffer[i] = [self characterAtIndex: aRange.location+i];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
1997-05-03 18:05:21 +00:00
|
|
|
buffer[aRange.length] = (unichar)0;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Combining Strings
|
|
|
|
|
|
|
|
- (NSString*) stringByAppendingFormat: (NSString*)format,...
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
id ret;
|
|
|
|
va_start(ap, format);
|
|
|
|
ret = [self stringByAppendingString:
|
|
|
|
[NSString stringWithFormat:format arguments:ap]];
|
|
|
|
va_end(ap);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString*) stringByAppendingString: (NSString*)aString
|
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
unsigned len = [self length];
|
|
|
|
unichar *s;
|
1997-10-31 16:26:44 +00:00
|
|
|
NSString *tmp;
|
1997-05-03 18:05:21 +00:00
|
|
|
OBJC_MALLOC(s, unichar, len + [aString length]+1);
|
|
|
|
[self getCharacters:s];
|
|
|
|
[aString getCharacters:s+len];
|
|
|
|
s[len + [aString length]]=(unichar) 0;
|
1997-10-31 16:26:44 +00:00
|
|
|
tmp = [NSString stringWithCharacters:s length: len + [aString length]];
|
|
|
|
OBJC_FREE(s);
|
|
|
|
return tmp;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Dividing Strings into Substrings
|
|
|
|
|
|
|
|
- (NSArray*) componentsSeparatedByString: (NSString*)separator
|
|
|
|
{
|
1997-09-13 17:52:31 +00:00
|
|
|
NSRange search, complete;
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
NSRange found;
|
1996-03-19 01:44:01 +00:00
|
|
|
NSMutableArray *array = [NSMutableArray array];
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
|
1997-03-03 20:07:35 +00:00
|
|
|
search = NSMakeRange (0, [self length]);
|
1997-09-13 17:52:31 +00:00
|
|
|
complete = search;
|
1996-03-19 01:44:01 +00:00
|
|
|
found = [self rangeOfString: separator];
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
while (found.length)
|
|
|
|
{
|
|
|
|
NSRange current;
|
1997-09-13 17:52:31 +00:00
|
|
|
|
1996-03-19 01:44:01 +00:00
|
|
|
current = NSMakeRange (search.location,
|
|
|
|
found.location - search.location);
|
|
|
|
[array addObject: [self substringFromRange: current]];
|
1997-09-13 17:52:31 +00:00
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
search = NSMakeRange (found.location + found.length,
|
1997-09-13 17:52:31 +00:00
|
|
|
complete.length - found.location - found.length);
|
1996-03-19 01:44:01 +00:00
|
|
|
found = [self rangeOfString: separator
|
|
|
|
options: 0
|
|
|
|
range: search];
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
}
|
1997-03-03 20:07:35 +00:00
|
|
|
// Add the last search string range
|
|
|
|
[array addObject: [self substringFromRange: search]];
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
|
|
|
|
// FIXME: Need to make mutable array into non-mutable array?
|
|
|
|
return array;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString*) substringFromIndex: (unsigned int)index
|
|
|
|
{
|
|
|
|
return [self substringFromRange:((NSRange){index, [self length]-index})];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString*) substringFromRange: (NSRange)aRange
|
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
|
|
|
return self;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString*) substringToIndex: (unsigned int)index
|
|
|
|
{
|
1997-05-03 17:26:16 +00:00
|
|
|
return [self substringFromRange:((NSRange){0,index})];;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Finding Ranges of Characters and Substrings
|
|
|
|
|
|
|
|
- (NSRange) rangeOfCharacterFromSet: (NSCharacterSet*)aSet
|
|
|
|
{
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
NSRange all = NSMakeRange(0, [self length]);
|
|
|
|
return [self rangeOfCharacterFromSet:aSet
|
|
|
|
options:0
|
|
|
|
range:all];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRange) rangeOfCharacterFromSet: (NSCharacterSet*)aSet
|
|
|
|
options: (unsigned int)mask
|
|
|
|
{
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
NSRange all = NSMakeRange(0, [self length]);
|
|
|
|
return [self rangeOfCharacterFromSet:aSet
|
|
|
|
options:mask
|
|
|
|
range:all];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
/* xxx FIXME */
|
1995-04-03 01:35:42 +00:00
|
|
|
- (NSRange) rangeOfCharacterFromSet: (NSCharacterSet*)aSet
|
|
|
|
options: (unsigned int)mask
|
|
|
|
range: (NSRange)aRange
|
|
|
|
{
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
int i, start, stop, step;
|
|
|
|
NSRange range;
|
|
|
|
|
|
|
|
/* xxx check to make sure aRange is within self; raise NSStringBoundsError */
|
1997-09-13 17:52:31 +00:00
|
|
|
assert(NSMaxRange(aRange) <= [self length]);
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
|
|
|
|
if ((mask & NSBackwardsSearch) == NSBackwardsSearch)
|
|
|
|
{
|
|
|
|
start = NSMaxRange(aRange); stop = aRange.location; step = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
start = aRange.location; stop = NSMaxRange(aRange); step = 1;
|
|
|
|
}
|
|
|
|
range.length = 0;
|
|
|
|
for (i = start; i < stop; i+=step)
|
|
|
|
{
|
|
|
|
unichar letter = [self characterAtIndex:i];
|
|
|
|
if ([aSet characterIsMember:letter])
|
|
|
|
{
|
|
|
|
range = NSMakeRange(i, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return range;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRange) rangeOfString: (NSString*)string
|
|
|
|
{
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
NSRange all = NSMakeRange(0, [self length]);
|
|
|
|
return [self rangeOfString:string
|
|
|
|
options:0
|
|
|
|
range:all];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRange) rangeOfString: (NSString*)string
|
|
|
|
options: (unsigned int)mask
|
|
|
|
{
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
NSRange all = NSMakeRange(0, [self length]);
|
|
|
|
return [self rangeOfString:string
|
|
|
|
options:mask
|
|
|
|
range:all];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
- (NSRange) _searchForwardCaseInsensitiveLiteral:(NSString *) aString
|
1996-09-02 13:38:19 +00:00
|
|
|
options:(unsigned int) mask
|
|
|
|
range:(NSRange) aRange
|
1995-04-03 01:35:42 +00:00
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
unsigned int myIndex, myEndIndex;
|
1996-09-02 13:38:19 +00:00
|
|
|
unsigned int strLength;
|
|
|
|
unichar strFirstCharacter;
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
strLength = [aString length];
|
|
|
|
|
|
|
|
myIndex = aRange.location;
|
|
|
|
myEndIndex = aRange.location + aRange.length - strLength;
|
|
|
|
|
|
|
|
if (mask & NSAnchoredSearch)
|
|
|
|
myEndIndex = myIndex;
|
|
|
|
|
|
|
|
strFirstCharacter = [aString characterAtIndex:0];
|
|
|
|
|
1997-05-03 20:39:07 +00:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
unsigned int i = 1;
|
|
|
|
unichar myCharacter = [self characterAtIndex:myIndex];
|
|
|
|
unichar strCharacter = strFirstCharacter;
|
1997-05-03 18:05:21 +00:00
|
|
|
|
1997-05-03 20:39:07 +00:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if ((myCharacter != strCharacter) &&
|
|
|
|
((uni_tolower (myCharacter) != uni_tolower (strCharacter))))
|
|
|
|
break;
|
|
|
|
if (i == strLength)
|
|
|
|
return (NSRange){myIndex, strLength};
|
|
|
|
myCharacter = [self characterAtIndex:myIndex + i];
|
|
|
|
strCharacter = [aString characterAtIndex:i];
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if (myIndex == myEndIndex)
|
|
|
|
break;
|
|
|
|
myIndex ++;
|
|
|
|
}
|
1997-05-03 18:05:21 +00:00
|
|
|
return (NSRange){0, 0};
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRange) _searchBackwardCaseInsensitiveLiteral:(NSString *) aString
|
|
|
|
options:(unsigned int) mask
|
|
|
|
range:(NSRange) aRange
|
|
|
|
{
|
|
|
|
unsigned int myIndex, myEndIndex;
|
|
|
|
unsigned int strLength;
|
|
|
|
unichar strFirstCharacter;
|
1996-09-02 13:38:19 +00:00
|
|
|
|
|
|
|
strLength = [aString length];
|
1995-04-03 01:35:42 +00:00
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
myIndex = aRange.location + aRange.length - strLength;
|
|
|
|
myEndIndex = aRange.location;
|
|
|
|
|
|
|
|
|
1996-09-02 13:38:19 +00:00
|
|
|
if (mask & NSAnchoredSearch)
|
|
|
|
myEndIndex = myIndex;
|
|
|
|
|
|
|
|
strFirstCharacter = [aString characterAtIndex:0];
|
1997-05-03 18:05:21 +00:00
|
|
|
|
1996-09-02 13:38:19 +00:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
unsigned int i = 1;
|
|
|
|
unichar myCharacter = [self characterAtIndex:myIndex];
|
|
|
|
unichar strCharacter = strFirstCharacter;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if ((myCharacter != strCharacter) &&
|
1997-05-03 18:05:21 +00:00
|
|
|
((uni_tolower (myCharacter) != uni_tolower (strCharacter))))
|
1996-09-02 13:38:19 +00:00
|
|
|
break;
|
|
|
|
if (i == strLength)
|
|
|
|
return (NSRange){myIndex, strLength};
|
|
|
|
myCharacter = [self characterAtIndex:myIndex + i];
|
|
|
|
strCharacter = [aString characterAtIndex:i];
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if (myIndex == myEndIndex)
|
|
|
|
break;
|
1997-05-03 18:05:21 +00:00
|
|
|
myIndex --;
|
1996-09-02 13:38:19 +00:00
|
|
|
}
|
1997-05-03 18:05:21 +00:00
|
|
|
return (NSRange){0, 0};
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRange) _searchForwardLiteral:(NSString *) aString
|
|
|
|
options:(unsigned int) mask
|
|
|
|
range:(NSRange) aRange
|
|
|
|
{
|
|
|
|
unsigned int myIndex, myEndIndex;
|
|
|
|
unsigned int strLength;
|
|
|
|
unichar strFirstCharacter;
|
|
|
|
|
|
|
|
strLength = [aString length];
|
|
|
|
|
|
|
|
myIndex = aRange.location;
|
|
|
|
myEndIndex = aRange.location + aRange.length - strLength;
|
|
|
|
|
|
|
|
if (mask & NSAnchoredSearch)
|
|
|
|
myEndIndex = myIndex;
|
|
|
|
|
|
|
|
strFirstCharacter = [aString characterAtIndex:0];
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
unsigned int i = 1;
|
|
|
|
unichar myCharacter = [self characterAtIndex:myIndex];
|
|
|
|
unichar strCharacter = strFirstCharacter;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (myCharacter != strCharacter)
|
|
|
|
break;
|
|
|
|
if (i == strLength)
|
|
|
|
return (NSRange){myIndex, strLength};
|
|
|
|
myCharacter = [self characterAtIndex:myIndex + i];
|
|
|
|
strCharacter = [aString characterAtIndex:i];
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if (myIndex == myEndIndex)
|
|
|
|
break;
|
|
|
|
myIndex ++;
|
|
|
|
}
|
|
|
|
return (NSRange){0, 0};
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRange) _searchBackwardLiteral:(NSString *) aString
|
|
|
|
options:(unsigned int) mask
|
|
|
|
range:(NSRange) aRange
|
|
|
|
{
|
|
|
|
unsigned int myIndex, myEndIndex;
|
|
|
|
unsigned int strLength;
|
|
|
|
unichar strFirstCharacter;
|
|
|
|
|
|
|
|
strLength = [aString length];
|
|
|
|
|
|
|
|
myIndex = aRange.location + aRange.length - strLength;
|
|
|
|
myEndIndex = aRange.location;
|
|
|
|
|
|
|
|
|
|
|
|
if (mask & NSAnchoredSearch)
|
|
|
|
myEndIndex = myIndex;
|
|
|
|
|
|
|
|
strFirstCharacter = [aString characterAtIndex:0];
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
unsigned int i = 1;
|
|
|
|
unichar myCharacter = [self characterAtIndex:myIndex];
|
|
|
|
unichar strCharacter = strFirstCharacter;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (myCharacter != strCharacter)
|
|
|
|
break;
|
|
|
|
if (i == strLength)
|
|
|
|
return (NSRange){myIndex, strLength};
|
|
|
|
myCharacter = [self characterAtIndex:myIndex + i];
|
|
|
|
strCharacter = [aString characterAtIndex:i];
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if (myIndex == myEndIndex)
|
|
|
|
break;
|
|
|
|
myIndex --;
|
|
|
|
}
|
|
|
|
return (NSRange){0, 0};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (NSRange) _searchForwardCaseInsensitive:(NSString *) aString
|
|
|
|
options:(unsigned int) mask
|
|
|
|
range:(NSRange) aRange
|
|
|
|
{
|
|
|
|
unsigned int myIndex, myEndIndex;
|
|
|
|
unsigned int strLength, strBaseLength;
|
|
|
|
id strFirstCharacterSeq;
|
|
|
|
|
|
|
|
strLength = [aString length];
|
|
|
|
strBaseLength = [aString _baseLength];
|
|
|
|
|
|
|
|
myIndex = aRange.location;
|
|
|
|
myEndIndex = aRange.location + aRange.length - strBaseLength;
|
|
|
|
|
|
|
|
if (mask & NSAnchoredSearch)
|
|
|
|
myEndIndex = myIndex;
|
|
|
|
|
|
|
|
strFirstCharacterSeq = [NSGSequence sequenceWithString: aString
|
|
|
|
range: [aString rangeOfComposedCharacterSequenceAtIndex: 0]];
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
NSRange myRange;
|
|
|
|
NSRange mainRange;
|
|
|
|
NSRange strRange;
|
|
|
|
unsigned int myCount = 1;
|
|
|
|
unsigned int strCount = 1;
|
|
|
|
id myCharacter = [NSGSequence sequenceWithString: self
|
|
|
|
range: [self rangeOfComposedCharacterSequenceAtIndex: myIndex]];
|
|
|
|
id strCharacter = strFirstCharacterSeq;
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (![[myCharacter normalize] isEqual: [strCharacter normalize]]
|
|
|
|
&& ![[[myCharacter lowercase] normalize] isEqual: [[strCharacter lowercase] normalize]])
|
|
|
|
|
|
|
|
break;
|
|
|
|
if (strCount >= strLength)
|
|
|
|
return (NSRange){myIndex, myCount};
|
|
|
|
myRange = [self rangeOfComposedCharacterSequenceAtIndex: myIndex + myCount];
|
|
|
|
myCharacter = [NSGSequence sequenceWithString: self range: myRange];
|
|
|
|
strRange = [aString rangeOfComposedCharacterSequenceAtIndex: strCount];
|
|
|
|
strCharacter = [NSGSequence sequenceWithString: aString range: strRange];
|
|
|
|
myCount += myRange.length;
|
|
|
|
strCount += strRange.length;
|
|
|
|
} /* for */
|
|
|
|
if (myIndex >= myEndIndex)
|
|
|
|
break;
|
|
|
|
mainRange = [self rangeOfComposedCharacterSequenceAtIndex: myIndex];
|
|
|
|
myIndex += mainRange.length;
|
|
|
|
} /* for */
|
|
|
|
return (NSRange){0, 0};
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRange) _searchBackwardCaseInsensitive:(NSString *) aString
|
|
|
|
options:(unsigned int) mask
|
|
|
|
range:(NSRange) aRange
|
|
|
|
{
|
|
|
|
unsigned int myIndex, myEndIndex;
|
|
|
|
unsigned int strLength, strBaseLength;
|
|
|
|
id strFirstCharacterSeq;
|
|
|
|
|
|
|
|
strLength = [aString length];
|
|
|
|
strBaseLength = [aString _baseLength];
|
|
|
|
|
|
|
|
myIndex = aRange.location + aRange.length - strBaseLength;
|
|
|
|
myEndIndex = aRange.location;
|
|
|
|
|
|
|
|
if (mask & NSAnchoredSearch)
|
|
|
|
myEndIndex = myIndex;
|
|
|
|
|
|
|
|
strFirstCharacterSeq = [NSGSequence sequenceWithString: aString
|
|
|
|
range: [aString rangeOfComposedCharacterSequenceAtIndex: 0]];
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
NSRange myRange;
|
|
|
|
NSRange strRange;
|
|
|
|
unsigned int myCount = 1;
|
|
|
|
unsigned int strCount = 1;
|
|
|
|
id myCharacter = [NSGSequence sequenceWithString: self
|
|
|
|
range: [self rangeOfComposedCharacterSequenceAtIndex: myIndex]];
|
|
|
|
id strCharacter = strFirstCharacterSeq;
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (![[myCharacter normalize] isEqual: [strCharacter normalize]]
|
|
|
|
&& ![[[myCharacter lowercase] normalize] isEqual: [[strCharacter lowercase] normalize]])
|
|
|
|
|
|
|
|
break;
|
|
|
|
if (strCount >= strLength)
|
|
|
|
return (NSRange){myIndex, myCount};
|
|
|
|
myCharacter = [NSGSequence sequenceWithString: self range: [self rangeOfComposedCharacterSequenceAtIndex: myIndex + myCount]];
|
|
|
|
myRange = [self rangeOfComposedCharacterSequenceAtIndex: myIndex + myCount];
|
|
|
|
strCharacter = [NSGSequence sequenceWithString: aString range: [aString rangeOfComposedCharacterSequenceAtIndex: strCount]];
|
|
|
|
strRange = [aString rangeOfComposedCharacterSequenceAtIndex: strCount];
|
|
|
|
myCount += myRange.length;
|
|
|
|
strCount += strRange.length;
|
|
|
|
} /* for */
|
|
|
|
if (myIndex <= myEndIndex)
|
|
|
|
break;
|
|
|
|
myIndex--;
|
|
|
|
while(uni_isnonsp([self characterAtIndex: myIndex])&&(myIndex>0))
|
|
|
|
myIndex--;
|
|
|
|
} /* for */
|
|
|
|
return (NSRange){0, 0};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (NSRange) _searchForward:(NSString *) aString
|
|
|
|
options:(unsigned int) mask
|
|
|
|
range:(NSRange) aRange
|
|
|
|
{
|
|
|
|
unsigned int myIndex, myEndIndex;
|
|
|
|
unsigned int strLength, strBaseLength;
|
|
|
|
id strFirstCharacterSeq;
|
|
|
|
|
|
|
|
strLength = [aString length];
|
|
|
|
strBaseLength = [aString _baseLength];
|
|
|
|
|
|
|
|
myIndex = aRange.location;
|
|
|
|
myEndIndex = aRange.location + aRange.length - strBaseLength;
|
|
|
|
|
|
|
|
if (mask & NSAnchoredSearch)
|
|
|
|
myEndIndex = myIndex;
|
|
|
|
|
|
|
|
strFirstCharacterSeq = [NSGSequence sequenceWithString: aString
|
|
|
|
range: [aString rangeOfComposedCharacterSequenceAtIndex: 0]];
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
NSRange myRange;
|
|
|
|
NSRange strRange;
|
|
|
|
NSRange mainRange;
|
|
|
|
unsigned int myCount = 1;
|
|
|
|
unsigned int strCount = 1;
|
|
|
|
id myCharacter = [NSGSequence sequenceWithString: self
|
|
|
|
range: [self rangeOfComposedCharacterSequenceAtIndex: myIndex]];
|
|
|
|
id strCharacter = strFirstCharacterSeq;
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (![[myCharacter normalize] isEqual: [strCharacter normalize]])
|
|
|
|
break;
|
|
|
|
if (strCount >= strLength)
|
|
|
|
return (NSRange){myIndex, myCount};
|
|
|
|
myRange = [self rangeOfComposedCharacterSequenceAtIndex: myIndex + myCount];
|
|
|
|
myCharacter = [NSGSequence sequenceWithString: self range: myRange];
|
|
|
|
strRange = [aString rangeOfComposedCharacterSequenceAtIndex: strCount];
|
|
|
|
strCharacter = [NSGSequence sequenceWithString: aString range: strRange];
|
|
|
|
myCount += myRange.length;
|
|
|
|
strCount += strRange.length;
|
|
|
|
} /* for */
|
|
|
|
if (myIndex >= myEndIndex)
|
|
|
|
break;
|
|
|
|
mainRange = [self rangeOfComposedCharacterSequenceAtIndex: myIndex];
|
|
|
|
myIndex += mainRange.length;
|
|
|
|
} /* for */
|
|
|
|
return (NSRange){0, 0};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (NSRange) _searchBackward:(NSString *) aString
|
|
|
|
options:(unsigned int) mask
|
|
|
|
range:(NSRange) aRange
|
|
|
|
{
|
|
|
|
unsigned int myIndex, myEndIndex;
|
|
|
|
unsigned int strLength, strBaseLength;
|
|
|
|
id strFirstCharacterSeq;
|
|
|
|
|
|
|
|
strLength = [aString length];
|
|
|
|
strBaseLength = [aString _baseLength];
|
|
|
|
|
|
|
|
myIndex = aRange.location + aRange.length - strBaseLength;
|
|
|
|
myEndIndex = aRange.location;
|
|
|
|
|
|
|
|
if (mask & NSAnchoredSearch)
|
|
|
|
myEndIndex = myIndex;
|
|
|
|
|
|
|
|
strFirstCharacterSeq = [NSGSequence sequenceWithString: aString
|
|
|
|
range: [aString rangeOfComposedCharacterSequenceAtIndex: 0]];
|
|
|
|
|
1996-09-02 13:38:19 +00:00
|
|
|
for (;;)
|
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
NSRange myRange;
|
|
|
|
NSRange strRange;
|
|
|
|
unsigned int myCount = 1;
|
|
|
|
unsigned int strCount = 1;
|
|
|
|
id myCharacter = [NSGSequence sequenceWithString: self
|
|
|
|
range: [self rangeOfComposedCharacterSequenceAtIndex: myIndex]];
|
|
|
|
id strCharacter = strFirstCharacterSeq;
|
1996-09-02 13:38:19 +00:00
|
|
|
for (;;)
|
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
if (![[myCharacter normalize] isEqual: [strCharacter normalize]])
|
|
|
|
|
1996-09-02 13:38:19 +00:00
|
|
|
break;
|
1997-05-03 18:05:21 +00:00
|
|
|
if (strCount >= strLength)
|
|
|
|
return (NSRange){myIndex, myCount};
|
|
|
|
myCharacter = [NSGSequence sequenceWithString: self range: [self rangeOfComposedCharacterSequenceAtIndex: myIndex + myCount]];
|
|
|
|
myRange = [self rangeOfComposedCharacterSequenceAtIndex: myIndex + myCount];
|
|
|
|
strCharacter = [NSGSequence sequenceWithString: aString range: [aString rangeOfComposedCharacterSequenceAtIndex: strCount]];
|
|
|
|
strRange = [aString rangeOfComposedCharacterSequenceAtIndex: strCount];
|
|
|
|
myCount += myRange.length;
|
|
|
|
strCount += strRange.length;
|
|
|
|
} /* for */
|
|
|
|
if (myIndex <= myEndIndex)
|
1996-09-02 13:38:19 +00:00
|
|
|
break;
|
1997-05-03 18:05:21 +00:00
|
|
|
myIndex--;
|
|
|
|
while(uni_isnonsp([self characterAtIndex: myIndex])&&(myIndex>0))
|
|
|
|
myIndex--;
|
|
|
|
} /* for */
|
|
|
|
return (NSRange){0, 0};
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRange) rangeOfString:(NSString *) aString
|
|
|
|
options:(unsigned int) mask
|
|
|
|
range:(NSRange) aRange
|
|
|
|
{
|
|
|
|
|
|
|
|
#define FCLS 3
|
|
|
|
#define BCLS 7
|
|
|
|
#define FLS 2
|
|
|
|
#define BLS 6
|
|
|
|
#define FCS 1
|
|
|
|
#define BCS 5
|
|
|
|
#define FS 0
|
|
|
|
#define BS 4
|
|
|
|
#define FCLAS 11
|
|
|
|
#define BCLAS 15
|
|
|
|
#define FLAS 10
|
|
|
|
#define BLAS 14
|
|
|
|
#define FCAS 9
|
|
|
|
#define BCAS 13
|
|
|
|
#define FAS 8
|
|
|
|
#define BAS 12
|
|
|
|
|
|
|
|
unsigned int myLength, strLength;
|
|
|
|
|
|
|
|
/* Check that the search range is reasonable */
|
|
|
|
myLength = [self length];
|
|
|
|
if (aRange.location > myLength)
|
|
|
|
[NSException raise: NSRangeException format:@"Invalid location."];
|
|
|
|
if (aRange.length > (myLength - aRange.location))
|
|
|
|
[NSException raise: NSRangeException format:@"Invalid location+length."];
|
|
|
|
|
|
|
|
|
|
|
|
/* Ensure the string can be found */
|
|
|
|
strLength = [aString length];
|
1997-09-01 21:59:51 +00:00
|
|
|
if (strLength > aRange.length || strLength == 0)
|
1997-05-03 18:05:21 +00:00
|
|
|
return (NSRange){0, 0};
|
|
|
|
|
|
|
|
switch (mask)
|
|
|
|
{
|
|
|
|
case FCLS :
|
|
|
|
case FCLAS :
|
|
|
|
return [self _searchForwardCaseInsensitiveLiteral: aString
|
|
|
|
options: mask
|
|
|
|
range: aRange];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BCLS :
|
|
|
|
case BCLAS :
|
|
|
|
return [self _searchBackwardCaseInsensitiveLiteral: aString
|
|
|
|
options: mask
|
|
|
|
range: aRange];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FLS :
|
|
|
|
case FLAS :
|
|
|
|
return [self _searchForwardLiteral: aString
|
|
|
|
options: mask
|
|
|
|
range: aRange];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BLS :
|
|
|
|
case BLAS :
|
|
|
|
return [self _searchBackwardLiteral: aString
|
|
|
|
options: mask
|
|
|
|
range: aRange];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FCS :
|
|
|
|
case FCAS :
|
|
|
|
return [self _searchForwardCaseInsensitive: aString
|
|
|
|
options: mask
|
|
|
|
range: aRange];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BCS :
|
|
|
|
case BCAS :
|
|
|
|
return [self _searchBackwardCaseInsensitive: aString
|
|
|
|
options: mask
|
|
|
|
range: aRange];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BS :
|
|
|
|
case BAS :
|
|
|
|
return [self _searchBackward: aString
|
|
|
|
options: mask
|
|
|
|
range: aRange];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FS :
|
|
|
|
case FAS :
|
|
|
|
default :
|
|
|
|
return [self _searchForward: aString
|
|
|
|
options: mask
|
|
|
|
range: aRange];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return (NSRange){0, 0};
|
1996-09-02 13:38:19 +00:00
|
|
|
}
|
1995-04-03 01:35:42 +00:00
|
|
|
|
|
|
|
// Determining Composed Character Sequences
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
- (NSRange) rangeOfComposedCharacterSequenceAtIndex: (unsigned int)anIndex
|
1995-04-03 01:35:42 +00:00
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
unsigned int start, end;
|
|
|
|
|
|
|
|
start=anIndex;
|
|
|
|
while(uni_isnonsp([self characterAtIndex: start]))
|
|
|
|
start++;
|
|
|
|
end=start+1;
|
|
|
|
if(end < [self length])
|
1997-09-01 21:59:51 +00:00
|
|
|
while((end < [self length]) && (uni_isnonsp([self characterAtIndex: end])) )
|
1997-05-03 18:05:21 +00:00
|
|
|
end++;
|
|
|
|
return NSMakeRange(start, end-start);
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
// Converting String Contents into a Property List
|
1995-04-03 01:35:42 +00:00
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
// xxx C strings only ???
|
|
|
|
- (id)propertyList
|
|
|
|
{
|
|
|
|
id obj;
|
|
|
|
void *bufstate;
|
|
|
|
bufstate = (void *)pl_scan_string([self cString]);
|
|
|
|
obj = (id)plparse();
|
|
|
|
pl_delete_buffer(bufstate);
|
|
|
|
return obj;
|
|
|
|
}
|
1995-04-03 01:35:42 +00:00
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
// xxx C strings only ???
|
|
|
|
- (NSDictionary*) propertyListFromStringsFileFormat
|
1995-04-03 01:35:42 +00:00
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
id dict = [[[NSMutableDictionary alloc] init] autorelease];
|
|
|
|
void *bufstate;
|
|
|
|
|
|
|
|
bufstate = (void *)sf_scan_string([self cString]);
|
|
|
|
sfSetDict(dict);
|
|
|
|
sfparse(dict);
|
|
|
|
sf_delete_buffer(bufstate);
|
|
|
|
return dict;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
// Identifying and Comparing Strings
|
|
|
|
|
1995-04-03 01:35:42 +00:00
|
|
|
- (NSComparisonResult) compare: (NSString*)aString
|
|
|
|
{
|
|
|
|
return [self compare:aString options:0];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSComparisonResult) compare: (NSString*)aString
|
|
|
|
options: (unsigned int)mask
|
|
|
|
{
|
|
|
|
return [self compare:aString options:mask
|
1995-10-18 16:47:59 +00:00
|
|
|
range:((NSRange){0, MAX([self length], [aString length])})];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
// xxx Should implement full POSIX.2 collate
|
1995-04-03 01:35:42 +00:00
|
|
|
- (NSComparisonResult) compare: (NSString*)aString
|
|
|
|
options: (unsigned int)mask
|
|
|
|
range: (NSRange)aRange
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
|
|
if(((![self length]) && (![aString length])))
|
|
|
|
return NSOrderedSame;
|
|
|
|
if(![self length])
|
|
|
|
return NSOrderedAscending;
|
|
|
|
if(![aString length])
|
|
|
|
return NSOrderedDescending;
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
if (mask & NSLiteralSearch)
|
|
|
|
{
|
1995-05-05 18:29:12 +00:00
|
|
|
int i, start, end, increment;
|
1997-05-03 18:05:21 +00:00
|
|
|
unichar *s1;
|
|
|
|
unichar *s2;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
OBJC_MALLOC(s1, unichar,[self length] +1);
|
|
|
|
OBJC_MALLOC(s2, unichar,[aString length] +1);
|
|
|
|
[self getCharacters:s1];
|
|
|
|
[aString getCharacters:s2];
|
1995-05-05 18:29:12 +00:00
|
|
|
|
|
|
|
start = aRange.location;
|
|
|
|
end = aRange.location + aRange.length;
|
|
|
|
increment = 1;
|
|
|
|
|
|
|
|
if (mask & NSCaseInsensitiveSearch)
|
|
|
|
{
|
|
|
|
for (i = start; i < end; i += increment)
|
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
int c1 = uni_tolower(s1[i]);
|
|
|
|
int c2 = uni_tolower(s2[i]);
|
1995-05-05 18:29:12 +00:00
|
|
|
if (c1 < c2) return NSOrderedAscending;
|
|
|
|
if (c1 > c2) return NSOrderedDescending;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = start; i < end; i += increment)
|
|
|
|
{
|
|
|
|
if (s1[i] < s2[i]) return NSOrderedAscending;
|
|
|
|
if (s1[i] > s2[i]) return NSOrderedDescending;
|
|
|
|
}
|
|
|
|
}
|
1997-09-01 21:59:51 +00:00
|
|
|
OBJC_FREE(s1);
|
|
|
|
OBJC_FREE(s2);
|
1995-05-05 18:29:12 +00:00
|
|
|
return NSOrderedSame;
|
1997-05-03 18:05:21 +00:00
|
|
|
} /* if NSLiteralSearch */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int start, end, myCount, strCount;
|
|
|
|
NSRange myRange, strRange;
|
|
|
|
id mySeq, strSeq;
|
|
|
|
NSComparisonResult result;
|
|
|
|
|
|
|
|
start = aRange.location;
|
|
|
|
end = aRange.location + aRange.length;
|
|
|
|
myCount = start;
|
|
|
|
strCount = start;
|
|
|
|
while(myCount < end)
|
|
|
|
{
|
|
|
|
if(strCount>=[aString length])
|
|
|
|
return NSOrderedAscending;
|
1997-09-01 21:59:51 +00:00
|
|
|
if(myCount>=[self length])
|
|
|
|
return NSOrderedDescending;
|
1997-05-03 18:05:21 +00:00
|
|
|
myRange = [self rangeOfComposedCharacterSequenceAtIndex: myCount];
|
|
|
|
myCount += myRange.length;
|
|
|
|
strRange = [aString rangeOfComposedCharacterSequenceAtIndex: strCount];
|
|
|
|
strCount += strRange.length;
|
|
|
|
mySeq = [NSGSequence sequenceWithString: self range: myRange];
|
|
|
|
strSeq = [NSGSequence sequenceWithString: aString range: strRange];
|
|
|
|
if (mask & NSCaseInsensitiveSearch)
|
|
|
|
result = [[mySeq lowercase] compare: [strSeq lowercase]];
|
|
|
|
else
|
|
|
|
result = [mySeq compare: strSeq];
|
|
|
|
if(result != NSOrderedSame)
|
|
|
|
return result;
|
|
|
|
} /* while */
|
|
|
|
return NSOrderedSame;
|
|
|
|
} /* else */
|
|
|
|
return NSOrderedSame;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) hasPrefix: (NSString*)aString
|
|
|
|
{
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
NSRange range;
|
|
|
|
range = [self rangeOfString:aString];
|
1997-01-06 22:36:21 +00:00
|
|
|
return ((range.location == 0) && (range.length != 0)) ? YES : NO;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) hasSuffix: (NSString*)aString
|
|
|
|
{
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
NSRange range;
|
|
|
|
range = [self rangeOfString:aString options:NSBackwardsSearch];
|
|
|
|
return (range.location == ([self length] - [aString length])) ? YES : NO;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
- (BOOL) isEqual: (id)anObject
|
|
|
|
{
|
|
|
|
if ([anObject isKindOf:[NSString class]])
|
|
|
|
return [self isEqualToString:anObject];
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) isEqualToString: (NSString*)aString
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
id mySeq, strSeq;
|
|
|
|
NSRange myRange, strRange;
|
|
|
|
unsigned int myLength = [self length];
|
|
|
|
unsigned int strLength = [aString length];
|
|
|
|
unsigned int myIndex = 0;
|
|
|
|
unsigned int strIndex = 0;
|
|
|
|
|
|
|
|
if((!myLength) && (!strLength))
|
|
|
|
return YES;
|
|
|
|
if(!myLength)
|
|
|
|
return NO;
|
|
|
|
if(!strLength)
|
|
|
|
return NO;
|
|
|
|
|
|
|
|
while((myIndex < myLength) && (strIndex < strLength))
|
|
|
|
if([self characterAtIndex: myIndex] ==
|
|
|
|
[aString characterAtIndex: strIndex])
|
|
|
|
{
|
|
|
|
myIndex++;
|
|
|
|
strIndex++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
myRange = [self rangeOfComposedCharacterSequenceAtIndex: myIndex];
|
|
|
|
strRange = [aString rangeOfComposedCharacterSequenceAtIndex: strIndex];
|
|
|
|
if((myRange.length < 2) || (strRange.length < 2))
|
|
|
|
return NO;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mySeq = [NSGSequence sequenceWithString: self range: myRange];
|
|
|
|
strSeq = [NSGSequence sequenceWithString: aString range: strRange];
|
|
|
|
if([mySeq isEqual: strSeq])
|
|
|
|
{
|
|
|
|
myIndex += myRange.length;
|
|
|
|
strIndex += strRange.length;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if((myIndex == myLength) && (strIndex == strLength))
|
|
|
|
return YES;
|
|
|
|
else
|
|
|
|
return NO;
|
|
|
|
return YES;
|
1997-05-03 18:05:21 +00:00
|
|
|
}
|
|
|
|
|
1995-04-03 01:35:42 +00:00
|
|
|
- (unsigned int) hash
|
1997-09-01 21:59:51 +00:00
|
|
|
#if 1
|
|
|
|
// xxx C string implementation
|
1995-04-03 01:35:42 +00:00
|
|
|
{
|
1996-02-22 21:50:35 +00:00
|
|
|
unsigned ret = 0;
|
|
|
|
unsigned ctr = 0;
|
|
|
|
unsigned char_count = 0;
|
1996-11-24 21:04:24 +00:00
|
|
|
const char *s = [self cStringNoCopy];
|
1996-02-22 21:50:35 +00:00
|
|
|
|
|
|
|
while (*s && char_count++ < NSHashStringLength)
|
|
|
|
{
|
|
|
|
ret ^= *s++ << ctr;
|
|
|
|
ctr = (ctr + 1) % sizeof (void*);
|
|
|
|
}
|
|
|
|
return ret;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
1997-09-01 21:59:51 +00:00
|
|
|
#else
|
|
|
|
// xxx Unicode string implementation - check !!!
|
|
|
|
|
|
|
|
{
|
|
|
|
unsigned ret = 0;
|
|
|
|
unsigned ctr = 0;
|
|
|
|
unsigned char_count = 0;
|
|
|
|
unichar *s,*p;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
id g = [self _normalizedString];
|
|
|
|
len = [g length];
|
|
|
|
OBJC_MALLOC(s, unichar, len + 1);
|
|
|
|
[g getCharacters: s];
|
|
|
|
p = s;
|
|
|
|
while (*p && char_count++ < NSHashStringLength)
|
|
|
|
{
|
|
|
|
ret ^= *p++ << ctr;
|
|
|
|
ctr = (ctr + 1) % sizeof (void*);
|
|
|
|
}
|
|
|
|
OBJC_FREE(s);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
1995-04-03 01:35:42 +00:00
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
// Getting a Shared Prefix
|
|
|
|
|
|
|
|
- (NSString*) commonPrefixWithString: (NSString*)aString
|
|
|
|
options: (unsigned int)mask
|
1995-04-03 01:35:42 +00:00
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
if(mask & NSLiteralSearch)
|
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
int prefix_len = 0;
|
|
|
|
unichar *s1;
|
|
|
|
unichar *s2;
|
1997-09-01 21:59:51 +00:00
|
|
|
unichar *u,*w;
|
1997-05-03 18:05:21 +00:00
|
|
|
OBJC_MALLOC(s1, unichar,[self length] +1);
|
|
|
|
OBJC_MALLOC(s2, unichar,[aString length] +1);
|
|
|
|
u=s1;
|
|
|
|
[self getCharacters:s1];
|
1997-09-01 21:59:51 +00:00
|
|
|
s1[[self length]] = (unichar)0;
|
1997-05-03 18:05:21 +00:00
|
|
|
[aString getCharacters:s2];
|
1997-09-01 21:59:51 +00:00
|
|
|
s2[[aString length]] = (unichar)0;
|
|
|
|
u=s1;
|
|
|
|
w=s2;
|
|
|
|
if(mask & NSCaseInsensitiveSearch)
|
1997-05-03 18:05:21 +00:00
|
|
|
while (*s1 && *s2
|
1997-09-01 21:59:51 +00:00
|
|
|
&& (uni_tolower(*s1) == uni_tolower(*s2)))
|
1997-05-03 18:05:21 +00:00
|
|
|
{
|
|
|
|
s1++;
|
|
|
|
s2++;
|
|
|
|
prefix_len++;
|
|
|
|
}
|
1997-09-01 21:59:51 +00:00
|
|
|
else
|
|
|
|
while (*s1 && *s2
|
|
|
|
&& (*s1 == *s2))
|
|
|
|
{
|
|
|
|
s1++;
|
|
|
|
s2++;
|
|
|
|
prefix_len++;
|
|
|
|
}
|
|
|
|
OBJC_FREE(w);
|
|
|
|
return [NSString stringWithCharacters: u length: prefix_len];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
id mySeq, strSeq;
|
|
|
|
NSRange myRange, strRange;
|
|
|
|
unsigned int myLength = [self length];
|
|
|
|
unsigned int strLength = [aString length];
|
|
|
|
unsigned int myIndex = 0;
|
|
|
|
unsigned int strIndex = 0;
|
|
|
|
if(!myLength)
|
|
|
|
return self;
|
|
|
|
if(!strLength)
|
|
|
|
return aString;
|
|
|
|
if(mask & NSCaseInsensitiveSearch)
|
|
|
|
{
|
|
|
|
while((myIndex < myLength) && (strIndex < strLength))
|
|
|
|
if(uni_tolower([self characterAtIndex: myIndex]) ==
|
|
|
|
uni_tolower([aString characterAtIndex: strIndex]))
|
|
|
|
{
|
|
|
|
myIndex++;
|
|
|
|
strIndex++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
myRange = [self rangeOfComposedCharacterSequenceAtIndex: myIndex];
|
|
|
|
strRange = [aString rangeOfComposedCharacterSequenceAtIndex: strIndex];
|
|
|
|
if((myRange.length < 2) || (strRange.length < 2))
|
|
|
|
return [self substringFromRange: NSMakeRange(0, myIndex)];
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mySeq = [NSGSequence sequenceWithString: self range: myRange];
|
|
|
|
strSeq = [NSGSequence sequenceWithString: aString range: strRange];
|
|
|
|
if([[mySeq lowercase] isEqual: [strSeq lowercase]])
|
|
|
|
{
|
|
|
|
myIndex += myRange.length;
|
|
|
|
strIndex += strRange.length;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return [self substringFromRange: NSMakeRange(0, myIndex)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return [self substringFromRange: NSMakeRange(0, myIndex)];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while((myIndex < myLength) && (strIndex < strLength))
|
|
|
|
if([self characterAtIndex: myIndex] ==
|
|
|
|
[aString characterAtIndex: strIndex])
|
|
|
|
{
|
|
|
|
myIndex++;
|
|
|
|
strIndex++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
myRange = [self rangeOfComposedCharacterSequenceAtIndex: myIndex];
|
|
|
|
strRange = [aString rangeOfComposedCharacterSequenceAtIndex: strIndex];
|
|
|
|
if((myRange.length < 2) || (strRange.length < 2))
|
|
|
|
return [self substringFromRange: NSMakeRange(0, myIndex)];
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mySeq = [NSGSequence sequenceWithString: self range: myRange];
|
|
|
|
strSeq = [NSGSequence sequenceWithString: aString range: strRange];
|
|
|
|
if([mySeq isEqual: strSeq])
|
|
|
|
{
|
|
|
|
myIndex += myRange.length;
|
|
|
|
strIndex += strRange.length;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return [self substringFromRange: NSMakeRange(0, myIndex)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return [self substringFromRange: NSMakeRange(0, myIndex)];
|
|
|
|
}
|
|
|
|
}
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
// Changing Case
|
|
|
|
|
|
|
|
// xxx There is more than this in word capitalization in Unicode,
|
|
|
|
// but this will work in most cases
|
|
|
|
// xxx fix me - consider tab, newline and friends
|
|
|
|
- (NSString*) capitalizedString
|
|
|
|
{
|
|
|
|
unichar *s;
|
|
|
|
int count=0;
|
|
|
|
int len=[self length];
|
|
|
|
OBJC_MALLOC(s, unichar,len +1);
|
|
|
|
s[0]=uni_toupper([self characterAtIndex:0]);
|
|
|
|
while(count<len)
|
|
|
|
{
|
|
|
|
while((!([self characterAtIndex: count++]==' '))&(count<len))
|
|
|
|
s[count]=uni_tolower([self characterAtIndex:count]);
|
|
|
|
if(count<len)
|
|
|
|
s[count]=uni_toupper([self characterAtIndex:count]);
|
|
|
|
}
|
|
|
|
s[len] = (unichar)0;
|
1997-09-01 21:59:51 +00:00
|
|
|
return [NSString stringWithCharacters:s length:len];
|
1997-05-03 18:05:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString*) lowercaseString
|
|
|
|
{
|
|
|
|
unichar *s;
|
|
|
|
int count;
|
|
|
|
int len=[self length];
|
|
|
|
OBJC_MALLOC(s, unichar,len +1);
|
|
|
|
for(count=0;count<len;count++)
|
|
|
|
s[count]=uni_tolower([self characterAtIndex:count]);
|
|
|
|
s[len] = (unichar)0;
|
1997-09-01 21:59:51 +00:00
|
|
|
return [NSString stringWithCharacters:s length:len];
|
1997-05-03 18:05:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString*) uppercaseString;
|
1995-04-03 01:35:42 +00:00
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
unichar *s;
|
|
|
|
int count;
|
|
|
|
int len=[self length];
|
|
|
|
OBJC_MALLOC(s, unichar,len +1);
|
|
|
|
for(count=0;count<len;count++)
|
|
|
|
s[count]=uni_toupper([self characterAtIndex:count]);
|
|
|
|
s[len] = (unichar)0;
|
1997-09-01 21:59:51 +00:00
|
|
|
return [NSString stringWithCharacters:s length:len];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Storing the String
|
|
|
|
|
|
|
|
- (NSString*) description
|
|
|
|
{
|
1997-03-03 20:07:35 +00:00
|
|
|
return self;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Getting C Strings
|
|
|
|
|
|
|
|
- (const char*) cString
|
|
|
|
{
|
1995-10-26 01:29:04 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-03 01:35:42 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (unsigned int) cStringLength
|
|
|
|
{
|
1995-10-26 01:29:04 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-03 01:35:42 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) getCString: (char*)buffer
|
|
|
|
{
|
|
|
|
[self getCString:buffer maxLength:NSMaximumStringLength
|
|
|
|
range:((NSRange){0, [self length]})
|
|
|
|
remainingRange:NULL];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) getCString: (char*)buffer
|
|
|
|
maxLength: (unsigned int)maxLength
|
|
|
|
{
|
|
|
|
[self getCString:buffer maxLength:maxLength
|
|
|
|
range:((NSRange){0, [self length]})
|
|
|
|
remainingRange:NULL];
|
|
|
|
}
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
// xxx FIXME adjust range for composite sequence
|
1995-04-03 01:35:42 +00:00
|
|
|
- (void) getCString: (char*)buffer
|
|
|
|
maxLength: (unsigned int)maxLength
|
|
|
|
range: (NSRange)aRange
|
|
|
|
remainingRange: (NSRange*)leftoverRange
|
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
int len, count;
|
1995-04-03 01:35:42 +00:00
|
|
|
|
|
|
|
/* xxx check to make sure aRange is within self; raise NSStringBoundsError */
|
1997-09-18 14:56:47 +00:00
|
|
|
assert(NSMaxRange(aRange) <= [self cStringLength]);
|
1995-04-03 01:35:42 +00:00
|
|
|
if (maxLength < aRange.length)
|
|
|
|
{
|
|
|
|
len = maxLength;
|
|
|
|
if (leftoverRange)
|
|
|
|
{
|
|
|
|
leftoverRange->location = 0;
|
|
|
|
leftoverRange->length = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
len = aRange.length;
|
|
|
|
if (leftoverRange)
|
|
|
|
{
|
|
|
|
leftoverRange->location = aRange.location + maxLength;
|
|
|
|
leftoverRange->length = aRange.length - maxLength;
|
|
|
|
}
|
|
|
|
}
|
1997-05-03 18:05:21 +00:00
|
|
|
count=0;
|
|
|
|
while(count<len)
|
|
|
|
{
|
|
|
|
buffer[count]=unitochar([self characterAtIndex: aRange.location + count]);
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
buffer[len] = '\0';
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Getting Numeric Values
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
// xxx Sould we use NSScanner here ?
|
|
|
|
|
1995-04-03 01:35:42 +00:00
|
|
|
- (double) doubleValue
|
|
|
|
{
|
1996-11-24 21:04:24 +00:00
|
|
|
return atof([self cStringNoCopy]);
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (float) floatValue
|
|
|
|
{
|
1996-11-24 21:04:24 +00:00
|
|
|
return (float) atof([self cStringNoCopy]);
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (int) intValue
|
|
|
|
{
|
1996-11-24 21:04:24 +00:00
|
|
|
return atoi([self cStringNoCopy]);
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Working With Encodings
|
|
|
|
|
|
|
|
+ (NSStringEncoding) defaultCStringEncoding
|
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
return DEFAULT_ENCODING;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) canBeConvertedToEncoding: (NSStringEncoding)encoding
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
id d = [self dataUsingEncoding: encoding allowLossyConversion: NO];
|
|
|
|
return d ? YES : NO;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSData*) dataUsingEncoding: (NSStringEncoding)encoding
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
return [self dataUsingEncoding: encoding allowLossyConversion: NO];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
// xxx incomplete
|
1995-04-03 01:35:42 +00:00
|
|
|
- (NSData*) dataUsingEncoding: (NSStringEncoding)encoding
|
|
|
|
allowLossyConversion: (BOOL)flag
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
unsigned char *buff="";
|
|
|
|
int count=0;
|
|
|
|
int len = [self length];
|
|
|
|
|
|
|
|
if((encoding==NSASCIIStringEncoding)
|
|
|
|
|| (encoding==NSISOLatin1StringEncoding)
|
|
|
|
|| (encoding==NSNEXTSTEPStringEncoding)
|
|
|
|
|| (encoding==NSNonLossyASCIIStringEncoding)
|
|
|
|
|| (encoding==NSSymbolStringEncoding)
|
|
|
|
|| (encoding==NSCyrillicStringEncoding))
|
|
|
|
{
|
|
|
|
char t;
|
|
|
|
OBJC_MALLOC(buff, char, len+1);
|
|
|
|
for(count=0; count<len; count++)
|
|
|
|
if(!flag)
|
|
|
|
if((t = encode_unitochar([self characterAtIndex: count], encoding)))
|
|
|
|
buff[count] = t;
|
|
|
|
else
|
|
|
|
return nil;
|
|
|
|
else /* lossy */
|
|
|
|
if((t = encode_unitochar([self characterAtIndex: count], encoding)))
|
|
|
|
buff[count] = t;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
t=[[NSGSequence sequenceWithString: self
|
|
|
|
range:
|
|
|
|
[self rangeOfComposedCharacterSequenceAtIndex: count]]
|
|
|
|
baseCharacter];
|
|
|
|
if((t = encode_unitochar([self characterAtIndex: count], encoding)))
|
|
|
|
buff[count] = t;
|
|
|
|
else
|
|
|
|
/* xxx should handle decomposed characters */
|
|
|
|
/* OpenStep documentation is unclear on what to do if there is no
|
|
|
|
simple replacement for character */
|
|
|
|
buff[count] = '*';
|
|
|
|
};
|
|
|
|
buff[count]=0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if(encoding==NSUnicodeStringEncoding)
|
|
|
|
{
|
|
|
|
OBJC_MALLOC((unichar*)buff, unichar, len+2);
|
|
|
|
(unichar)buff[0]=0xFEFF;
|
|
|
|
for(count=0; count<len; count++)
|
|
|
|
(unichar)buff[count]=[self characterAtIndex: count];
|
|
|
|
(unichar)buff[count]= (unichar)0;
|
|
|
|
}
|
|
|
|
else /* UTF8 or EUC */
|
|
|
|
[self notImplemented:_cmd];
|
|
|
|
return [NSData dataWithBytes: (char *)buff length: count];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSStringEncoding) fastestEncoding
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-03 01:35:42 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSStringEncoding) smallestEncoding
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-03 01:35:42 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Manipulating File System Paths
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
|
1995-04-03 01:35:42 +00:00
|
|
|
- (unsigned int) completePathIntoString: (NSString**)outputName
|
|
|
|
caseSensitive: (BOOL)flag
|
|
|
|
matchesIntoArray: (NSArray**)outputArray
|
|
|
|
filterTypes: (NSArray*)filterTypes
|
|
|
|
{
|
|
|
|
[self notImplemented:_cmd];
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1997-11-03 01:40:03 +00:00
|
|
|
/* Return a string for passing to OS calls to handle file system objects. */
|
|
|
|
- (const char*)fileSystemRepresentation
|
|
|
|
{
|
|
|
|
return [self cString];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)fileSystemRepresentation: (char*)buffer maxLength: (unsigned int)size
|
|
|
|
{
|
|
|
|
const char* ptr = [self cStringNoCopy];
|
|
|
|
if (strlen(ptr) > size)
|
|
|
|
return NO;
|
|
|
|
strcpy(buffer, ptr);
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
/* Returns a new string containing the last path component of the receiver. The
|
|
|
|
path component is any substring after the last '/' character. If the last
|
|
|
|
character is a '/', then the substring before the last '/', but after the
|
|
|
|
second-to-last '/' is returned. Returns the receiver if there are no '/'
|
|
|
|
characters. Returns the null string if the receiver only contains a '/'
|
|
|
|
character. */
|
1995-04-03 01:35:42 +00:00
|
|
|
- (NSString*) lastPathComponent
|
|
|
|
{
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
NSRange range;
|
|
|
|
NSString *substring = nil;
|
|
|
|
|
1997-09-13 17:52:31 +00:00
|
|
|
range = [self rangeOfString: PATH_COMPONENT options:NSBackwardsSearch];
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
if (range.length == 0)
|
1997-09-13 17:52:31 +00:00
|
|
|
substring = [[self copy] autorelease];
|
|
|
|
else if (range.location == ([self length] - PATH_COMPONENT_LEN))
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
{
|
|
|
|
if (range.location == 0)
|
1997-09-13 17:52:31 +00:00
|
|
|
substring = [[NSString new] autorelease];
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
else
|
1997-09-13 17:52:31 +00:00
|
|
|
substring = [[self substringToIndex:range.location]
|
|
|
|
lastPathComponent];
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
}
|
|
|
|
else
|
1997-09-13 17:52:31 +00:00
|
|
|
substring = [self substringFromIndex:range.location + PATH_COMPONENT_LEN];
|
|
|
|
|
|
|
|
#ifdef PATH_COMPONENT2
|
|
|
|
if (substring == self)
|
|
|
|
{
|
|
|
|
NSRange range2 = [self rangeOfString: PATH_COMPONENT2
|
|
|
|
options:NSBackwardsSearch];
|
|
|
|
if (range2.length == 0)
|
|
|
|
substring = [[self copy] autorelease];
|
|
|
|
else if (range2.location == ([self length] - PATH_COMPONENT_LEN2))
|
|
|
|
{
|
|
|
|
if (range2.location == 0)
|
|
|
|
substring = [[NSString new] autorelease];
|
|
|
|
else
|
|
|
|
substring = [[self substringToIndex:range2.location]
|
|
|
|
lastPathComponent];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
substring = [self substringFromIndex:
|
|
|
|
range2.location + PATH_COMPONENT_LEN2];
|
|
|
|
}
|
|
|
|
#endif /* PATH_COMPONENT2 */
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
|
|
|
|
return substring;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
1997-09-13 17:52:31 +00:00
|
|
|
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
/* Returns a new string containing the path extension of the receiver. The
|
|
|
|
path extension is a suffix on the last path component which starts with
|
|
|
|
a '.' (for example .tiff is the pathExtension for /foo/bar.tiff). Returns
|
|
|
|
a null string if no such extension exists. */
|
1995-04-03 01:35:42 +00:00
|
|
|
- (NSString*) pathExtension
|
|
|
|
{
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
NSRange range;
|
|
|
|
NSString *substring = nil;
|
|
|
|
|
|
|
|
range = [self rangeOfString:@"." options:NSBackwardsSearch];
|
|
|
|
if (range.length == 0
|
1997-09-13 17:52:31 +00:00
|
|
|
|| range.location < ([self rangeOfString: PATH_COMPONENT
|
|
|
|
options:NSBackwardsSearch]).location)
|
|
|
|
substring = nil;
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
else
|
1997-09-13 17:52:31 +00:00
|
|
|
substring = [self substringFromIndex:range.location + PATH_COMPONENT_LEN];
|
|
|
|
|
|
|
|
#ifdef PATH_COMPONENT2
|
|
|
|
if (!substring)
|
|
|
|
{
|
|
|
|
if (range.length == 0
|
|
|
|
|| range.location < ([self rangeOfString: PATH_COMPONENT2
|
|
|
|
options:NSBackwardsSearch]).location)
|
|
|
|
substring = nil;
|
|
|
|
else
|
|
|
|
substring = [self substringFromIndex:
|
|
|
|
range.location + PATH_COMPONENT_LEN2];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!substring)
|
|
|
|
substring = [[NSString new] autorelease];
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
return substring;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
/* Returns a new string with the path component given in aString
|
1997-09-18 14:56:47 +00:00
|
|
|
appended to the receiver. Raises an exception if aString starts with
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
a '/'. Checks the receiver to see if the last letter is a '/', if it
|
|
|
|
is not, a '/' is appended before appending aString */
|
1995-04-03 01:35:42 +00:00
|
|
|
- (NSString*) stringByAppendingPathComponent: (NSString*)aString
|
|
|
|
{
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
NSRange range;
|
|
|
|
NSString *newstring;
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
if ([aString length] == 0)
|
|
|
|
return [[self copy] autorelease];
|
|
|
|
|
|
|
|
range = [aString rangeOfString:@"/"];
|
1997-09-18 14:56:47 +00:00
|
|
|
if (range.length != 0 && range.location == 0)
|
1997-09-01 21:59:51 +00:00
|
|
|
[NSException raise: NSGenericException
|
|
|
|
format: @"attempt to append illegal path component"];
|
|
|
|
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
range = [self rangeOfString:@"/" options:NSBackwardsSearch];
|
1997-09-01 21:59:51 +00:00
|
|
|
if ((range.length == 0 || range.location != [self length] - 1) && [self length] > 0)
|
|
|
|
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
newstring = [self stringByAppendingString:@"/"];
|
|
|
|
else
|
|
|
|
newstring = self;
|
|
|
|
|
|
|
|
return [newstring stringByAppendingString:aString];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
/* Returns a new string with the path extension given in aString
|
1997-09-18 14:56:47 +00:00
|
|
|
appended to the receiver. Raises an exception if aString starts with
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
a '.'. Checks the receiver to see if the last letter is a '.', if it
|
|
|
|
is not, a '.' is appended before appending aString */
|
1995-04-03 01:35:42 +00:00
|
|
|
- (NSString*) stringByAppendingPathExtension: (NSString*)aString
|
|
|
|
{
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
NSRange range;
|
|
|
|
NSString *newstring;
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
if ([aString length] == 0)
|
|
|
|
return [[self copy] autorelease];
|
|
|
|
|
|
|
|
range = [aString rangeOfString:@"."];
|
1997-09-18 14:56:47 +00:00
|
|
|
if (range.length != 0 && range.location == 0)
|
1997-09-01 21:59:51 +00:00
|
|
|
[NSException raise: NSGenericException
|
|
|
|
format: @"attempt to append illegal path extension"];
|
|
|
|
|
1997-05-03 17:24:31 +00:00
|
|
|
range = [self rangeOfString:@"." options:NSBackwardsSearch];
|
1997-09-01 21:59:51 +00:00
|
|
|
if (range.length == 0 || range.location != [self length] - 1)
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
newstring = [self stringByAppendingString:@"."];
|
|
|
|
else
|
|
|
|
newstring = self;
|
|
|
|
|
|
|
|
return [newstring stringByAppendingString:aString];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
/* Returns a new string with the last path component removed from the
|
|
|
|
receiver. See lastPathComponent for a definition of a path component */
|
1995-04-03 01:35:42 +00:00
|
|
|
- (NSString*) stringByDeletingLastPathComponent
|
|
|
|
{
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
NSRange range;
|
|
|
|
NSString *substring;
|
|
|
|
|
|
|
|
range = [self rangeOfString:[self lastPathComponent]
|
|
|
|
options:NSBackwardsSearch];
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
|
|
if (range.length == 0)
|
|
|
|
substring = [[self copy] autorelease];
|
|
|
|
else if (range.location == 0)
|
|
|
|
substring = [[NSString new] autorelease];
|
|
|
|
else if (range.location > 1)
|
1997-05-03 17:26:16 +00:00
|
|
|
substring = [self substringToIndex:range.location-1];
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
else
|
1997-09-13 17:52:31 +00:00
|
|
|
substring = PATH_COMPONENT;
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
return substring;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
/* Returns a new string with the path extension removed from the receiver.
|
|
|
|
See pathExtension for a definition of the path extension */
|
1995-04-03 01:35:42 +00:00
|
|
|
- (NSString*) stringByDeletingPathExtension
|
|
|
|
{
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
NSRange range;
|
|
|
|
NSString *substring;
|
|
|
|
|
|
|
|
range = [self rangeOfString:[self pathExtension] options:NSBackwardsSearch];
|
|
|
|
if (range.length != 0)
|
1997-05-03 17:26:16 +00:00
|
|
|
substring = [self substringToIndex:range.location-1];
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
else
|
1997-09-01 21:59:51 +00:00
|
|
|
substring = [[self copy] autorelease];
|
(componentsSeparatedByString:, substringFromRange:,
rangeOfCharacterFromSet:, rangeOfCharacterFromSet:options:,
rangeOfCharacterFromSet:options:range:, rangeOfString:,
rangeOfString:options:, caseInsensitiveCompare:, hasPrefix:,
hasSuffix:, lastPathComponent, pathExtension,
stringByAppendingPathComponent:, stringByAppendingPathExtension:,
stringByDeletingLastPathComponent, stringByDeletingPathExtension):
Implemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@505 72102866-910b-0410-8b05-ffd578937521
1995-08-02 15:10:41 +00:00
|
|
|
return substring;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString*) stringByExpandingTildeInPath
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
unichar *s;
|
1996-11-24 21:04:24 +00:00
|
|
|
NSString *homedir;
|
|
|
|
NSRange first_slash_range;
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
|
|
OBJC_MALLOC(s, unichar,[self length] +1);
|
|
|
|
[self getCharacters:s];
|
1996-11-24 21:04:24 +00:00
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
if (s[0] != 0x007E)
|
|
|
|
return [[self copy] autorelease];
|
1996-11-24 21:04:24 +00:00
|
|
|
|
|
|
|
first_slash_range = [self rangeOfString: @"/"];
|
|
|
|
|
|
|
|
if (first_slash_range.location != 1)
|
|
|
|
{
|
|
|
|
/* It is of the form `~username/blah/...' */
|
|
|
|
int uname_len;
|
|
|
|
NSString *uname;
|
|
|
|
|
|
|
|
if (first_slash_range.length != 0)
|
|
|
|
uname_len = first_slash_range.length - 1;
|
|
|
|
else
|
|
|
|
/* It is actually of the form `~username' */
|
|
|
|
uname_len = [self length] - 1;
|
|
|
|
uname = [self substringFromRange: ((NSRange){1, uname_len})];
|
|
|
|
homedir = NSHomeDirectoryForUser (uname);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* It is of the form `~/blah/...' */
|
|
|
|
homedir = NSHomeDirectory ();
|
|
|
|
}
|
|
|
|
|
|
|
|
return [NSString stringWithFormat: @"%@%@",
|
|
|
|
homedir,
|
|
|
|
[self substringFromIndex: first_slash_range.location]];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString*) stringByAbbreviatingWithTildeInPath
|
|
|
|
{
|
|
|
|
NSString *homedir = NSHomeDirectory ();
|
|
|
|
|
|
|
|
if (![self hasPrefix: homedir])
|
1997-09-01 21:59:51 +00:00
|
|
|
return [[self copy] autorelease];
|
1996-11-24 21:04:24 +00:00
|
|
|
|
|
|
|
return [NSString stringWithFormat: @"~/%@",
|
|
|
|
[self substringFromIndex: [homedir length] + 1]];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString*) stringByResolvingSymlinksInPath
|
|
|
|
{
|
|
|
|
[self notImplemented:_cmd];
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString*) stringByStandardizingPath
|
|
|
|
{
|
1996-11-24 21:04:24 +00:00
|
|
|
NSMutableString *s;
|
|
|
|
NSRange r;
|
|
|
|
|
|
|
|
/* Expand `~' in the path */
|
|
|
|
s = [[self stringByExpandingTildeInPath] mutableCopy];
|
|
|
|
|
|
|
|
/* Remove `/private' */
|
|
|
|
if ([s hasPrefix: @"/private"])
|
|
|
|
[s deleteCharactersInRange: ((NSRange){0,7})];
|
|
|
|
|
|
|
|
/* Condense `//' */
|
|
|
|
while ((r = [s rangeOfString: @"//"]).length)
|
|
|
|
[s deleteCharactersInRange: r];
|
|
|
|
|
|
|
|
/* Condense `/./' */
|
|
|
|
while ((r = [s rangeOfString: @"/./"]).length)
|
|
|
|
{
|
|
|
|
r.length--;
|
|
|
|
[s deleteCharactersInRange: r];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Condense `/../' */
|
|
|
|
while ((r = [s rangeOfString: @"/../"]).length)
|
|
|
|
{
|
|
|
|
NSRange r2 = {0, r.length-1};
|
|
|
|
r = [s rangeOfString: @"/"
|
|
|
|
options: NSBackwardsSearch
|
|
|
|
range: r2];
|
|
|
|
r.length += 4; /* Add the `/../' */
|
|
|
|
[s deleteCharactersInRange: r];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* xxx Should we not return a mutable string? */
|
|
|
|
return s;
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
// private methods for Unicode level 3 implementation
|
1997-05-03 18:05:21 +00:00
|
|
|
- (int) _baseLength
|
|
|
|
{
|
|
|
|
int count=0;
|
|
|
|
int blen=0;
|
|
|
|
while(count < [self length])
|
|
|
|
if(!uni_isnonsp([self characterAtIndex: count++]))
|
|
|
|
blen++;
|
|
|
|
return blen;
|
|
|
|
}
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
|
|
|
|
- (NSString*) _normalizedString
|
|
|
|
{
|
|
|
|
#define MAXDEC 18
|
|
|
|
|
|
|
|
unichar *u, *upoint;
|
|
|
|
NSRange r;
|
|
|
|
id seq;
|
|
|
|
int len = [self length];
|
|
|
|
int count = 0;
|
|
|
|
OBJC_MALLOC(u, unichar, len*MAXDEC+1);
|
|
|
|
upoint = u;
|
|
|
|
|
|
|
|
while(count < len)
|
|
|
|
{
|
|
|
|
r = [self rangeOfComposedCharacterSequenceAtIndex: count];
|
|
|
|
seq=[NSGSequence sequenceWithString: self range: r];
|
|
|
|
[[seq normalize] getCharacters: upoint];
|
|
|
|
upoint += [seq length];
|
|
|
|
count += r.length;
|
|
|
|
}
|
|
|
|
*upoint = (unichar)0;
|
|
|
|
|
|
|
|
return [self initWithCharactersNoCopy:u
|
|
|
|
length: uslen(u)
|
|
|
|
freeWhenDone:YES];
|
|
|
|
}
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
// #ifndef STRICT_OPENSTEP
|
|
|
|
+ (NSString*) localizedStringWithFormat: (NSString*) format, ...
|
|
|
|
{
|
|
|
|
[self notImplemented:_cmd];
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSComparisonResult) caseInsensitiveCompare: (NSString*)aString
|
|
|
|
{
|
|
|
|
return [self compare:aString options:NSCaseInsensitiveSearch
|
|
|
|
range:((NSRange){0, [self length]})];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) writeToFile: (NSString*)filename
|
|
|
|
atomically: (BOOL)useAuxiliaryFile
|
|
|
|
{
|
1997-09-01 21:59:51 +00:00
|
|
|
id d = [self dataUsingEncoding: NSUnicodeStringEncoding allowLossyConversion: NO];
|
|
|
|
return [d writeToFile: filename
|
|
|
|
atomically: useAuxiliaryFile];
|
1997-05-03 18:05:21 +00:00
|
|
|
}
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
// #ifndef NO_GNUSTEP
|
|
|
|
- (const char *) cStringNoCopy
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
return NULL;
|
|
|
|
}
|
1997-10-31 16:26:44 +00:00
|
|
|
|
|
|
|
- (const char *) quotedCString
|
|
|
|
{
|
|
|
|
const char *from;
|
|
|
|
char *buf;
|
|
|
|
char *ptr;
|
|
|
|
int len = 0;
|
|
|
|
|
|
|
|
for (from = [self cStringNoCopy]; *from; from++) {
|
|
|
|
switch (*from) {
|
|
|
|
case '\a':
|
|
|
|
case '\b':
|
|
|
|
case '\t':
|
|
|
|
case '\r':
|
|
|
|
case '\n':
|
|
|
|
case '\v':
|
|
|
|
case '\f':
|
|
|
|
case '\\':
|
|
|
|
case '\'' :
|
|
|
|
case '"' :
|
|
|
|
len += 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
if (isprint(*from) || *from == ' ') {
|
|
|
|
len++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
len += 4;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
buf = objc_malloc(len + 3);
|
|
|
|
ptr = buf;
|
|
|
|
*ptr++ = '"';
|
|
|
|
for (from = [self cStringNoCopy]; *from; from++) {
|
|
|
|
switch (*from) {
|
|
|
|
case '\a': *ptr++ = '\\'; *ptr++ = 'a'; break;
|
|
|
|
case '\b': *ptr++ = '\\'; *ptr++ = 'b'; break;
|
|
|
|
case '\t': *ptr++ = '\\'; *ptr++ = 't'; break;
|
|
|
|
case '\r': *ptr++ = '\\'; *ptr++ = 'r'; break;
|
|
|
|
case '\n': *ptr++ = '\\'; *ptr++ = 'n'; break;
|
|
|
|
case '\v': *ptr++ = '\\'; *ptr++ = 'v'; break;
|
|
|
|
case '\f': *ptr++ = '\\'; *ptr++ = 'f'; break;
|
|
|
|
case '\\': *ptr++ = '\\'; *ptr++ = '\\'; break;
|
|
|
|
case '\'': *ptr++ = '\\'; *ptr++ = '\''; break;
|
|
|
|
case '"' : *ptr++ = '\\'; *ptr++ = '"'; break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
if (isprint(*from) || *from == ' ') {
|
|
|
|
*ptr++ = *from;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sprintf(ptr, "\\%03o", *(unsigned char*)from);
|
|
|
|
ptr = &ptr[4];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*ptr++ = '"';
|
|
|
|
*ptr = '\0';
|
|
|
|
[MallocAddress autoreleaseMallocAddress: buf];
|
|
|
|
return buf;
|
|
|
|
}
|
1997-05-03 18:05:21 +00:00
|
|
|
// #endif /* NO_GNUSTEP */
|
|
|
|
|
|
|
|
|
1995-04-03 01:35:42 +00:00
|
|
|
/* NSCopying Protocol */
|
|
|
|
|
|
|
|
- copyWithZone: (NSZone*)zone
|
|
|
|
{
|
|
|
|
return [[[self class] allocWithZone:zone] initWithString:self];
|
|
|
|
}
|
|
|
|
|
1996-09-24 17:41:03 +00:00
|
|
|
/* xxx Temporarily put this NSObject-like implementation here, so
|
|
|
|
we don't get String's Collection implementation.
|
|
|
|
When we separate Core from NonCore methods, this problem will
|
|
|
|
go away. */
|
|
|
|
- copy
|
|
|
|
{
|
1997-01-09 19:12:56 +00:00
|
|
|
return [self copyWithZone: NSDefaultMallocZone ()];
|
1996-09-24 17:41:03 +00:00
|
|
|
}
|
|
|
|
|
1995-04-03 01:35:42 +00:00
|
|
|
- mutableCopyWithZone: (NSZone*)zone
|
|
|
|
{
|
1995-08-09 16:07:19 +00:00
|
|
|
return [[[[self class] _mutableConcreteClass] allocWithZone:zone]
|
|
|
|
initWithString:self];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
1995-04-09 01:53:53 +00:00
|
|
|
/* NSCoding Protocol */
|
|
|
|
|
|
|
|
- (void) encodeWithCoder: anEncoder
|
|
|
|
{
|
|
|
|
[super encodeWithCoder:anEncoder];
|
|
|
|
}
|
|
|
|
|
|
|
|
- initWithCoder: aDecoder
|
|
|
|
{
|
|
|
|
return [super initWithCoder:aDecoder];
|
|
|
|
}
|
|
|
|
|
1995-04-03 01:35:42 +00:00
|
|
|
@end
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
|
1995-04-03 01:35:42 +00:00
|
|
|
@implementation NSMutableString
|
|
|
|
|
1995-11-19 20:29:39 +00:00
|
|
|
+ allocWithZone: (NSZone*)z
|
|
|
|
{
|
1997-05-03 17:05:57 +00:00
|
|
|
if ([self class] == [NSMutableString class])
|
|
|
|
return NSAllocateObject([self _mutableConcreteClass], 0, z);
|
|
|
|
return [super allocWithZone:z];
|
1995-11-19 20:29:39 +00:00
|
|
|
}
|
|
|
|
|
1995-04-03 01:35:42 +00:00
|
|
|
/* xxx This method may be removed in future. */
|
|
|
|
- (void) setCString: (const char *)byteString length: (unsigned)length
|
|
|
|
{
|
1995-08-09 16:26:44 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Creating Temporary Strings
|
|
|
|
|
|
|
|
+ (NSMutableString*) stringWithCapacity:(unsigned)capacity
|
|
|
|
{
|
1995-11-19 20:29:39 +00:00
|
|
|
return [[[self alloc] initWithCapacity:capacity]
|
1995-04-03 01:35:42 +00:00
|
|
|
autorelease];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Inefficient. */
|
|
|
|
+ (NSString*) stringWithCharacters: (const unichar*)characters
|
|
|
|
length: (unsigned)length
|
|
|
|
{
|
|
|
|
id n;
|
|
|
|
n = [self stringWithCapacity:length];
|
|
|
|
[n setString: [NSString stringWithCharacters:characters length:length]];
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (NSString*) stringWithCString: (const char*)byteString
|
|
|
|
{
|
|
|
|
return [self stringWithCString:byteString length:strlen(byteString)];
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (NSString*) stringWithCString: (const char*)bytes
|
|
|
|
length:(unsigned)length
|
|
|
|
{
|
1995-11-19 20:29:39 +00:00
|
|
|
id n = [[self alloc] initWithCapacity:length];
|
1995-04-03 01:35:42 +00:00
|
|
|
[n setCString:bytes length:length];
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* xxx Change this when we have non-CString classes */
|
|
|
|
+ (NSString*) stringWithFormat: (NSString*)format, ...
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, format);
|
|
|
|
self = [super stringWithFormat:format arguments:ap];
|
|
|
|
va_end(ap);
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
1997-05-03 18:05:21 +00:00
|
|
|
// Initializing Newly Allocated Strings
|
|
|
|
|
|
|
|
- initWithCapacity:(unsigned)capacity
|
|
|
|
{
|
|
|
|
[self subclassResponsibility:_cmd];
|
|
|
|
return self;
|
|
|
|
}
|
1995-04-03 01:35:42 +00:00
|
|
|
|
|
|
|
// Modify A String
|
|
|
|
|
|
|
|
/* Inefficient. */
|
|
|
|
- (void) appendString: (NSString*)aString
|
|
|
|
{
|
1997-03-03 20:07:35 +00:00
|
|
|
id tmp;
|
|
|
|
if (!aString)
|
|
|
|
return;
|
|
|
|
tmp = [self stringByAppendingString:aString];
|
1995-04-03 01:35:42 +00:00
|
|
|
[self setString:tmp];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Inefficient. */
|
|
|
|
- (void) appendFormat: (NSString*)format, ...
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
id tmp;
|
|
|
|
va_start(ap, format);
|
1997-10-31 16:26:44 +00:00
|
|
|
tmp = [[NSString alloc] initWithFormat:format arguments:ap];
|
1995-04-03 01:35:42 +00:00
|
|
|
va_end(ap);
|
|
|
|
[self appendString:tmp];
|
1997-10-31 16:26:44 +00:00
|
|
|
[tmp release];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) deleteCharactersInRange: (NSRange)range
|
|
|
|
{
|
1995-08-09 16:26:44 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) insertString: (NSString*)aString atIndex:(unsigned)loc
|
|
|
|
{
|
1995-08-09 16:26:44 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Inefficient. */
|
|
|
|
- (void) replaceCharactersInRange: (NSRange)range
|
|
|
|
withString: (NSString*)aString
|
|
|
|
{
|
|
|
|
[self deleteCharactersInRange:range];
|
|
|
|
[self insertString:aString atIndex:range.location];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setString: (NSString*)aString
|
|
|
|
{
|
1997-05-03 18:05:21 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-03 01:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation NXConstantString
|
1995-08-02 15:25:34 +00:00
|
|
|
|
1997-09-12 17:54:10 +00:00
|
|
|
/*
|
|
|
|
* NXConstantString overrides [-dealloc] so that it is never deallocated.
|
|
|
|
* If we pass an NXConstantString to another process it will never get
|
|
|
|
* deallocated in the other process - causing a memory leak. So we tell
|
|
|
|
* the DO system to use the super class instead.
|
|
|
|
*/
|
1997-09-29 14:39:53 +00:00
|
|
|
- (Class)classForPortCoder
|
1997-09-12 17:54:10 +00:00
|
|
|
{
|
|
|
|
return [self superclass];
|
|
|
|
}
|
|
|
|
|
1995-08-02 15:25:34 +00:00
|
|
|
- (void)dealloc
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
- (const char*) cString
|
|
|
|
{
|
|
|
|
return _contents_chars;
|
|
|
|
}
|
|
|
|
|
|
|
|
- retain
|
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
1995-08-09 16:07:19 +00:00
|
|
|
- (oneway void) release
|
1995-08-02 15:25:34 +00:00
|
|
|
{
|
1995-08-09 16:07:19 +00:00
|
|
|
return;
|
1995-08-02 15:25:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- autorelease
|
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- copyWithZone: (NSZone*)z
|
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
1997-09-01 21:59:51 +00:00
|
|
|
- (NSStringEncoding) fastestEncoding
|
|
|
|
{
|
|
|
|
return NSASCIIStringEncoding;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSStringEncoding) smallestEncoding
|
|
|
|
{
|
|
|
|
return NSASCIIStringEncoding;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (unichar) characterAtIndex: (unsigned int)index
|
|
|
|
{
|
|
|
|
/* xxx This should raise an NSException. */
|
|
|
|
CHECK_INDEX_RANGE_ERROR(index, _count);
|
|
|
|
return (unichar)_contents_chars[index];
|
|
|
|
}
|
|
|
|
|
1995-03-12 19:54:14 +00:00
|
|
|
@end
|