/** GSWUtils.m - GSWeb: Utilities Copyright (C) 1999-2003 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" //-------------------------------------------------------------------- BOOL ClassIsKindOfClass(Class classA,Class classB) { Class class; for (class = classA; class != Nil; class = class_get_super_class (class)) { if (class == classB) return YES; } return NO; }; //-------------------------------------------------------------------- BOOL boolValueFor(id anObject) { if (anObject) { if (/*anObject==BNYES ||*/ anObject==NSTYES) return YES; else if (/*anObject==BNNO ||*/ anObject==NSTNO) return NO; else if (/*[anObject conformsTo:@protocol(NSString)]*/ [anObject isKindOfClass:[NSString class]] && [anObject length]>0) 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; //@protocol NSString else if (/*[anObject conformsTo:@protocol(NSString)]*/ [anObject isKindOfClass:[NSString class]] && [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); else if ([anObject respondsToSelector:@selector(unsignedCharValue)]) //BOOL is unsigned char 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]; }; return equal; }; //-------------------------------------------------------------------- BOOL SBIsValueEqual(id id1,id id2) { BOOL equal=SBIsEqual(id1,id2); if (!equal && [id1 class]!=[id2 class]) { if ([id1 isKindOfClass:[NSString class]]) { NSString* id2String=[NSString stringWithObject:id2]; equal=[id1 isEqualToString:id2String]; } else if ([id2 isKindOfClass:[NSString class]]) { NSString* id1String=[NSString stringWithObject: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); }; }; NSString* pidproccontent(NSString* path) { NSString* content=nil; char thePath[BUFSIZ*2]; FILE* theFile = 0; if ([path getFileSystemRepresentation:thePath maxLength:sizeof(thePath)-1] == NO) { LOGSeriousError(@"Open (%@) attempt failed - bad path", path); } else { #if defined(__WIN32__) theFile = fopen(thePath, "rb"); #else theFile = fopen(thePath, "r"); #endif if (theFile == NULL) /* We failed to open the file. */ { LOGSeriousError(@"Open (%s) attempt failed - %s", thePath, strerror(errno)); } else { char buff[1024]=""; if (!fgets(buff,1024,theFile)) { LOGSeriousError(@"Read (%s) attempt failed",thePath); } else { content=[NSString stringWithCString:buff]; }; fclose(theFile); }; }; return content; }; void pidstat(pid_t pid, proc_t* P) { NSString* filename=[NSString stringWithFormat:@"/proc/%d/stat",(int)pid]; NSString* pidstat=pidproccontent(filename); NSDebugFLog(@"pidstat=%@",pidstat); NSDebugFLog(@"filename=%@",filename); NSDebugFLog(@"pid=%d",(int)pid); if (pidstat) { NSRange cmdEnd=[pidstat rangeOfString:@") "]; if (cmdEnd.length>0) { NSString* pid_cmd=[pidstat substringToIndex:cmdEnd.location]; NSDebugFLog(@"pid_cmd=%@",pid_cmd); if (cmdEnd.location+cmdEnd.length<[pidstat length]) { NSString* stats=[pidstat substringFromIndex:cmdEnd.location+cmdEnd.length]; /* char* tmp = strrchr(S, ')'); // split into "PID (cmd" and "" *tmp = '\0'; // replace trailing ')' with NUL // parse these two strings separately, skipping the leading "(". memset(P->cmd, 0, sizeof P->cmd); // clear even though *P xcalloc'd ?! sscanf(S, "%d (%39c", &P->pid, P->cmd); */ const char* statsChars=[stats cString]; NSDebugFLog(@"stats=%@",stats); sscanf(statsChars, "%c %d %d %d %d %d %lu %lu %lu %lu %lu %ld %ld %ld %ld %d " "%d %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %LX %LX %LX %LX %lu", &P->state, &P->ppid, &P->pgrp, &P->session, &P->tty, &P->tpgid, &P->flags, &P->min_flt, &P->cmin_flt, &P->maj_flt, &P->cmaj_flt, &P->utime, &P->stime, &P->cutime, &P->cstime, &P->priority, &P->nice, &P->timeout, &P->it_real_value, &P->start_time, &P->vsize, &P->rss, &P->rss_rlim, &P->start_code, &P->end_code, &P->start_stack, &P->kstk_esp, &P->kstk_eip, &P->signal, &P->blocked, &P->sigignore, &P->sigcatch, &P->wchan); if (P->tty == 0) P->tty = -1; // the old notty val, update elsewhere bef. moving to 0 /* if (linux_version_code < LINUX_VERSION(1,3,39)) { P->priority = 2*15 - P->priority; // map old meanings to new P->nice = 15 - P->nice; } if (linux_version_code < LINUX_VERSION(1,1,30) && P->tty != -1) P->tty = 4*0x100 + P->tty; // when tty wasn't full devno */ NSDebugFLog(@"P->vsize=%lu",P->vsize); NSDebugFLog(@"P->rss=%lu",P->rss); }; }; }; }; void pidstatm(pid_t pid, proc_t* P) { NSString* filename=[NSString stringWithFormat:@"/proc/%d/statm",(int)pid]; NSString* pidstat=pidproccontent(filename); NSDebugFLog(@"pidstat=%@",pidstat); NSDebugFLog(@"filename=%@",filename); NSDebugFLog(@"pid=%d",(int)pid); if (pidstat) { const char* statsChars=[pidstat cString]; NSDebugFLog(@"pidstat=%@",pidstat); sscanf(statsChars, "%ld %ld %ld %ld %ld %ld %ld", &P->size, &P->resident, &P->share, &P->trs, &P->lrs, &P->drs, &P->dt); NSDebugFLog(@"P->size=%ld",P->size); NSDebugFLog(@"P->resident=%ld",P->resident); NSDebugFLog(@"P->share=%ld",P->share); NSDebugFLog(@"P->trs=%ld",P->trs); NSDebugFLog(@"P->lrs=%ld",P->lrs); NSDebugFLog(@"P->drs=%ld",P->drs); NSDebugFLog(@"P->dt=%ld",P->dt); }; }; //-------------------------------------------------------------------- void StackTraceIFND() { NSString* stackTraceString=[NSString stringWithContentsOfFile:[NSString stringWithFormat:@"/tmp/%@.stacktrace", globalApplicationClassName]]; if ([stackTraceString intValue]) { StackTrace(); }; }; //-------------------------------------------------------------------- void DebugBreakpointIFND() { NSString* breakString=[NSString stringWithContentsOfFile:[NSString stringWithFormat:@"/tmp/%@.break", globalApplicationClassName]]; if ([breakString intValue]) { DebugBreakpoint(); }; }; //-------------------------------------------------------------------- void ExceptionRaiseFn(const char *func, const char *file, int line, NSString* name, NSString* format, ...) { NSString* fmt = [NSString stringWithFormat:@"File %s: %d. In %s EXCEPTION %@: %@", func,line,file,name,format]; NSString* string= nil; va_list args; va_start(args,format); string=[NSString 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 stringWithFormat:@"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 stringWithFormat:@"File %s: %d. In %s EXCEPTION %@: %@", func,line,file,name,format]; NSString* string=nil; va_list args; va_start(args,format); string=[NSString stringWithFormat:fmt arguments:args]; va_end(args); NSLog(@"%@",string); exception=[NSException exceptionWithName:name reason:string userInfo:[NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES],@"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 stringWithFormat:@"File %s: %d. In %s EXCEPTION %@: %@", func,line,file,name,format]; NSLog(@"%@",string); exception=[NSException exceptionWithName:name reason:format userInfo:[NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES],@"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=[NSString 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 = [NSString 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 = [NSString 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 = [NSString 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 stringWithFormat: @"%s: %d. In [%@ %c%@] %@", file, line, NSStringFromClass(cls), c, NSStringFromSelector(sel), format]; va_start(args,format); string=[NSString 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 stringWithFormat:@"%s: %d. In %s %@: %@", file,line,fn,format]; string=[NSString 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; NSComparisonResult result=NSOrderedSame; for(i=0;result!=NSOrderedDescending && i<[_array count];i++) { result=(NSComparisonResult)[object performSelector:_compareSelector withObject:[_array objectAtIndex:i]]; if (result==NSOrderedDescending) [_array insertObject:object atIndex:i]; }; if (result!=NSOrderedDescending) [_array addObject:object]; }; //-------------------------------------------------------------------- -(void)addObjectsFromArray:(NSArray*)array { int i; for(i=0;i<[array count];i++) { [_array addObject:[array objectAtIndex:i]]; }; }; //-------------------------------------------------------------------- -(void)insertObject:(id)object atIndex:(unsigned int)index { LOGException0(@"NSMutableOrderedArray doesn't support this fn"); [NSException raise:@"NSMutableOrderedArray" format:@"NSMutableOrderedArray doesn't support %s",sel_get_name(_cmd)]; }; //-------------------------------------------------------------------- -(void)replaceObjectAtIndex:(unsigned int)index withObject:(id)object { LOGException0(@"NSMutableOrderedArray doesn't support this fn"); [NSException raise:@"NSMutableOrderedArray" format:@"NSMutableOrderedArray doesn't support %s",sel_get_name(_cmd)]; }; //-------------------------------------------------------------------- -(void)replaceObjectsInRange:(NSRange)range withObjectsFromArray:(NSArray*)array { LOGException0(@"NSMutableOrderedArray doesn't support this fn"); [NSException raise:@"NSMutableOrderedArray" format:@"NSMutableOrderedArray doesn't support %s",sel_get_name(_cmd)]; }; //-------------------------------------------------------------------- -(void)replaceObjectsInRange:(NSRange)range withObjectsFromArray:(NSArray*)array range:(NSRange)arrayRange { LOGException0(@"NSMutableOrderedArray doesn't support this fn"); [NSException raise:@"NSMutableOrderedArray" format:@"NSMutableOrderedArray doesn't support %s",sel_get_name(_cmd)]; }; //-------------------------------------------------------------------- -(void)setArray:(NSArray*)array { [_array setArray:[array sortedArrayUsingSelector:_compareSelector]]; }; @end //==================================================================== @implementation NSBundle (NSBundleAllFrameworks) //-------------------------------------------------------------------- -(NSString*)bundleName { NSString* bundlePath=nil; NSString* name=nil; LOGObjectFnStart(); bundlePath=[self bundlePath]; NSDebugMLLog(@"low",@"bundlePath=%@",bundlePath); bundlePath=[bundlePath stringGoodPath]; NSDebugMLLog(@"low",@"bundlePath=%@",bundlePath); name=[bundlePath lastPathComponent]; NSDebugMLLog(@"low",@"name=%@",name); name=[name stringByDeletingPathExtension]; NSDebugMLLog(@"low",@"name=%@",name); LOGObjectFnStop(); return name; }; @end //==================================================================== @implementation NSObject (NSObjectVoid) //-------------------------------------------------------------------- -(id)nilMethod { return nil; }; //-------------------------------------------------------------------- +(id)nilMethod { return nil; }; //-------------------------------------------------------------------- -(NSString*)className { return NSStringFromClass([self class]); }; //-------------------------------------------------------------------- +(NSString*)className { return NSStringFromClass([self class]); }; //-------------------------------------------------------------------- -(id)performSelectorIfPossible:(SEL)aSelector { if ([self respondsToSelector:aSelector]) return [self performSelector:aSelector]; else return nil; }; //-------------------------------------------------------------------- -(id)performSelectorIfPossible:(SEL)aSelector withObject:(id)anObject { if ([self respondsToSelector:aSelector]) return [self performSelector:aSelector withObject:anObject]; else return nil; }; //-------------------------------------------------------------------- -(id)performSelectorIfPossible:(SEL)aSelector withObject:(id)object1 withObject:(id)object2 { if ([self respondsToSelector:aSelector]) return [self performSelector:aSelector withObject:object1 withObject:object2]; else return nil; }; @end //==================================================================== #ifdef GNUSTEP @implementation NSThread (Debugging) - (NSString *)description { /* This guards us from associating the wrong objc_thread_id() when other threads invoke description on us. */ if (self == [NSThread currentThread]) { return [NSString stringWithFormat: @"<%s: %p (%p)>", 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 stringWithFormat: @"(%@ mutex:%p owner:%p depth:%d)", self, mutex, mutex->owner, mutex->depth]; } else { return [NSString stringWithFormat: @"(%@ 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=[NSString 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=[NSString stringWithString:@"/"]; }; return good; }; @end //==================================================================== //TODO #ifdef GNUSTEP @implementation NSUserDefaults (Description) //-------------------------------------------------------------------- -(NSString*)description { return [NSString stringWithFormat:@"<%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:[NSString class]]) string=anObject; else if (anObject) { switch(_type) { case NSNumFmtType__Int: if ([anObject isKindOfClass:[NSNumber class]]) { int value=[anObject intValue]; string=[NSString stringWithFormat:@"%d",value]; } else if ([anObject respondsToSelector:@selector(intValue)]) { int value=[anObject intValue]; string=[NSString stringWithFormat:@"%d",value]; } else if ([anObject respondsToSelector:@selector(floatValue)]) { int value=(int)[anObject floatValue]; string=[NSString stringWithFormat:@"%d",value]; } else if ([anObject respondsToSelector:@selector(doubleValue)]) { int value=(int)[anObject doubleValue]; string=[NSString stringWithFormat:@"%d",value]; } else { LOGSeriousError(@"Can't convert %@ of class %@ to string", anObject, [anObject class]); string=@"***"; }; break; case NSNumFmtType__Float: if ([anObject isKindOfClass:[NSNumber class]]) { double value=[anObject doubleValue]; string=[NSString stringWithFormat:@"%.2f",value]; } else if ([anObject respondsToSelector:@selector(intValue)]) { int value=[anObject intValue]; string=[NSString stringWithFormat:@"%d.00",value]; } else if ([anObject respondsToSelector:@selector(floatValue)]) { double value=(double)[anObject floatValue]; string=[NSString stringWithFormat:@"%.2f",value]; } else if ([anObject respondsToSelector:@selector(doubleValue)]) { double value=[anObject doubleValue]; string=[NSString stringWithFormat:@"%.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=[NSNumber numberWithInt:[string intValue]]; ok=YES; break; case NSNumFmtType__Float: *anObject=[NSNumber 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 [[[NSString 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