bug-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Modifications on gnustep-base for OSX compatibility


From: Stéphane Corthésy
Subject: Modifications on gnustep-base for OSX compatibility
Date: Thu, 27 Mar 2003 20:36:50 -0000

Hi,

Here are some methods missing in gnustep-base for MacOS X compatibility; they are defined in gnustep, but should/could be moved in Additions/GSCategories.h/m. They are needed to compile gsweb on OSX.

I'm not sure at all that my reimplementation of GSCurrentThreadDictionary() is correct!

I also have a question concerning GCxxx classes: shouldn't all retain/release/autorelease calls be replaced by macros too? If so, I'll provide a patch.

Other question: in base/Source/Additions/GSMime.m, in -[GSMimeDocument copyWithZone:], shouldn't the implementation do a real copy, as the instances are mutable, instead of simply performing a RETAIN() on self? Same question for -[GSXMLDocument copyWithZone:].


Stéphane

===========
Changelog

base/Headers/gnustep/base/GSCategories.h: declared new methods
base/Source/Additions/GSCategories.m: new compatibility methods for NSString and NSMutableString (copied from NSString.m); implemented +[NSDistantObject setDebug:] by using Apple's private method, if method exists; copied -[NSNumber valueFromString:] from NSNumber.m; added simple implementation of GSCurrentThreadDictionary(); provided implementations of -[NSFileHandle initAsServerAtAddress:service:protocol:], +[NSFileHandle fileHandleAsServerAtAddress:service:protocol:] and -[NSFileHandle socketAddress] - code has been adapted from GSFileHandle;



Index: GSCategories.h
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/base/Headers/gnustep/base/GSCategories.h,v
retrieving revision 1.7
diff -r1.7 GSCategories.h
36a37
> #include <gnustep/base/GSObjCRuntime.h>
55a57,61
> - (NSString*) stringByTrimmingLeadSpaces;
> - (NSString*) stringByTrimmingTailSpaces;
> - (NSString*) stringByTrimmingSpaces;
> - (NSString*) stringByReplacingString: (NSString*)replace
>                            withString: (NSString*)by;
60a67,71
> - (void) replaceString: (NSString*)replace
>             withString: (NSString*)by;
> - (void) trimLeadSpaces;
> - (void) trimTailSpaces;
> - (void) trimSpaces;
73a85,101
>
> @interface NSDistantObject (GSCategories)
> + (void) setDebug: (int)val;
> @end
>
> @interface NSNumber(GSCategories)
> + (NSValue*) valueFromString: (NSString *)string;
> @end
>
> GS_EXPORT NSMutableDictionary *GSCurrentThreadDictionary();
>
> @interface NSFileHandle(GSCompatibility)
> + (id) fileHandleAsServerAtAddress: (NSString*)address
>                            service: (NSString*)service
>                           protocol: (NSString*)protocol;
> - (NSString*) socketAddress;
> @end


