/** GSWUtils.m - GSWeb: Utilities Copyright (C) 1999-2004 Free Software Foundation, Inc. Written by: Manuel Guesdon Date: Jan 1999 $Revision$ $Date$ $Id$ This file is part of the GNUstep Web Library. 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. 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. **/ #include "config.h" RCS_ID("$Id$") #include "GSWeb.h" #include #include #include #ifdef GNUSTEP #include #endif #include "stacktrace.h" #include "attach.h" static NSNumber* cachedGSWNumber_Yes=nil; static NSNumber* cachedGSWNumber_No=nil; #define INT_NUMBER_CACHE_SIZE 128 static NSNumber* GSWIntNumber_cache[INT_NUMBER_CACHE_SIZE]; static SEL numberWithIntSEL = NULL; static IMP numberWithIntIMP = NULL; static SEL stringWithStringSEL = NULL; static IMP nsString_stringWithStringIMP = NULL; static SEL stringWithFormatSEL = NULL; static IMP nsString_stringWithFormatIMP = NULL; static SEL stringWithCString_lengthSEL = NULL; static IMP nsString_stringWithCString_lengthIMP = NULL; static Class nsNumberClass=Nil; static Class nsStringClass=Nil; static Class nsMutableStringClass=Nil; static Class eoNullClass=Nil; static Class nsNullClass=Nil; static NSMapTable* encodingsByName=NULL; //-------------------------------------------------------------------- void GSWInitializeAllMisc() { static BOOL initialized=NO; if (!initialized) { initialized=YES; // Yes & No ASSIGN(cachedGSWNumber_Yes,([NSNumber numberWithBool:YES])); ASSIGN(cachedGSWNumber_No,([NSNumber numberWithBool:NO])); // GSWInt Number int i=0; nsNumberClass=[NSNumber class]; numberWithIntSEL=@selector(numberWithInt:); NSCAssert(numberWithIntSEL,@"No SEL for numberWithIntSEL:"); numberWithIntIMP=[nsNumberClass methodForSelector:numberWithIntSEL]; for(i=0;i0,@"Buffer not large (%d) enough for %d",bufferSize,origValue);//>0 for null term buffer[i--]='0'+(value%10); value=value/10; } while(value); i++; j=0; if (origValue<0) { NSCAssert2(i>0,@"Buffer not large (%d) enough for %d",bufferSize,origValue); buffer[j++]='-'; }; do { buffer[j++]=buffer[i++]; } while(i %s",origValue,buffer); return buffer; }; //-------------------------------------------------------------------- NSString* cachedStringForInt(int value) { static NSString* cachedString[] = { @"0", @"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10", @"11", @"12", @"13", @"14", @"15", @"16", @"17", @"18", @"19", @"20", @"21", @"22", @"23", @"24", @"25", @"26", @"27", @"28", @"29", @"30", @"31", @"32", @"33", @"34", @"35", @"36", @"37", @"38", @"39", @"40", @"41", @"42", @"43", @"44", @"45", @"46", @"47", @"48", @"49", @"50", @"51", @"52", @"53", @"54", @"55", @"56", @"57", @"58", @"59", @"60", @"61", @"62", @"63", @"64", @"65", @"66", @"67", @"68", @"69", @"70", @"71", @"72", @"73", @"74", @"75", @"76", @"77", @"78", @"79", @"80", @"81", @"82", @"83", @"84", @"85", @"86", @"87", @"88", @"89", @"90", @"91", @"92", @"93", @"94", @"95", @"96", @"97", @"98", @"99" }; if (value>=0 && value <100) return cachedString[value]; else return nil; } //-------------------------------------------------------------------- NSString* GSWIntToNSString(int value) { NSString* s=nil; char buffer[20]; unsigned int resultLength=0; NSCAssert(nsStringClass,@"GSWUtils not initialized"); s=cachedStringForInt(value); if (!s) { GSWIntToString(buffer,20,value,&resultLength); s=(*nsString_stringWithCString_lengthIMP)(nsStringClass,stringWithCString_lengthSEL, buffer,resultLength); } return s; }; //-------------------------------------------------------------------- NSNumber* GSWIntNumber(int value) { NSCAssert(numberWithIntIMP,@"GSWIntNumber not initialized"); if (value>=0 && value0) return ([anObject caseInsensitiveCompare: @"NO"]!=NSOrderedSame); else if ([anObject respondsToSelector:@selector(boolValue)] && [anObject boolValue]) return YES; else if ([anObject respondsToSelector:@selector(intValue)] && [anObject intValue]) return YES; //BOOL is unisgned char else if ([anObject respondsToSelector:@selector(unsignedCharValue)] && [anObject unsignedCharValue]) return YES; else return NO; } else return NO; }; //-------------------------------------------------------------------- BOOL boolValueWithDefaultFor(id anObject,BOOL defaultValue) { if (anObject) { if (/*anObject==BNYES ||*/ anObject==NSTYES) return YES; else if (/*anObject==BNNO ||*/ anObject==NSTNO) return NO; else if ([anObject isKindOfClass:nsStringClass] && [anObject length]>0) return ([anObject caseInsensitiveCompare: @"NO"]!=NSOrderedSame); else if ([anObject respondsToSelector:@selector(boolValue)]) return ([anObject boolValue]!=NO); else if ([anObject respondsToSelector:@selector(intValue)]) return ([anObject intValue]!=0); /* BOOL is unsigned char. */ else if ([anObject respondsToSelector:@selector(unsignedCharValue)]) return ([anObject unsignedCharValue]!=0); else return defaultValue; } else return NO; }; /* //-------------------------------------------------------------------- BOOLNB boolNbFor(BOOL value) { return (value ? BNYES : BNNO); }; */ //-------------------------------------------------------------------- BOOL isHeaderKeysEqual(NSString* headerKey,NSString* testKey) { return [[headerKey lowercaseString]isEqualToString:[testKey lowercaseString]]; }; //-------------------------------------------------------------------- BOOL SBIsEqual(id id1,id id2) { BOOL equal=NO; if (id1==id2) equal=YES; else if (id1) { if (id2) equal=[id1 isEqual:id2]; } else if (!id2) { equal=YES; }; return equal; }; //-------------------------------------------------------------------- BOOL SBIsValueEqual(id id1,id id2) { BOOL equal=SBIsEqual(id1,id2); if (!equal && [id1 class]!=[id2 class]) { if ([id1 isKindOfClass:nsStringClass]) { NSString* id2String=NSStringWithObject(id2); equal=[id1 isEqualToString:id2String]; } else if ([id2 isKindOfClass:nsStringClass]) { NSString* id1String=NSStringWithObject(id1); equal=[id2 isEqualToString:id1String]; }; }; return equal; }; //-------------------------------------------------------------------- BOOL SBIsValueIsIn(id id1,id id2) { int i=0; int count=[id2 count]; for(i=0;itv_sec; interval += (double)tv->tv_usec/1000000.0; /* There seems to be a problem with bad double arithmetic... */ NSCAssert(interval < 0, NSInternalInconsistencyException); return interval; }; //-------------------------------------------------------------------- void NSTimeIntervalSleep(NSTimeInterval ti) { struct timespec ts; struct timespec remaining; ts.tv_sec=(time_t)ti; ts.tv_nsec=(long)((ti-ts.tv_sec)*100000000.0); remaining.tv_sec=0; remaining.tv_nsec=0; NSDebugFLog(@"ts.tv_sec=%ld ts.tv_nsec=%ld",(long)ts.tv_sec,ts.tv_nsec); if (nanosleep(&ts,&remaining)==-1) { NSDebugFLog(@"remaining tv_sec=%ld tv_nsec=%ld",(long)remaining.tv_sec,remaining.tv_nsec); }; }; //-------------------------------------------------------------------- void StackTraceIFND() { NSString* stackTraceString=[nsStringClass stringWithContentsOfFile: (*nsString_stringWithFormatIMP)(nsStringClass,stringWithFormatSEL,@"/tmp/%@.stacktrace", globalApplicationClassName)]; if ([stackTraceString intValue]) { StackTrace(); }; }; //-------------------------------------------------------------------- void DebugBreakpointIFND() { NSString* breakString=[nsStringClass stringWithContentsOfFile: (*nsString_stringWithFormatIMP)(nsStringClass,stringWithFormatSEL,@"/tmp/%@.break", globalApplicationClassName)]; if ([breakString intValue]) { DebugBreakpoint(); }; }; //-------------------------------------------------------------------- void ExceptionRaiseFn(const char *func, const char *file, int line, NSString* name, NSString* format, ...) { NSString* fmt = (*nsString_stringWithFormatIMP) (nsStringClass,stringWithFormatSEL,@"File %s: %d. In %s EXCEPTION %@: %@", func,line,file,name,format); NSString* string= nil; va_list args; va_start(args,format); string=[nsStringClass stringWithFormat:fmt arguments:args]; va_end(args); NSLog(@"%@",string); StackTraceIFND(); DebugBreakpointIFND(); [NSException raise:name format:@"%@",string]; }; //-------------------------------------------------------------------- void ExceptionRaiseFn0(const char *func, const char *file, int line, NSString* name, NSString* format) { NSString* string = (*nsString_stringWithFormatIMP) (nsStringClass,stringWithFormatSEL,@"File %s: %d. In %s EXCEPTION %@: %@", func,line,file,name,format); NSLog(@"%@",string); StackTraceIFND(); DebugBreakpointIFND(); [NSException raise:name format:@"%@",string]; }; //-------------------------------------------------------------------- void ValidationExceptionRaiseFn(const char *func, const char *file, int line, NSString* name, NSString* message, NSString* format, ...) { NSException* exception=nil; NSString* fmt=(*nsString_stringWithFormatIMP) (nsStringClass,stringWithFormatSEL,@"File %s: %d. In %s EXCEPTION %@: %@", func,line,file,name,format); NSString* string=nil; va_list args; va_start(args,format); string=[nsStringClass stringWithFormat:fmt arguments:args]; va_end(args); NSLog(@"%@",string); exception=[NSException exceptionWithName:name reason:string userInfo:[NSDictionary dictionaryWithObjectsAndKeys: GSWNumberYes,@"isValidationException", message,@"message", nil,nil]]; StackTraceIFND(); DebugBreakpointIFND(); [exception raise]; }; //-------------------------------------------------------------------- void ValidationExceptionRaiseFn0(const char *func, const char *file, int line, NSString* name, NSString* message, NSString* format) { NSException* exception=nil; NSString* string=(*nsString_stringWithFormatIMP) (nsStringClass,stringWithFormatSEL,@"File %s: %d. In %s EXCEPTION %@: %@", func,line,file,name,format); NSLog(@"%@",string); exception=[NSException exceptionWithName:name reason:format userInfo:[NSDictionary dictionaryWithObjectsAndKeys: GSWNumberYes,@"isValidationException", message,@"message", nil,nil]]; StackTraceIFND(); DebugBreakpointIFND(); [exception raise]; }; //==================================================================== @implementation NSException (NSBuild) //-------------------------------------------------------------------- +(NSException*)exceptionWithName:(NSString*)excptName format:(NSString*)format,... { NSException* exception=nil; NSString* excptReason=nil; va_list args; va_start(args,format); excptReason=[nsStringClass stringWithFormat:format arguments:args]; va_end(args); exception=[self exceptionWithName:excptName reason:excptReason userInfo: nil]; return exception; }; @end //==================================================================== @implementation NSException (NSExceptionUserInfoAdd) //-------------------------------------------------------------------- -(NSException*)exceptionByAddingUserInfo:(NSDictionary*)aUserInfo { NSMutableDictionary* excptUserInfo = [NSMutableDictionary dictionaryWithDictionary:[self userInfo]]; [excptUserInfo addEntriesFromDictionary:aUserInfo]; return [[self class]exceptionWithName:[self name] reason:[self reason] userInfo: excptUserInfo]; }; //-------------------------------------------------------------------- -(NSException*)exceptionByAddingToUserInfoKey:(id)key format:(NSString*)format,... { NSException* exception=nil; NSString* userInfoString=nil; NSMutableDictionary* excptUserInfo=nil; va_list args; LOGObjectFnStart(); excptUserInfo=[NSMutableDictionary dictionaryWithDictionary:[self userInfo]]; va_start(args,format); userInfoString = [nsStringClass stringWithFormat:format arguments:args]; va_end(args); { id curArray = [excptUserInfo objectForKey:key]; id newArray=[NSMutableArray arrayWithObject:userInfoString]; if (!curArray) { curArray = [NSMutableArray array]; } if (![curArray isKindOfClass:[NSMutableArray class]]) { id tempObject = curArray; curArray = [NSMutableArray array]; [curArray addObject:tempObject]; } [newArray addObjectsFromArray:curArray]; [excptUserInfo setObject:newArray forKey:key]; } exception=[[self class]exceptionWithName:[self name] reason:[self reason] userInfo:excptUserInfo]; LOGObjectFnStop(); return exception; }; //-------------------------------------------------------------------- -(NSException*)exceptionByAddingUserInfoKey:(id)key format:(NSString*)format,... { NSException* exception=nil; NSString* userInfoString=nil; NSMutableDictionary* excptUserInfo=nil; va_list args; LOGObjectFnStart(); excptUserInfo=[NSMutableDictionary dictionaryWithDictionary:[self userInfo]]; va_start(args,format); userInfoString = [nsStringClass stringWithFormat:format arguments:args]; va_end(args); [excptUserInfo setObject:userInfoString forKey:key]; exception=[[self class]exceptionWithName:[self name] reason:[self reason] userInfo:excptUserInfo]; LOGObjectFnStop(); return exception; }; //-------------------------------------------------------------------- -(NSException*)exceptionByAddingUserInfoFrameInfo:(NSString*)frameInfo { NSException* exception=nil; NSMutableDictionary* excptUserInfo=nil; NSArray* frameInfoArray=nil; LOGObjectFnStart(); NSAssert(frameInfo,@"No frameInfo"); excptUserInfo=[NSMutableDictionary dictionaryWithDictionary:[self userInfo]]; frameInfoArray=[excptUserInfo objectForKey:@"FrameInfo"]; if (frameInfoArray) frameInfoArray=[frameInfoArray arrayByAddingObject:frameInfo]; else frameInfoArray=[NSArray arrayWithObject:frameInfo]; [excptUserInfo setObject:frameInfoArray forKey:@"FrameInfo"]; exception=[[self class]exceptionWithName:[self name] reason:[self reason] userInfo:excptUserInfo]; LOGObjectFnStop(); return exception; }; //-------------------------------------------------------------------- -(NSException*)exceptionByAddingUserInfoFrameInfoFormat:(NSString*)format,... { NSException* exception=nil; NSString* frameInfo=nil; va_list args; LOGObjectFnStart(); va_start(args,format); frameInfo = [nsStringClass stringWithFormat:format arguments:args]; va_end(args); exception=[self exceptionByAddingUserInfoFrameInfo:frameInfo]; LOGObjectFnStop(); return exception; }; //-------------------------------------------------------------------- -(NSException*)exceptionByAddingUserInfoFrameInfoObject:(id)obj sel:(SEL)sel file:(const char*)file line:(int)line format:(NSString*)format,... { NSException* exception=nil; Class cls = (Class)obj; char c = '+'; NSString* fmt=nil; NSString* string= nil; va_list args; LOGObjectFnStart(); if ([obj isInstance] == YES) { c = '-'; cls = [obj class]; }; fmt = (*nsString_stringWithFormatIMP)(nsStringClass,stringWithFormatSEL, @"%s: %d. In [%@ %c%@] %@", file, line, NSStringFromClass(cls), c, NSStringFromSelector(sel), format); va_start(args,format); string=[nsStringClass stringWithFormat:fmt arguments:args]; va_end(args); exception=[self exceptionByAddingUserInfoFrameInfo:string]; LOGObjectFnStop(); return exception; }; //-------------------------------------------------------------------- -(NSException*)exceptionByAddingUserInfoFrameInfoFunction:(const char*)fn file:(const char*)file line:(int)line format:(NSString*)format,... { NSException* exception=nil; NSString* fmt =nil; NSString* string= nil; va_list args; LOGObjectFnStart(); va_start(args,format); fmt = (*nsString_stringWithFormatIMP)(nsStringClass,stringWithFormatSEL,@"%s: %d. In %s %@: %@", file,line,fn,format); string=[nsStringClass stringWithFormat:fmt arguments:args]; va_end(args); exception=[self exceptionByAddingUserInfoFrameInfo:string]; LOGObjectFnStop(); return exception; }; //-------------------------------------------------------------------- -(BOOL)isValidationException { BOOL isValidationException=boolValueWithDefaultFor([[self userInfo] objectForKey:@"isValidationException"],NO); return isValidationException; }; @end //==================================================================== @implementation NSDate (NSDateHTMLDescription) //------------------------------------------------------------------------------ -(NSString*)htmlDescription { NSTimeZone* gmtTZ=[NSTimeZone timeZoneWithName:@"GMT"]; LOGObjectFnNotImplemented(); //TODOFN if (!gmtTZ) NSWarnLog(@"no time zone for GMT"); //TODO English day... return [self descriptionWithCalendarFormat:@"%A, %d-%b-%Y %H:%M:%S GMT" timeZone:gmtTZ locale:nil]; }; @end //==================================================================== @implementation NSMutableOrderedArray: NSMutableArray //-------------------------------------------------------------------- - (id)initWithCompareSelector:(SEL)compareSelector { if ((self=[super init])) { _array = [NSMutableArray new]; _compareSelector=compareSelector; } return self; }; //-------------------------------------------------------------------- - (id)initWithCapacity:(unsigned)cap { if ((self=[super init])) { _array = [NSMutableArray new]; _compareSelector=NULL; }; return self; } //-------------------------------------------------------------------- - (unsigned)count { return [_array count]; } //-------------------------------------------------------------------- - (id)objectAtIndex:(unsigned)i { return [_array objectAtIndex:i]; } //-------------------------------------------------------------------- - (void)removeObjectAtIndex:(unsigned)i { [_array removeObjectAtIndex:i]; } //-------------------------------------------------------------------- - (void)release { DESTROY(_array); _compareSelector=NULL; [super dealloc]; } //-------------------------------------------------------------------- -(void)addObject:(id)object { //TODO better method int i=0; int count=[_array count]; NSComparisonResult result=NSOrderedSame; for(i=0;result!=NSOrderedDescending && i", GSClassNameFromObject(self), self, objc_thread_id()); } return [super description]; } @end #endif //-------------------------------------------------------------------- static NSString * volatileInternalDescription(NSLock *self) { #ifdef GNUSTEP struct objc_mutex *mutex = 0; const char *type; unsigned int size; int offset; if (GSObjCFindVariable(self, "_mutex", &type, &size, &offset)) { GSObjCGetVariable(self, offset, size, &mutex); } if (mutex != 0) { return (*nsString_stringWithFormatIMP)(nsStringClass,stringWithFormatSEL, @"(%@ mutex:%p owner:%p depth:%d)", self, mutex, mutex->owner, mutex->depth); } else { return (*nsString_stringWithFormatIMP)(nsStringClass,stringWithFormatSEL, @"(%@ mutex:%p)", self, mutex); } #else return [self description]; #endif } //-------------------------------------------------------------------- BOOL loggedLockBeforeDateFromFunctionInFileInLine(id self, BOOL try, NSDate *limit, const char *file, const char *function, long line) { BOOL isLocked = YES; NSThread *thread; void *threadID = 0; thread = [NSThread currentThread]; #ifdef GNUSTEP threadID = objc_thread_id(); #endif NSDebugFLLog(@"locking", @"%@ thread %@(%p) " @"date:%@ file:%s function:%s line:%li " @"lock:%@", (try ? @"trying lock" : @"locking"), thread, threadID, limit, file, function, line, volatileInternalDescription(self)); if (limit == nil) { if (try == YES) { isLocked = [self tryLock]; } else { NS_DURING [self lock]; NS_HANDLER { NSDebugFLLog(@"locking", @"locking FAILED thread %@(%p) " @"date:%@ file:%s function:%s line:%li " @"lock:%@ " @"excaption:%@ reason:%@ info:%@", thread, threadID, limit, file, function, line, volatileInternalDescription(self), [localException name], [localException reason], [localException userInfo]); [localException raise]; } NS_ENDHANDLER } } else { isLocked = [self lockBeforeDate: limit]; if (try == NO && isLocked == NO) { NSString *name; NSDebugFLLog(@"locking", @"tried lock FAILED thread %@(%p) " @"date:%@ file:%s function:%s line:%li " @"lock:%@ " @"exception:%@ reason:%@ info:%@", thread, threadID, limit, file, function, line, volatileInternalDescription(self)); name = NSStringFromClass([self class]); name = [name stringByAppendingString:@"Exception"]; [NSException raise: name format: @"lockBeforeDate (%@) failed", limit]; } } NSDebugFLLog(@"locking", @"%@ %@ thread %@(%p) " @"date:%@ file:%s function:%s line:%li " @"result:%d lock:%@", (try ? @"tried lock" : @"lock"), (isLocked ? @"SUCCEEDED" : @"FAILED"), thread, threadID, limit, file, function, line, isLocked, volatileInternalDescription(self)); return isLocked; } //-------------------------------------------------------------------- void loggedUnlockFromFunctionInFileInLine(id self, const char *file, const char *function, long line) { NSThread *thread; void *threadID = 0; thread = [NSThread currentThread]; #ifdef GNUSTEP threadID = objc_thread_id(); #endif NSDebugFLLog(@"locking", @"unlock thread %@(%p) " @"file:%s function:%s line:%li " @"lock:%@", thread, threadID, file, function, line, volatileInternalDescription(self)); [self unlock]; NSDebugFLLog(@"locking", @"unlock SUCCEEDED thread %@(%p) " @"file:%s function:%s line:%li " @"lock:%@", thread, threadID, file, function, line, volatileInternalDescription(self)); } //==================================================================== @implementation NSArray (NSPerformSelectorWith2Objects) //-------------------------------------------------------------------- -(void)makeObjectsPerformSelector:(SEL)selector withObject:(id)object1 withObject:(id)object2 { unsigned i = [self count]; while (i-- > 0) [[self objectAtIndex:i]performSelector:selector withObject:object1 withObject:object2]; }; //-------------------------------------------------------------------- -(void)makeObjectsPerformSelectorIfPossible:(SEL)aSelector { unsigned i = [self count]; while (i-->0) [[self objectAtIndex: i] performSelectorIfPossible:aSelector]; } //-------------------------------------------------------------------- -(void)makeObjectsPerformIfPossible:(SEL)aSelector { [self makeObjectsPerformSelectorIfPossible:aSelector]; } //-------------------------------------------------------------------- -(void)makeObjectsPerformSelectorIfPossible:(SEL)aSelector withObject:(id)argument { unsigned i = [self count]; while (i-->0) [[self objectAtIndex: i] performSelectorIfPossible:aSelector withObject:argument]; } //-------------------------------------------------------------------- -(void)makeObjectsPerformSelectorIfPossible:(SEL)aSelector withObject:(id)argument1 withObject:(id)argument2 { unsigned i = [self count]; while (i-->0) [[self objectAtIndex: i] performSelectorIfPossible:aSelector withObject:argument1 withObject:argument2]; } //-------------------------------------------------------------------- -(void)makeObjectsPerformIfPossible:(SEL)aSelector withObject:(id)argument { [self makeObjectsPerformSelectorIfPossible:aSelector withObject: argument]; } @end //==================================================================== @implementation NSDictionary (NSPerformSelector) //-------------------------------------------------------------------- -(void)makeObjectsPerformSelector:(SEL)selector { NSArray* array=[self allValues]; [array makeObjectsPerformSelector:selector]; }; //-------------------------------------------------------------------- -(void)makeObjectsPerformSelector:(SEL)selector withObject:(id)object { NSArray* array=[self allValues]; [array makeObjectsPerformSelector:selector withObject:object]; }; //-------------------------------------------------------------------- -(void)makeObjectsPerformSelector:(SEL)selector withObject:(id)object1 withObject:(id)object2 { NSArray* array=[self allValues]; [array makeObjectsPerformSelector:selector withObject:object1 withObject:object2]; }; //-------------------------------------------------------------------- -(void)makeObjectsPerformSelectorIfPossible:(SEL)aSelector { NSArray* array=[self allValues]; [array makeObjectsPerformSelectorIfPossible:aSelector]; }; //-------------------------------------------------------------------- -(void)makeObjectsPerformIfPossible:(SEL)aSelector { NSArray* array=[self allValues]; [array makeObjectsPerformSelectorIfPossible:aSelector]; }; //-------------------------------------------------------------------- -(void)makeObjectsPerformSelectorIfPossible:(SEL)aSelector withObject:(id)object { NSArray* array=[self allValues]; [array makeObjectsPerformSelectorIfPossible:aSelector withObject:object]; }; //-------------------------------------------------------------------- -(void)makeObjectsPerformIfPossible:(SEL)aSelector withObject:(id)argument { NSArray* array=[self allValues]; [array makeObjectsPerformSelectorIfPossible:aSelector withObject:argument]; }; //-------------------------------------------------------------------- -(void)makeObjectsPerformSelectorIfPossible:(SEL)aSelector withObject:(id)object1 withObject:(id)object2 { NSArray* array=[self allValues]; [array makeObjectsPerformSelectorIfPossible:aSelector withObject:object1 withObject:object2]; }; @end //-------------------------------------------------------------------- NSString* GSWGetDefaultDocRoot() { NSUserDefaults* userDefaults=[NSUserDefaults standardUserDefaults]; NSDictionary* gsweb=[userDefaults objectForKey:@"GSWeb"]; NSString* rootDoc=[gsweb objectForKey:@"rootDoc"]; if (!rootDoc) rootDoc=[nsStringClass stringWithString:@"/home/httpd/gsweb"]; return rootDoc; }; //=================================================================================== @implementation NSDictionary (SBDictionary) //-------------------------------------------------------------------- -(id) objectForKey:(id)key withDefaultObject:(id)defaultObject { id object=[self objectForKey:key]; if (object) return object; else return defaultObject; }; //-------------------------------------------------------------------- +(NSDictionary*)dictionaryWithDictionary:(NSDictionary*)dictionary andDefaultEntriesFromDictionary:(NSDictionary*)dictionaryDefaults { NSMutableDictionary* dict=nil; if (dictionary) { dict=[[dictionary mutableCopy]autorelease]; //NSDebugFLog(@"_dict=%@",_dict); [dict addDefaultEntriesFromDictionary:dictionaryDefaults]; //NSDebugFLog(@"_dict=%@",_dict); dict=[NSDictionary dictionaryWithDictionary:dict]; //NSDebugFLog(@"_dict=%@",_dict); } else dict=[NSDictionary dictionaryWithDictionary:dictionaryDefaults]; // NSDebugFLog(@"dict=%@",dict); return dict; }; //-------------------------------------------------------------------- -(NSDictionary*)dictionaryBySettingObject:(id)object forKey:(id)key { NSMutableDictionary* dict=[[self mutableCopy]autorelease]; [dict setObject:object forKey:key]; dict=[NSDictionary dictionaryWithDictionary:dict]; return dict; }; //-------------------------------------------------------------------- -(NSDictionary*)dictionaryByAddingEntriesFromDictionary:(NSDictionary*)dictionary { NSMutableDictionary* dict=[[self mutableCopy]autorelease]; [dict addEntriesFromDictionary:dictionary]; dict=[NSDictionary dictionaryWithDictionary:dict]; return dict; }; @end //==================================================================== @implementation NSMutableDictionary (SBMutableDictionary) //-------------------------------------------------------------------- -(void)setDefaultObject:(id)object forKey:(id)key { if (![self objectForKey:key]) [self setObject:object forKey:key]; }; //-------------------------------------------------------------------- -(void)addDefaultEntriesFromDictionary:(NSDictionary*)dictionary { id key=nil; NSEnumerator* anEnum = [dictionary keyEnumerator]; while ((key=[anEnum nextObject])) [self setDefaultObject:[dictionary objectForKey:key] forKey:key]; }; //-------------------------------------------------------------------- -(NSDictionary*)extractObjectsForKeysWithPrefix:(NSString*)prefix removePrefix:(BOOL)removePrefix { NSMutableDictionary* newDictionary=nil; NSEnumerator *enumerator = nil; NSString* key=nil; NSString* newKey=nil; id value=nil; LOGObjectFnStart(); newDictionary=(NSMutableDictionary*)[NSMutableDictionary dictionary]; enumerator = [self keyEnumerator]; while ((key = [enumerator nextObject])) { NSDebugMLLog(@"associations",@"key=%@",key); if ([key hasPrefix:prefix]) { value=[self objectForKey:key]; NSDebugMLLog(@"associations",@"value=%@",value); if (removePrefix) newKey=[key stringByDeletingPrefix:prefix]; else newKey=key; [newDictionary setObject:value forKey:newKey]; [self removeObjectForKey:key]; }; }; newDictionary=[NSDictionary dictionaryWithDictionary:newDictionary]; LOGObjectFnStop(); return newDictionary; }; @end //=================================================================================== @implementation NSString (SBGoodPath) //-------------------------------------------------------------------- -(NSString*)stringGoodPath { NSString* good=[self stringByStandardizingPath]; while([good hasSuffix:@"/."]) { if ([good length]>2) good=[good stringByDeletingSuffix:@"/."]; else good=[nsStringClass stringWithString:@"/"]; }; return good; }; @end //==================================================================== //TODO #ifdef GNUSTEP @implementation NSUserDefaults (Description) //-------------------------------------------------------------------- -(NSString*)description { return (*nsString_stringWithFormatIMP)(nsStringClass,stringWithFormatSEL,@"<%s %p - searchList:\n%@\n persDomains:\n%@\n tempDomains:\n%@\n changedDomains:\n%@\n dictionaryRep:\n%@\n defaultsDatabase:\n%@\n>", object_get_class_name(self), (void*)self, _searchList, _persDomains, _tempDomains, _changedDomains, _dictionaryRep, _defaultsDatabase); }; @end #endif //==================================================================== @implementation NSDictionary (FromNSArray) //-------------------------------------------------------------------- +(id)dictionaryWithArray:(NSArray*)array onSelector:(SEL)sel { NSMutableDictionary* dict=[NSMutableDictionary dictionary]; int count=[array count]; int i=0; id object=nil; id key=nil; for(i=0;iselfLength) [NSException raise:NSInvalidArgumentException format:@"Bad Range (%d,%d) for self length %d", aRange.location, aRange.length, selfLength]; else if (aDataLength>0) { BOOL reverse=((mask&NSBackwardsSearch)==NSBackwardsSearch); BOOL anchored=((mask&NSAnchoredSearch)==NSAnchoredSearch); const void* selfBytes=[self bytes]; const void* aDataBytes=[aData bytes]; NSDebugFLog(@"reverse=%d",(int)reverse); NSDebugFLog(@"anchored=%d",(int)anchored); if (anchored) { // Can be found ? if (aDataLength<=aRange.length) { if (reverse) { NSDebugFLog(@"cmp at %d length %d", aRange.location-aDataLength, aDataLength); if (memcmp(selfBytes+aRange.location-aDataLength, aDataBytes, aDataLength)==0) { NSDebugFLog0(@"FOUND"); range=NSMakeRange(selfLength-aDataLength,aDataLength); }; } else { NSDebugFLog(@"cmp at %d length %d", aRange.location, aDataLength); if (memcmp(selfBytes+aRange.location, aDataBytes, aDataLength)) { NSDebugFLog0(@"FOUND"); range=NSMakeRange(0,aDataLength); }; }; }; } else { if (reverse) { int i=0; int first=(aRange.location+aDataLength); NSDebugFLog(@"cmp at %d downto index: %d", aRange.location+aRange.length-1, first); for(i=aRange.location+aRange.length-1;i>=first && range.length==0;i--) { if (((unsigned char*)selfBytes)[i]==((unsigned char*)aDataBytes)[aDataLength-1]) { NSDebugFLog(@"FOUND Last Char at %d",i); if (memcmp(selfBytes+i-aDataLength,aDataBytes,aDataLength)==0) { range=NSMakeRange(i-aDataLength,aDataLength); NSDebugFLog(@"FOUND at %d",i-aDataLength); }; }; }; } else { int i=0; int last=aRange.location+aRange.length-aDataLength; NSDebugFLog(@"cmp at %d upto index: %d", aRange.location, last); for(i=aRange.location;i<=last && range.length==0;i++) { if (((unsigned char*)selfBytes)[i]==((unsigned char*)aDataBytes)[0]) { NSDebugFLog(@"FOUND First Char at %d",i); if (memcmp(selfBytes+i,aDataBytes,aDataLength)==0) { range=NSMakeRange(i,aDataLength); NSDebugFLog(@"FOUND at %d",i); }; }; }; }; }; }; } else [NSException raise:NSInvalidArgumentException format: @"range of nil"]; return range; } //-------------------------------------------------------------------- -(NSArray*)componentsSeparatedByData:(NSData*)aSeparator { NSRange search, complete; NSRange found; NSData* tmpData=nil; NSMutableArray *array = [NSMutableArray array]; NSDebugFLog(@"aSeparator %@ length=%d",aSeparator,[aSeparator length]); NSDebugFLog(@"self length=%d",[self length]); search=NSMakeRange(0, [self length]); complete=search; found=[self rangeOfData:aSeparator]; NSDebugFLog(@"found=(%u,%u)",found.location,found.length); while (found.length) { NSRange current; current = NSMakeRange (search.location, found.location-search.location); NSDebugFLog(@"current=(%u,%u)",current.location,current.length); tmpData=[self subdataWithRange:current]; [array addObject:tmpData]; search = NSMakeRange (found.location + found.length, complete.length - found.location - found.length); found = [self rangeOfData:aSeparator options: 0 range:search]; } // Add the last search data range tmpData=[self subdataWithRange:search]; [array addObject:tmpData]; NSDebugFLog(@"array=%@",array); return [NSArray arrayWithArray:array]; }; //-------------------------------------------------------------------- -(NSData*)dataByDeletingFirstBytesCount:(unsigned int)bytesCount { NSMutableData* tmpdata=[self mutableCopy]; [tmpdata deleteFirstBytesCount:bytesCount]; return [NSData dataWithData:tmpdata]; }; //-------------------------------------------------------------------- -(NSData*)dataByDeletingLastBytesCount:(unsigned int)bytesCount { NSMutableData* tmpdata=[self mutableCopy]; [tmpdata deleteLastBytesCount:bytesCount]; return [NSData dataWithData:tmpdata]; }; @end //==================================================================== @implementation NSMutableData (SBNSData) //-------------------------------------------------------------------- -(void)deleteFirstBytesCount:(unsigned int)bytesCount { void* mutableBytes=NULL; unsigned int length=[self length]; NSAssert2(length>=bytesCount, @"Can't delete %d first bytes from a data of length %d", bytesCount,length); mutableBytes=[self mutableBytes]; memmove(mutableBytes,mutableBytes+bytesCount,bytesCount); [self setLength:length-bytesCount]; }; //-------------------------------------------------------------------- -(void)deleteLastBytesCount:(unsigned int)bytesCount; { unsigned int length=[self length]; NSAssert2(length>=bytesCount, @"Can't delete %d last bytes from a data of length %d", bytesCount,length); [self setLength:length-bytesCount]; }; @end //==================================================================== @implementation NSFooNumberFormatter //-------------------------------------------------------------------- -(id)initType:(NSNumFmtType)type { if ((self=[super init])) { _type=type; }; return self; }; //-------------------------------------------------------------------- -(NSString*)stringForObjectValue:(id)anObject { NSString* string=nil; if ([anObject isKindOfClass:nsStringClass]) string=anObject; else if (anObject) { switch(_type) { case NSNumFmtType__Int: if ([anObject isKindOfClass:nsNumberClass]) { int value=[anObject intValue]; string=GSWIntToNSString(value); } else if ([anObject respondsToSelector:@selector(intValue)]) { int value=[anObject intValue]; string=GSWIntToNSString(value); } else if ([anObject respondsToSelector:@selector(floatValue)]) { int value=(int)[anObject floatValue]; string=GSWIntToNSString(value); } else if ([anObject respondsToSelector:@selector(doubleValue)]) { int value=(int)[anObject doubleValue]; string=GSWIntToNSString(value); } else { LOGSeriousError(@"Can't convert %@ of class %@ to string", anObject, [anObject class]); string=@"***"; }; break; case NSNumFmtType__Float: if ([anObject isKindOfClass:nsNumberClass]) { double value=[anObject doubleValue]; string=(*nsString_stringWithFormatIMP)(nsStringClass,stringWithFormatSEL,@"%.2f",value); } else if ([anObject respondsToSelector:@selector(intValue)]) { int value=[anObject intValue]; string=(*nsString_stringWithFormatIMP)(nsStringClass,stringWithFormatSEL,@"%d.00",value); } else if ([anObject respondsToSelector:@selector(floatValue)]) { double value=(double)[anObject floatValue]; string=(*nsString_stringWithFormatIMP)(nsStringClass,stringWithFormatSEL,@"%.2f",value); } else if ([anObject respondsToSelector:@selector(doubleValue)]) { double value=[anObject doubleValue]; string=(*nsString_stringWithFormatIMP)(nsStringClass,stringWithFormatSEL,@"%.2f",value); } else { LOGSeriousError(@"Can't convert %@ of class %@ to string", anObject, [anObject class]); string=@"***"; }; break; case NSNumFmtType__Unknown: default: LOGSeriousError(@"Unknown type %d to convert %@ to string", (int)_type, anObject); string=@"***"; break; }; }; return string; }; //-------------------------------------------------------------------- -(BOOL)getObjectValue:(id*)anObject forString:(NSString*)string errorDescription:(NSString**)error { BOOL ok=NO; NSAssert(anObject,@"No value* to return"); NSAssert(error,@"No error* to return"); *anObject=nil; *error=nil; switch(_type) { case NSNumFmtType__Int: *anObject=GSWIntNumber([string intValue]); ok=YES; break; case NSNumFmtType__Float: *anObject=[nsNumberClass numberWithFloat:[string floatValue]]; ok=YES; break; case NSNumFmtType__Unknown: default: LOGSeriousError(@"Unknown type %d to convert from string %@", (int)_type, string); *error = @"Unknown type"; break; }; return ok; }; @end #include //==================================================================== @implementation NSData (Base64) //-------------------------------------------------------------------- - (NSString*) base64Representation { return [[[nsStringClass alloc]initWithData:[GSMimeDocument encodeBase64:self] encoding:NSASCIIStringEncoding] autorelease]; }; //-------------------------------------------------------------------- - (id) initWithBase64Representation: (NSString*)string { return [self initWithData:[GSMimeDocument decodeBase64:[string dataUsingEncoding: NSASCIIStringEncoding]]]; }; @end //==================================================================== @implementation NSData (Search) //-------------------------------------------------------------------- - (NSRange) rangeOfData: (NSData *)data range: (NSRange)aRange { NSRange range=NSMakeRange(0,0); if (data == nil) [NSException raise: NSInvalidArgumentException format: @"range of nil"]; else { int selfLength=[self length]; int searchedLength=[data length]; if (aRange.location<0) { } else if (aRange.location+aRange.length>selfLength) { } else if (selfLength>0 && searchedLength>0) { const unsigned char* bytes=(const unsigned char*)[self bytes]; const unsigned char* searchedBytes=(const unsigned char*)[data bytes]; int searchIndex=0; for(searchIndex=aRange.location; searchIndex<(selfLength-searchedLength) && range.length==0; searchIndex++) { int i=0; if (bytes[searchIndex]==searchedBytes[0]) { for(i=1;i 0) { unsigned byLen = [by length]; const void* byBytes=[by bytes]; do { unsigned int newEnd; count++; [self replaceBytesInRange:range withBytes:byBytes length:byLen]; newEnd = NSMaxRange(searchRange) + byLen - range.length; searchRange.location = range.location + byLen; searchRange.length = newEnd - searchRange.location; range = [self rangeOfData: replace range: searchRange]; } while (range.length > 0); } return count; } @end //==================================================================== // this should be in Gnustep base / extensions @implementation NSString (EncodingDataExt) //-------------------------------------------------------------------- + (id)stringWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)encoding { NSData * tmpData = nil; NSString * tmpString = nil; if ((tmpData = [NSData dataWithContentsOfFile: path])) { tmpString = [nsStringClass alloc]; tmpString = [tmpString initWithData:tmpData encoding:encoding]; if (!tmpString) { NSLog(@"%s NO STRING for path '%@' encoding:%d", __PRETTY_FUNCTION__, path, encoding); [NSException raise:NSInvalidArgumentException format:@"%s: could not open convert file contents '%s' non-lossy to encoding %i", __PRETTY_FUNCTION__, path, encoding]; } AUTORELEASE(tmpString); } return tmpString; } //-------------------------------------------------------------------- + (NSStringEncoding) encodingNamed:(NSString*) encodingName { NSStringEncoding encoding=GSUndefinedEncoding; NSCAssert(encodingsByName,@"encodingsByName not initialized"); encoding=(NSStringEncoding)NSMapGet(encodingsByName,(const void*)encodingName); if (!encoding) [NSException raise:NSInvalidArgumentException format:@"%s: does not know about '%s'", __PRETTY_FUNCTION__, encodingName]; return encoding; } @end //==================================================================== NSString* NSStringWithObject(id object) { NSString* string=nil; NSCAssert(nsMutableStringClass,@"GSWUtils not initialized"); if (object) { if ([object isKindOfClass:nsMutableStringClass]) string=AUTORELEASE([object copy]); else if ([object isKindOfClass:nsStringClass]) string=(NSString*)object; #ifdef HAVE_GDL2 else if ([object isKindOfClass:eoNullClass]) string=@""; #else else if ([object isKindOfClass:nsNullClass]) string=@""; #endif else if ([object respondsToSelector:@selector(stringValue)]) string=[object stringValue]; else if ([object respondsToSelector:@selector(description)]) string=[object description]; else string=object; }; return string; };