/** 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 "GSWPrivate.h" #include #include #include #ifndef GNUSTEP #include #endif #include #include #include #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; SEL gswAppendStringSEL = NULL; SEL gswObjectAtIndexSEL = NULL; //-------------------------------------------------------------------- void GSWInitializeAllMisc() { static BOOL initialized=NO; if (!initialized) { initialized=YES; gswAppendStringSEL = @selector(appendString:); gswObjectAtIndexSEL = @selector(objectAtIndex:); // 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 (%"PRIuPTR") 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 (%"PRIuPTR") enough for %d",bufferSize,origValue); buffer[j++]='-'; }; do { buffer[j++]=buffer[i++]; } while(i=0 && value <100) return cachedString[value]; else return nil; } //-------------------------------------------------------------------- NSString* GSWIntToNSString(int value) { NSString* s=nil; char buffer[20]; NSUInteger 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 && valuetv_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; 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]; }; //==================================================================== @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; 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]; return exception; }; //-------------------------------------------------------------------- -(NSException*)exceptionByAddingUserInfoKey:(id)key format:(NSString*)format,... { NSException* exception=nil; NSString* userInfoString=nil; NSMutableDictionary* excptUserInfo=nil; va_list args; 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]; return exception; }; //-------------------------------------------------------------------- -(NSException*)exceptionByAddingUserInfoFrameInfo:(NSString*)frameInfo { NSException* exception=nil; NSMutableDictionary* excptUserInfo=nil; NSArray* frameInfoArray=nil; 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]; return exception; }; //-------------------------------------------------------------------- -(NSException*)exceptionByAddingUserInfoFrameInfoFormat:(NSString*)format,... { NSException* exception=nil; NSString* frameInfo=nil; va_list args; va_start(args,format); frameInfo = [nsStringClass stringWithFormat:format arguments:args]; va_end(args); exception=[self exceptionByAddingUserInfoFrameInfo:frameInfo]; 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; if (class_isMetaClass([self class]) == NO) { 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]; 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; 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]; 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"]; if (!gmtTZ) NSWarnLog(@"no time zone for GMT"); 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:(NSUInteger)cap { if ((self=[super init])) { _array = [NSMutableArray new]; _compareSelector=NULL; }; return self; } //-------------------------------------------------------------------- - (NSUInteger)count { return [_array count]; } //-------------------------------------------------------------------- - (id)objectAtIndex:(NSUInteger)i { return [_array objectAtIndex:i]; } //-------------------------------------------------------------------- - (void)removeObjectAtIndex:(NSUInteger)i { [_array removeObjectAtIndex:i]; } //-------------------------------------------------------------------- - (oneway void)release { DESTROY(_array); _compareSelector=NULL; [super dealloc]; } //-------------------------------------------------------------------- -(void)addObject:(id)object { //TODO better method int i=0; int count=[_array count]; IMP oaiIMP=NULL; NSComparisonResult result=NSOrderedSame; for(i=0;result!=NSOrderedDescending && i", GSClassNameFromObject(self), self); } return [super description]; } @end #endif //-------------------------------------------------------------------- static NSString * volatileInternalDescription(NSLock *self) { return [self description]; } //-------------------------------------------------------------------- BOOL loggedLockBeforeDateFromFunctionInFileInLine(id self, BOOL try, NSDate *limit, const char *file, const char *function, long line) { BOOL isLocked = YES; NSThread *thread; thread = [NSThread currentThread]; if (limit == nil) { if (try == YES) { isLocked = [self tryLock]; } else { NS_DURING [self lock]; NS_HANDLER { [localException raise]; } NS_ENDHANDLER } } else { isLocked = [self lockBeforeDate: limit]; if (try == NO && isLocked == NO) { NSString *name; NSDebugFLLog(@"locking", @"tried lock FAILED thread %@ " @"date:%@ file:%s function:%s line:%li " @"lock:%@ ", thread, limit, file, function, line, volatileInternalDescription(self)); name = NSStringFromClass([self class]); name = [name stringByAppendingString:@"Exception"]; [NSException raise: name format: @"lockBeforeDate (%@) failed", limit]; } } NSDebugFLLog(@"locking", @"%@ %@ thread %@ " @"date:%@ file:%s function:%s line:%li " @"result:%d lock:%@", (try ? @"tried lock" : @"lock"), (isLocked ? @"SUCCEEDED" : @"FAILED"), thread, limit, file, function, line, isLocked, volatileInternalDescription(self)); return isLocked; } //-------------------------------------------------------------------- void loggedUnlockFromFunctionInFileInLine(id self, const char *file, const char *function, long line) { NSThread *thread; thread = [NSThread currentThread]; NSDebugFLLog(@"locking", @"unlock thread %@ " @"file:%s function:%s line:%li " @"lock:%@", thread, file, function, line, volatileInternalDescription(self)); [self unlock]; NSDebugFLLog(@"locking", @"unlock SUCCEEDED thread %@ " @"file:%s function:%s line:%li " @"lock:%@", thread, file, function, line, volatileInternalDescription(self)); } //==================================================================== @implementation NSArray (NSPerformSelectorWith2Objects) //-------------------------------------------------------------------- -(void)makeObjectsPerformSelector:(SEL)selector withObject:(id)object1 withObject:(id)object2 { NSUInteger i = [self count]; IMP oaiIMP=NULL; while (i-- > 0) { [GSWeb_objectAtIndexWithImpPtr(self,&oaiIMP,i) performSelector:selector withObject:object1 withObject:object2]; } }; //-------------------------------------------------------------------- -(void)makeObjectsPerformSelectorIfPossible:(SEL)aSelector { NSUInteger i = [self count]; IMP oaiIMP=NULL; while (i-->0) [GSWeb_objectAtIndexWithImpPtr(self,&oaiIMP,i) performSelectorIfPossible:aSelector]; } //-------------------------------------------------------------------- -(void)makeObjectsPerformIfPossible:(SEL)aSelector { [self makeObjectsPerformSelectorIfPossible:aSelector]; } //-------------------------------------------------------------------- -(void)makeObjectsPerformSelectorIfPossible:(SEL)aSelector withObject:(id)argument { NSUInteger i = [self count]; IMP oaiIMP=NULL; while (i-->0) { [GSWeb_objectAtIndexWithImpPtr(self,&oaiIMP,i) performSelectorIfPossible:aSelector withObject:argument]; } } //-------------------------------------------------------------------- -(void)makeObjectsPerformSelectorIfPossible:(SEL)aSelector withObject:(id)argument1 withObject:(id)argument2 { NSUInteger i = [self count]; IMP oaiIMP=NULL; while (i-->0) { [GSWeb_objectAtIndexWithImpPtr(self,&oaiIMP,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]; [dict addDefaultEntriesFromDictionary:dictionaryDefaults]; dict=[NSDictionary dictionaryWithDictionary:dict]; } else dict=[NSDictionary dictionaryWithDictionary:dictionaryDefaults]; 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; 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]; 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_getClassName(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; IMP oaiIMP=NULL; for(i=0;iselfLength) [NSException raise:NSInvalidArgumentException format:@"Bad Range (%"PRIuPTR",%"PRIuPTR") 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) { if (memcmp(selfBytes+aRange.location-aDataLength, aDataBytes, aDataLength)==0) { range=NSMakeRange(selfLength-aDataLength,aDataLength); }; } else { if (memcmp(selfBytes+aRange.location, aDataBytes, aDataLength)) { range=NSMakeRange(0,aDataLength); }; }; }; } else { if (reverse) { int i=0; int first=(aRange.location+aDataLength); for(i=aRange.location+aRange.length-1;i>=first && range.length==0;i--) { if (((unsigned char*)selfBytes)[i]==((unsigned char*)aDataBytes)[aDataLength-1]) { if (memcmp(selfBytes+i-aDataLength,aDataBytes,aDataLength)==0) { range=NSMakeRange(i-aDataLength,aDataLength); }; }; }; } else { int i=0; int last=aRange.location+aRange.length-aDataLength; for(i=aRange.location;i<=last && range.length==0;i++) { if (((unsigned char*)selfBytes)[i]==((unsigned char*)aDataBytes)[0]) { if (memcmp(selfBytes+i,aDataBytes,aDataLength)==0) { range=NSMakeRange(i,aDataLength); }; }; }; }; }; }; } 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]; search=NSMakeRange(0, [self length]); complete=search; found=[self rangeOfData:aSeparator]; while (found.length) { NSRange current; current = NSMakeRange (search.location, found.location-search.location); 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]; return [NSArray arrayWithArray:array]; }; //-------------------------------------------------------------------- -(NSData*)dataByDeletingFirstBytesCount:(NSUInteger)bytesCount { NSMutableData* tmpdata=[self mutableCopy]; [tmpdata deleteFirstBytesCount:bytesCount]; return [NSData dataWithData:tmpdata]; }; //-------------------------------------------------------------------- -(NSData*)dataByDeletingLastBytesCount:(NSUInteger)bytesCount { NSMutableData* tmpdata=[self mutableCopy]; [tmpdata deleteLastBytesCount:bytesCount]; return [NSData dataWithData:tmpdata]; }; @end //==================================================================== @implementation NSMutableData (SBNSData) //-------------------------------------------------------------------- -(void)deleteFirstBytesCount:(NSUInteger)bytesCount { void* mutableBytes=NULL; NSUInteger length=[self length]; NSAssert2(length>=bytesCount, @"Can't delete %"PRIuPTR" first bytes from a data of length %"PRIuPTR, bytesCount,length); mutableBytes=[self mutableBytes]; memmove(mutableBytes,mutableBytes+bytesCount,bytesCount); [self setLength:length-bytesCount]; }; //-------------------------------------------------------------------- -(void)deleteLastBytesCount:(NSUInteger)bytesCount; { NSUInteger length=[self length]; NSAssert2(length>=bytesCount, @"Can't delete %"PRIuPTR" last bytes from a data of length %"PRIuPTR, bytesCount,length); [self setLength:length-bytesCount]; }; @end //==================================================================== @implementation NSFooNumberFormatter //-------------------------------------------------------------------- -(id)initType:(NSNumFmtType)type { if ((self=[super init])) { _type=type; }; return self; }; //-------------------------------------------------------------------- -(id)copyWithZone:(NSZone*)zone { NSFooNumberFormatter* clone = [[isa allocWithZone:zone] init]; if (clone) { clone->_type=_type; }; return clone; }; //-------------------------------------------------------------------- -(void)encodeWithCoder:(NSCoder*)coder { [super encodeWithCoder:coder]; [coder encodeValueOfObjCType: @encode(int) at: &_type]; } //-------------------------------------------------------------------- -(id)initWithCoder: (NSCoder*)coder { if (([super initWithCoder:coder])) { [coder decodeValueOfObjCType: @encode(int) at: &_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=[GSWIntToNSString(value) stringByAppendingString:@".00"]; } 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 //==================================================================== @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 { NSUInteger selfLength=[self length]; NSUInteger searchedLength=[data length]; if (aRange.location+aRange.length>selfLength || searchedLength>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]; NSUInteger searchIndex=0; for(searchIndex=aRange.location; searchIndex<(selfLength-searchedLength) && range.length==0; searchIndex++) { NSUInteger i=0; if (bytes[searchIndex]==searchedBytes[0]) { for(i=1;i 0) { NSUInteger byLen = [by length]; const void* byBytes=[by bytes]; do { NSUInteger 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:%"PRIuPTR, __PRETTY_FUNCTION__, path, (NSUInteger)encoding); [NSException raise:NSInvalidArgumentException format:@"%s: could not open convert file contents '%@' non-lossy to encoding %"PRIuPTR, __PRETTY_FUNCTION__, path, (NSUInteger)encoding]; } AUTORELEASE(tmpString); } return tmpString; } @end //==================================================================== NSString* NSStringWithObject(id object) { NSString* string=nil; NSCAssert(nsMutableStringClass,@"GSWUtils not initialized"); if (object) { if ([object isKindOfClass:nsStringClass]) string=(NSString*)object; else if ([object isKindOfClass:eoNullClass]) string=@""; else if ([object respondsToSelector:@selector(stringValue)]) string=[object stringValue]; else if ([object respondsToSelector:@selector(description)]) string=[object description]; else string=object; }; return string; };