Index: GSCategories.m
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/base/Source/Additions/GSCategories.m,v
retrieving revision 1.9
diff -r1.9 GSCategories.m
608a609,742
> /**
>  * Returns a string formed by removing leading white space from the
>  * receiver.
>  */
> - (NSString*) stringByTrimmingLeadSpaces
> {
>     static SEL     caiSel = NULL;
>     unsigned       length = [self length];
>
>     if (length > 0)
>     {
>         unsigned   start = 0;
>         unichar    (*caiImp)(NSString*, SEL, unsigned int);
>
>         if(caiSel == NULL)
>             caiSel = @selector(characterAtIndex:);
>         caiImp = (unichar (*)())[self methodForSelector: caiSel];
> while (start < length && isspace((*caiImp)(self, caiSel, start)))
>         {
>             start++;
>         }
>         if (start > 0)
>         {
>             return [self substringFromIndex: start];
>         }
>     }
>     return self;
> }
>
> /**
>  * Returns a string formed by removing trailing white space from the
>  * receiver.
>  */
> - (NSString*) stringByTrimmingTailSpaces
> {
>     static SEL     caiSel = NULL;
>     unsigned       length = [self length];
>
>     if (length > 0)
>     {
>         unsigned   end = length;
>         unichar    (*caiImp)(NSString*, SEL, unsigned int);
>
>         if(caiSel == NULL)
>             caiSel = @selector(characterAtIndex:);
>         caiImp = (unichar (*)())[self methodForSelector: caiSel];
>         while (end > 0)
>         {
>             if (!isspace((*caiImp)(self, caiSel, end - 1)))
>             {
>                 break;
>             }
>             end--;
>         }
>         if (end < length)
>         {
>             return [self substringToIndex: end];
>         }
>     }
>     return self;
> }
>
> /**
>  * Returns a string formed by removing both leading and trailing
>  * white space from the receiver.
>  */
> - (NSString*) stringByTrimmingSpaces
> {
>     static SEL     caiSel = NULL;
>     unsigned       length = [self length];
>
>     if (length > 0)
>     {
>         unsigned   start = 0;
>         unsigned   end = length;
>         unichar    (*caiImp)(NSString*, SEL, unsigned int);
>
>         if(caiSel == NULL)
>             caiSel = @selector(characterAtIndex:);
>         caiImp = (unichar (*)())[self methodForSelector: caiSel];
> while (start < length && isspace((*caiImp)(self, caiSel, start)))
>         {
>             start++;
>         }
>         while (end > start)
>         {
>             if (!isspace((*caiImp)(self, caiSel, end - 1)))
>             {
>                 break;
>             }
>             end--;
>         }
>         if (start > 0 || end < length)
>         {
>             if (start < end)
>             {
>                 return [self substringWithRange:
>                     NSMakeRange(start, end - start)];
>             }
>             else
>             {
>                 return [NSString string];
>             }
>         }
>     }
>     return self;
> }
>
> /**
>  * Returns a string in which any (and all) occurrances of
>  * replace in the receiver have been replaced with by.
>  * Returns the receiver if replace
>  * does not occur within the receiver.  NB. an empty string is
>  * not considered to exist within the receiver.
>  */
> - (NSString*) stringByReplacingString: (NSString*)replace
>                                     withString: (NSString*)by
> {
>     NSRange range = [self rangeOfString: replace];
>
>     if (range.length > 0)
>     {
>         NSMutableString    *tmp = [self mutableCopy];
>         NSString           *str;
>
>         [tmp replaceString: replace withString: by];
>         str = AUTORELEASE([tmp copy]);
>         RELEASE(tmp);
>         return str;
>     }
>     else
>         return self;
> }
>
633a768,1075
> }
>
> /**
>  * Replaces all occurrances of the string replace with the string by
>  * in the receiver.<br />
>  * Has no effect if replace does not occur within the
>  * receiver.  NB. an empty string is not considered to exist within
>  * the receiver.<br />
> * Calls - replaceOccurrencesOfString:withString:options:range: passing > * zero for the options and a range from 0 with the length of the receiver.
>  */
> - (void) replaceString: (NSString*)replace
>                withString: (NSString*)by
> {
>     [self replaceOccurrencesOfString: replace
>                                    withString: by
>                                       options: 0
> range: NSMakeRange(0, [self length])];
> }
>
> /**
>  * Removes all leading white space from the receiver.
>  */
> - (void) trimLeadSpaces
> {
>     static SEL     caiSel = NULL;
>     unsigned       length = [self length];
>
>     if (length > 0)
>     {
>         unsigned   start = 0;
>         unichar    (*caiImp)(NSString*, SEL, unsigned int);
>
>         if(caiSel == NULL)
>             caiSel = @selector(characterAtIndex:);
>         caiImp = (unichar (*)())[self methodForSelector: caiSel];
> while (start < length && isspace((*caiImp)(self, caiSel, start)))
>         {
>             start++;
>         }
>         if (start > 0)
>         {
>             [self deleteCharactersInRange: NSMakeRange(0, start)];
>         }
>     }
> }
>
> /**
>  * Removes all trailing white space from the receiver.
>  */
> - (void) trimTailSpaces
> {
>     static SEL     caiSel = NULL;
>     unsigned       length = [self length];
>
>     if (length > 0)
>     {
>         unsigned   end = length;
>         unichar    (*caiImp)(NSString*, SEL, unsigned int);
>
>         if(caiSel == NULL)
>             caiSel = @selector(characterAtIndex:);
>         caiImp = (unichar (*)())[self methodForSelector: caiSel];
>         while (end > 0 && isspace((*caiImp)(self, caiSel, end - 1)))
>         {
>             end--;
>         }
>         if (end < length)
>         {
> [self deleteCharactersInRange: NSMakeRange(end, length - end)];
>         }
>     }
> }
>
> /**
>  * Removes all leading or trailing white space from the receiver.
>  */
> - (void) trimSpaces
> {
>     [self trimTailSpaces];
>     [self trimLeadSpaces];
> }
>
> @end
>
> @interface NSDistantObject (GSCategoriesRevealed)
> // This method is implemented in MacOS X 10.2.4, but is not public
> + (void) _enableLogging:(BOOL)flag;
> @end
>
> @implementation NSDistantObject (GSCategories)
>
> + (void) setDebug: (int)val
> {
>     if([self respondsToSelector:@selector(_enableLogging:)])
>         [self _enableLogging:!!val];
> }
>
> @end
>
> @implementation NSNumber(GSCategories)
>
> + (NSValue*) valueFromString: (NSString*)string
> {
>     /* FIXME: implement this better */
>     const char *str;
>
>     str = [string cString];
>     if (strchr(str, '.') >= 0 || strchr(str, 'e') >= 0
>         || strchr(str, 'E') >= 0)
>         return [NSNumber numberWithDouble: atof(str)];
>     else if (strchr(str, '-') >= 0)
>         return [NSNumber numberWithInt: atoi(str)];
>     else
>         return [NSNumber numberWithUnsignedInt: atoi(str)];
>     return [NSNumber numberWithInt: 0];
> }
>
> @end
>
> NSMutableDictionary *GSCurrentThreadDictionary()
> {
>     return [[NSThread currentThread] threadDictionary];
> }
>
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <netinet/in.h>
> #include <arpa/inet.h>
> #include <netdb.h>
> #include <unistd.h>
>
>
> @implementation NSFileHandle(GSCompatibility)
> // From GSFileHandle.m
>
> static BOOL
> getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
> {
>     const char             *proto = "tcp";
>     struct servent *sp;
>
>     if (pcl)
>     {
>         proto = [pcl lossyCString];
>     }
>     memset(sin, '\0', sizeof(*sin));
>     sin->sin_family = AF_INET;
>
>     /*
>      *     If we were given a hostname, we use any address for that host.
> * Otherwise we expect the given name to be an address unless it is
>      *     a null (any address).
>      */
>     if (name)
>     {
>         NSHost*            host = [NSHost hostWithName: name];
>
>         if (host != nil)
>         {
>             name = [host address];
>         }
> #ifndef    HAVE_INET_ATON
>         sin->sin_addr.s_addr = inet_addr([name lossyCString]);
>         if (sin->sin_addr.s_addr == INADDR_NONE)
> #else
>             if (inet_aton([name lossyCString], &sin->sin_addr) == 0)
> #endif
>             {
>                 return NO;
>             }
>     }
>         else
>         {
>             sin->sin_addr.s_addr = NSSwapHostIntToBig(INADDR_ANY);
>         }
>         if (svc == nil)
>         {
>             sin->sin_port = 0;
>             return YES;
>         }
>         else if ((sp = getservbyname([svc lossyCString], proto)) == 0)
>         {
>             const char*     ptr = [svc lossyCString];
>             int             val = atoi(ptr);
>
>             while (isdigit(*ptr))
>             {
>                 ptr++;
>             }
>             if (*ptr == '\0' && val <= 0xffff)
>             {
>                 unsigned short       v = val;
>
>                 sin->sin_port = NSSwapHostShortToBig(v);
>                 return YES;
>             }
>             else if (strcmp(ptr, "gdomap") == 0)
>             {
>                 unsigned short       v;
> #ifdef     GDOMAP_PORT_OVERRIDE
>                 v = GDOMAP_PORT_OVERRIDE;
> #else
>                 v = 538;   // IANA allocated port
> #endif
>                 sin->sin_port = NSSwapHostShortToBig(v);
>                 return YES;
>             }
>             else
>             {
>                 return NO;
>             }
>         }
>         else
>         {
>             sin->sin_port = sp->s_port;
>             return YES;
>         }
> }
>
> - (id) initAsServerAtAddress: (NSString*)a
>                            service: (NSString*)s
>                           protocol: (NSString*)p
> {
> #ifndef    BROKEN_SO_REUSEADDR
>     int    status = 1;
> #endif
>     int    net;
>     struct sockaddr_in     sin;
>     int    size = sizeof(sin);
>
>     if (getAddr(a, s, p, &sin) == NO)
>     {
>         RELEASE(self);
>         NSLog(@"bad address-service-protocol combination");
>         return  nil;
>     }
>
>     if ((net = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0)
>     {
>         NSLog(@"unable to create socket - %s", GSLastErrorStr(errno));
>         RELEASE(self);
>         return nil;
>     }
>
> #ifndef    BROKEN_SO_REUSEADDR
>     /*
> * Under decent systems, SO_REUSEADDR means that the port can be reused
>      * immediately that this process exits.  Under some it means
>      * that multiple processes can serve the same port simultaneously.
>      * We don't want that broken behavior!
>      */
> setsockopt(net, SOL_SOCKET, SO_REUSEADDR, (char *)&status, sizeof(status));
> #endif
>
>     if (bind(net, (struct sockaddr *)&sin, sizeof(sin)) < 0)
>     {
> NSLog(@"unable to bind to port %s:%d - %s", inet_ntoa(sin.sin_addr), > NSSwapBigShortToHost(sin.sin_port), GSLastErrorStr(errno));
>         (void) close(net);
>         RELEASE(self);
>         return nil;
>     }
>
>     if (listen(net, 5) < 0)
>     {
> NSLog(@"unable to listen on port - %s", GSLastErrorStr(errno));
>         (void) close(net);
>         RELEASE(self);
>         return nil;
>     }
>
>     if (getsockname(net, (struct sockaddr*)&sin, &size) < 0)
>     {
> NSLog(@"unable to get socket name - %s", GSLastErrorStr(errno));
>         (void) close(net);
>         RELEASE(self);
>         return nil;
>     }
>
>     self = [self initWithFileDescriptor: net closeOnDealloc: YES];
>
>     return self;
> }
>
> + (id) fileHandleAsServerAtAddress: (NSString*)address
>                            service: (NSString*)service
>                           protocol: (NSString*)protocol
> {
>     id     o = [self allocWithZone: NSDefaultMallocZone()];
>
>     return AUTORELEASE([o initAsServerAtAddress: address
>                                         service: service
>                                        protocol: protocol]);
> }
>
> - (NSString*) socketAddress
> {
>     struct sockaddr_in     sin;
>     int    size = sizeof(sin);
>
> if (getsockname([self fileDescriptor], (struct sockaddr*)&sin, &size) < 0)
>     {
> NSLog(@"unable to get socket name - %s", GSLastErrorStr(errno));
>         return nil;
>     }
>
> return [[[NSString alloc] initWithCString: (char*)inet_ntoa(sin.sin_addr)] autorelease];






reply via email to

[Prev in Thread] Current Thread [Next in Thread]