From 78480e004ad55fa87c22ab839d3f62756e783f5a Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Latour Date: Wed, 8 Jan 2014 22:27:15 -0800 Subject: [PATCH] Added ARC support --- CGDWebServer/GCDWebServer.m | 57 +++++++------ CGDWebServer/GCDWebServerConnection.m | 58 +++++++------ CGDWebServer/GCDWebServerPrivate.h | 18 +++- CGDWebServer/GCDWebServerRequest.m | 114 +++++++++++++------------ CGDWebServer/GCDWebServerResponse.m | 48 +++++------ GCDWebServer.xcodeproj/project.pbxproj | 78 +++++++++++++++-- Mac/main.m | 2 + iOS/AppDelegate.m | 4 + 8 files changed, 246 insertions(+), 133 deletions(-) diff --git a/CGDWebServer/GCDWebServer.m b/CGDWebServer/GCDWebServer.m index db45a48b..f63fe622 100644 --- a/CGDWebServer/GCDWebServer.m +++ b/CGDWebServer/GCDWebServer.m @@ -50,9 +50,9 @@ if (extension.length) { mimeType = [_overrides objectForKey:extension]; if (mimeType == nil) { - CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)extension, NULL); + CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (ARC_BRIDGE CFStringRef)extension, NULL); if (uti) { - mimeType = [(id)UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType) autorelease]; + mimeType = ARC_BRIDGE_RELEASE(UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)); CFRelease(uti); } } @@ -61,8 +61,8 @@ } NSString* GCDWebServerUnescapeURLString(NSString* string) { - return [(id)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, (CFStringRef)string, CFSTR(""), - kCFStringEncodingUTF8) autorelease]; + return ARC_BRIDGE_RELEASE(CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, (CFStringRef)string, CFSTR(""), + kCFStringEncodingUTF8)); } NSDictionary* GCDWebServerParseURLEncodedForm(NSString* form) { @@ -90,7 +90,7 @@ } [scanner setScanLocation:([scanner scanLocation] + 1)]; } - [scanner release]; + ARC_RELEASE(scanner); return parameters; } @@ -105,17 +105,17 @@ @implementation GCDWebServerHandler - (id)initWithMatchBlock:(GCDWebServerMatchBlock)matchBlock processBlock:(GCDWebServerProcessBlock)processBlock { if ((self = [super init])) { - _matchBlock = Block_copy(matchBlock); - _processBlock = Block_copy(processBlock); + _matchBlock = [matchBlock copy]; + _processBlock = [processBlock copy]; } return self; } - (void)dealloc { - Block_release(_matchBlock); - Block_release(_processBlock); + ARC_RELEASE(_matchBlock); + ARC_RELEASE(_processBlock); - [super dealloc]; + ARC_DEALLOC(super); } @end @@ -140,16 +140,16 @@ - (void)dealloc { [self stop]; } - [_handlers release]; + ARC_RELEASE(_handlers); - [super dealloc]; + ARC_DEALLOC(super); } - (void)addHandlerWithMatchBlock:(GCDWebServerMatchBlock)matchBlock processBlock:(GCDWebServerProcessBlock)handlerBlock { DCHECK(_source == NULL); GCDWebServerHandler* handler = [[GCDWebServerHandler alloc] initWithMatchBlock:matchBlock processBlock:handlerBlock]; [_handlers insertObject:handler atIndex:0]; - [handler release]; + ARC_RELEASE(handler); } - (void)removeAllHandlers { @@ -212,8 +212,12 @@ - (BOOL)startWithPort:(NSUInteger)port bonjourName:(NSString*)name { NSData* data = [NSData dataWithBytes:&addr length:addrlen]; Class connectionClass = [[self class] connectionClass]; - GCDWebServerConnection* connection = [[connectionClass alloc] initWithServer:self address:data socket:socket]; - [connection release]; // Connection will automatically retain itself while opened + GCDWebServerConnection* connection = [[connectionClass alloc] initWithServer:self address:data socket:socket]; // Connection will automatically retain itself while opened +#if __has_feature(objc_arc) + [connection self]; // Prevent compiler from complaining about unused variable / useless statement +#else + [connection release]; +#endif } else { LOG_ERROR(@"Failed accepting socket (%i): %s", errno, strerror(errno)); } @@ -235,9 +239,9 @@ - (BOOL)startWithPort:(NSUInteger)port bonjourName:(NSString*)name { } if (name) { - _service = CFNetServiceCreate(kCFAllocatorDefault, CFSTR("local."), CFSTR("_http._tcp"), (CFStringRef)name, _port); + _service = CFNetServiceCreate(kCFAllocatorDefault, CFSTR("local."), CFSTR("_http._tcp"), (ARC_BRIDGE CFStringRef)name, _port); if (_service) { - CFNetServiceClientContext context = {0, self, NULL, NULL, NULL}; + CFNetServiceClientContext context = {0, (ARC_BRIDGE void*)self, NULL, NULL, NULL}; CFNetServiceSetClient(_service, _NetServiceClientCallBack, &context); CFNetServiceScheduleWithRunLoop(_service, CFRunLoopGetMain(), kCFRunLoopCommonModes); CFStreamError error = {0}; @@ -326,7 +330,7 @@ @implementation GCDWebServer (Handlers) - (void)addDefaultHandlerForMethod:(NSString*)method requestClass:(Class)class processBlock:(GCDWebServerProcessBlock)block { [self addHandlerWithMatchBlock:^GCDWebServerRequest *(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) { - return [[[class alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery] autorelease]; + return ARC_AUTORELEASE([[class alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery]); } processBlock:block]; } @@ -363,6 +367,11 @@ - (GCDWebServerResponse*)_responseWithContentsOfDirectory:(NSString*)path { - (void)addHandlerForBasePath:(NSString*)basePath localPath:(NSString*)localPath indexFilename:(NSString*)indexFilename cacheAge:(NSUInteger)cacheAge { if ([basePath hasPrefix:@"/"] && [basePath hasSuffix:@"/"]) { +#if __has_feature(objc_arc) + __unsafe_unretained GCDWebServer* server = self; +#else + GCDWebServer* server = self; +#endif [self addHandlerWithMatchBlock:^GCDWebServerRequest *(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) { if (![requestMethod isEqualToString:@"GET"]) { @@ -371,7 +380,7 @@ - (void)addHandlerForBasePath:(NSString*)basePath localPath:(NSString*)localPath if (![urlPath hasPrefix:basePath]) { return nil; } - return [[[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery] autorelease]; + return ARC_AUTORELEASE([[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery]); } processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { @@ -383,12 +392,12 @@ - (void)addHandlerForBasePath:(NSString*)basePath localPath:(NSString*)localPath if (indexFilename) { NSString* indexPath = [filePath stringByAppendingPathComponent:indexFilename]; if ([[NSFileManager defaultManager] fileExistsAtPath:indexPath isDirectory:&isDirectory] && !isDirectory) { - return [self _responseWithContentsOfFile:indexPath]; + return [server _responseWithContentsOfFile:indexPath]; } } - response = [self _responseWithContentsOfDirectory:filePath]; + response = [server _responseWithContentsOfDirectory:filePath]; } else { - response = [self _responseWithContentsOfFile:filePath]; + response = [server _responseWithContentsOfFile:filePath]; } } if (response) { @@ -414,7 +423,7 @@ - (void)addHandlerForMethod:(NSString*)method path:(NSString*)path requestClass: if ([urlPath caseInsensitiveCompare:path] != NSOrderedSame) { return nil; } - return [[[class alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery] autorelease]; + return ARC_AUTORELEASE([[class alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery]); } processBlock:block]; } else { @@ -433,7 +442,7 @@ - (void)addHandlerForMethod:(NSString*)method pathRegex:(NSString*)regex request if ([expression firstMatchInString:urlPath options:0 range:NSMakeRange(0, urlPath.length)] == nil) { return nil; } - return [[[class alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery] autorelease]; + return ARC_AUTORELEASE([[class alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery]); } processBlock:block]; } else { diff --git a/CGDWebServer/GCDWebServerConnection.m b/CGDWebServer/GCDWebServerConnection.m index 5d71d178..e93e9c51 100644 --- a/CGDWebServer/GCDWebServerConnection.m +++ b/CGDWebServer/GCDWebServerConnection.m @@ -84,7 +84,7 @@ - (void)_readDataWithCompletionBlock:(ReadDataCompletionBlock)block { return true; }); block(data); - [data release]; + ARC_RELEASE(data); } else { block(nil); } @@ -190,9 +190,15 @@ - (void)_writeBuffer:(dispatch_data_t)buffer withCompletionBlock:(WriteBufferCom } - (void)_writeData:(NSData*)data withCompletionBlock:(WriteDataCompletionBlock)block { +#if !__has_feature(objc_arc) [data retain]; +#endif dispatch_data_t buffer = dispatch_data_create(data.bytes, data.length, dispatch_get_current_queue(), ^{ +#if __has_feature(objc_arc) + [data self]; // Keeps ARC from releasing data too early +#else [data release]; +#endif }); [self _writeBuffer:buffer withCompletionBlock:block]; dispatch_release(buffer); @@ -201,7 +207,7 @@ - (void)_writeData:(NSData*)data withCompletionBlock:(WriteDataCompletionBlock)b - (void)_writeHeadersWithCompletionBlock:(WriteHeadersCompletionBlock)block { DCHECK(_responseMessage); CFDataRef message = CFHTTPMessageCopySerializedMessage(_responseMessage); - [self _writeData:(NSData*)message withCompletionBlock:block]; + [self _writeData:(ARC_BRIDGE NSData*)message withCompletionBlock:block]; CFRelease(message); } @@ -245,7 +251,11 @@ + (void)initialize { } if (_continueData == nil) { CFHTTPMessageRef message = CFHTTPMessageCreateResponse(kCFAllocatorDefault, 100, NULL, kCFHTTPVersion1_1); +#if __has_feature(objc_arc) + _continueData = CFBridgingRelease(CFHTTPMessageCopySerializedMessage(message)); +#else _continueData = (NSData*)CFHTTPMessageCopySerializedMessage(message); +#endif CFRelease(message); DCHECK(_continueData); } @@ -253,7 +263,7 @@ + (void)initialize { _dateFormatter = [[NSDateFormatter alloc] init]; _dateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"]; _dateFormatter.dateFormat = @"EEE',' dd MMM yyyy HH':'mm':'ss 'GMT'"; - _dateFormatter.locale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"] autorelease]; + _dateFormatter.locale = ARC_AUTORELEASE([[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]); DCHECK(_dateFormatter); } if (_formatterQueue == NULL) { @@ -265,10 +275,10 @@ + (void)initialize { - (void)_initializeResponseHeadersWithStatusCode:(NSInteger)statusCode { _responseMessage = CFHTTPMessageCreateResponse(kCFAllocatorDefault, statusCode, NULL, kCFHTTPVersion1_1); CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Connection"), CFSTR("Close")); - CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Server"), (CFStringRef)[[_server class] serverName]); + CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Server"), (ARC_BRIDGE CFStringRef)[[_server class] serverName]); dispatch_sync(_formatterQueue, ^{ NSString* date = [_dateFormatter stringFromDate:[NSDate date]]; - CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Date"), (CFStringRef)date); + CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Date"), (ARC_BRIDGE CFStringRef)date); }); } @@ -288,23 +298,23 @@ - (void)_processRequest { GCDWebServerResponse* response = [self processRequest:_request withBlock:_handler.processBlock]; if (![response hasBody] || [response open]) { - _response = [response retain]; + _response = ARC_RETAIN(response); } if (_response) { [self _initializeResponseHeadersWithStatusCode:_response.statusCode]; NSUInteger maxAge = _response.cacheControlMaxAge; if (maxAge > 0) { - CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Cache-Control"), (CFStringRef)[NSString stringWithFormat:@"max-age=%i, public", (int)maxAge]); + CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Cache-Control"), (ARC_BRIDGE CFStringRef)[NSString stringWithFormat:@"max-age=%i, public", (int)maxAge]); } else { CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Cache-Control"), CFSTR("no-cache")); } [_response.additionalHeaders enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL* stop) { - CFHTTPMessageSetHeaderFieldValue(_responseMessage, (CFStringRef)key, (CFStringRef)obj); + CFHTTPMessageSetHeaderFieldValue(_responseMessage, (ARC_BRIDGE CFStringRef)key, (ARC_BRIDGE CFStringRef)obj); }]; if ([_response hasBody]) { - CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Content-Type"), (CFStringRef)_response.contentType); - CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Content-Length"), (CFStringRef)[NSString stringWithFormat:@"%i", (int)_response.contentLength]); + CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Content-Type"), (ARC_BRIDGE CFStringRef)_response.contentType); + CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Content-Length"), (ARC_BRIDGE CFStringRef)[NSString stringWithFormat:@"%i", (int)_response.contentLength]); } [self _writeHeadersWithCompletionBlock:^(BOOL success) { @@ -373,22 +383,22 @@ - (void)_readRequestHeaders { [self _readHeadersWithCompletionBlock:^(NSData* extraData) { if (extraData) { - NSString* requestMethod = [[(id)CFHTTPMessageCopyRequestMethod(_requestMessage) autorelease] uppercaseString]; + NSString* requestMethod = [ARC_BRIDGE_RELEASE(CFHTTPMessageCopyRequestMethod(_requestMessage)) uppercaseString]; DCHECK(requestMethod); - NSURL* requestURL = [(id)CFHTTPMessageCopyRequestURL(_requestMessage) autorelease]; + NSURL* requestURL = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyRequestURL(_requestMessage)); DCHECK(requestURL); - NSString* requestPath = GCDWebServerUnescapeURLString([(id)CFURLCopyPath((CFURLRef)requestURL) autorelease]); // Don't use -[NSURL path] which strips the ending slash + NSString* requestPath = GCDWebServerUnescapeURLString(ARC_BRIDGE_RELEASE(CFURLCopyPath((CFURLRef)requestURL))); // Don't use -[NSURL path] which strips the ending slash DCHECK(requestPath); NSDictionary* requestQuery = nil; - NSString* queryString = [(id)CFURLCopyQueryString((CFURLRef)requestURL, NULL) autorelease]; // Don't use -[NSURL query] to make sure query is not unescaped; + NSString* queryString = ARC_BRIDGE_RELEASE(CFURLCopyQueryString((CFURLRef)requestURL, NULL)); // Don't use -[NSURL query] to make sure query is not unescaped; if (queryString.length) { requestQuery = GCDWebServerParseURLEncodedForm(queryString); DCHECK(requestQuery); } - NSDictionary* requestHeaders = [(id)CFHTTPMessageCopyAllHeaderFields(_requestMessage) autorelease]; + NSDictionary* requestHeaders = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyAllHeaderFields(_requestMessage)); DCHECK(requestHeaders); for (_handler in _server.handlers) { - _request = [_handler.matchBlock(requestMethod, requestURL, requestHeaders, requestPath, requestQuery) retain]; + _request = ARC_RETAIN(_handler.matchBlock(requestMethod, requestURL, requestHeaders, requestPath, requestQuery)); if (_request) { break; } @@ -396,7 +406,7 @@ - (void)_readRequestHeaders { if (_request) { if (_request.hasBody) { if (extraData.length <= _request.contentLength) { - NSString* expectHeader = [(id)CFHTTPMessageCopyHeaderFieldValue(_requestMessage, CFSTR("Expect")) autorelease]; + NSString* expectHeader = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyHeaderFieldValue(_requestMessage, CFSTR("Expect"))); if (expectHeader) { if ([expectHeader caseInsensitiveCompare:@"100-continue"] == NSOrderedSame) { [self _writeData:_continueData withCompletionBlock:^(BOOL success) { @@ -432,8 +442,8 @@ - (void)_readRequestHeaders { - (id)initWithServer:(GCDWebServer*)server address:(NSData*)address socket:(CFSocketNativeHandle)socket { if ((self = [super init])) { - _server = [server retain]; - _address = [address retain]; + _server = ARC_RETAIN(server); + _address = ARC_RETAIN(address); _socket = socket; [self open]; @@ -444,20 +454,20 @@ - (id)initWithServer:(GCDWebServer*)server address:(NSData*)address socket:(CFSo - (void)dealloc { [self close]; - [_server release]; - [_address release]; + ARC_RELEASE(_server); + ARC_RELEASE(_address); if (_requestMessage) { CFRelease(_requestMessage); } - [_request release]; + ARC_RELEASE(_request); if (_responseMessage) { CFRelease(_responseMessage); } - [_response release]; + ARC_RELEASE(_response); - [super dealloc]; + ARC_DEALLOC(super); } @end diff --git a/CGDWebServer/GCDWebServerPrivate.h b/CGDWebServer/GCDWebServerPrivate.h index f20f2d9f..86605648 100644 --- a/CGDWebServer/GCDWebServerPrivate.h +++ b/CGDWebServer/GCDWebServerPrivate.h @@ -25,6 +25,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if __has_feature(objc_arc) +#define ARC_BRIDGE __bridge +#define ARC_BRIDGE_RELEASE(__OBJECT__) CFBridgingRelease(__OBJECT__) +#define ARC_RETAIN(__OBJECT__) __OBJECT__ +#define ARC_RELEASE(__OBJECT__) +#define ARC_AUTORELEASE(__OBJECT__) __OBJECT__ +#define ARC_DEALLOC(__OBJECT__) +#else +#define ARC_BRIDGE +#define ARC_BRIDGE_RELEASE(__OBJECT__) [(id)__OBJECT__ autorelease] +#define ARC_RETAIN(__OBJECT__) [__OBJECT__ retain] +#define ARC_RELEASE(__OBJECT__) [__OBJECT__ release] +#define ARC_AUTORELEASE(__OBJECT__) [__OBJECT__ autorelease] +#define ARC_DEALLOC(__OBJECT__) [__OBJECT__ dealloc] +#endif + #import "GCDWebServerConnection.h" #ifdef __GCDWEBSERVER_LOGGING_HEADER__ @@ -47,7 +63,7 @@ static inline void __LogMessage(long level, NSString* format, ...) { NSString* message = [[NSString alloc] initWithFormat:format arguments:arguments]; va_end(arguments); printf("[%s] %s\n", levelNames[level], [message UTF8String]); - [message release]; + ARC_RELEASE(message); } } diff --git a/CGDWebServer/GCDWebServerRequest.m b/CGDWebServer/GCDWebServerRequest.m index b57f93e4..00ce5f93 100644 --- a/CGDWebServer/GCDWebServerRequest.m +++ b/CGDWebServer/GCDWebServerRequest.m @@ -54,7 +54,7 @@ [scanner scanUpToCharactersFromSet:[NSCharacterSet whitespaceCharacterSet] intoString:&value]; } } - [scanner release]; + ARC_RELEASE(scanner); } return value; } @@ -75,16 +75,16 @@ @implementation GCDWebServerRequest : NSObject - (id)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query { if ((self = [super init])) { _method = [method copy]; - _url = [url retain]; - _headers = [headers retain]; + _url = ARC_RETAIN(url); + _headers = ARC_RETAIN(headers); _path = [path copy]; - _query = [query retain]; + _query = ARC_RETAIN(query); - _type = [[_headers objectForKey:@"Content-Type"] retain]; + _type = ARC_RETAIN([_headers objectForKey:@"Content-Type"]); NSInteger length = [[_headers objectForKey:@"Content-Length"] integerValue]; if (length < 0) { DNOT_REACHED(); - [self release]; + ARC_RELEASE(self); return nil; } _length = length; @@ -97,14 +97,14 @@ - (id)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)he } - (void)dealloc { - [_method release]; - [_url release]; - [_headers release]; - [_path release]; - [_query release]; - [_type release]; + ARC_RELEASE(_method); + ARC_RELEASE(_url); + ARC_RELEASE(_headers); + ARC_RELEASE(_path); + ARC_RELEASE(_query); + ARC_RELEASE(_type); - [super dealloc]; + ARC_DEALLOC(super); } - (BOOL)hasBody { @@ -138,9 +138,9 @@ @implementation GCDWebServerDataRequest - (void)dealloc { DCHECK(_data != nil); - [_data release]; + ARC_RELEASE(_data); - [super dealloc]; + ARC_DEALLOC(super); } - (BOOL)open { @@ -168,7 +168,7 @@ @implementation GCDWebServerFileRequest - (id)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query { if ((self = [super initWithMethod:method url:url headers:headers path:path query:query])) { - _filePath = [[NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]] retain]; + _filePath = ARC_RETAIN([NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]); } return self; } @@ -176,9 +176,9 @@ - (id)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)he - (void)dealloc { DCHECK(_file < 0); unlink([_filePath fileSystemRepresentation]); - [_filePath release]; + ARC_RELEASE(_filePath); - [super dealloc]; + ARC_DEALLOC(super); } - (BOOL)open { @@ -210,9 +210,9 @@ + (NSString*)mimeType { } - (void)dealloc { - [_arguments release]; + ARC_RELEASE(_arguments); - [super dealloc]; + ARC_DEALLOC(super); } - (BOOL)close { @@ -222,8 +222,8 @@ - (BOOL)close { NSString* charset = _ExtractHeaderParameter(self.contentType, @"charset"); NSString* string = [[NSString alloc] initWithData:self.data encoding:_StringEncodingFromCharset(charset)]; - _arguments = [GCDWebServerParseURLEncodedForm(string) retain]; - [string release]; + _arguments = ARC_RETAIN(GCDWebServerParseURLEncodedForm(string)); + ARC_RELEASE(string); return (_arguments ? YES : NO); } @@ -239,7 +239,7 @@ - (id)initWithContentType:(NSString*)contentType { _contentType = [contentType copy]; NSArray* components = [_contentType componentsSeparatedByString:@";"]; if (components.count) { - _mimeType = [[[components objectAtIndex:0] lowercaseString] retain]; + _mimeType = ARC_RETAIN([[components objectAtIndex:0] lowercaseString]); } if (_mimeType == nil) { _mimeType = @"text/plain"; @@ -249,10 +249,10 @@ - (id)initWithContentType:(NSString*)contentType { } - (void)dealloc { - [_contentType release]; - [_mimeType release]; + ARC_RELEASE(_contentType); + ARC_RELEASE(_mimeType); - [super dealloc]; + ARC_DEALLOC(super); } @end @@ -263,7 +263,7 @@ @implementation GCDWebServerMultiPartArgument - (id)initWithContentType:(NSString*)contentType data:(NSData*)data { if ((self = [super initWithContentType:contentType])) { - _data = [data retain]; + _data = ARC_RETAIN(data); if ([self.mimeType hasPrefix:@"text/"]) { NSString* charset = _ExtractHeaderParameter(self.contentType, @"charset"); @@ -274,10 +274,10 @@ - (id)initWithContentType:(NSString*)contentType data:(NSData*)data { } - (void)dealloc { - [_data release]; - [_string release]; + ARC_RELEASE(_data); + ARC_RELEASE(_string); - [super dealloc]; + ARC_DEALLOC(super); } - (NSString*)description { @@ -301,10 +301,10 @@ - (id)initWithContentType:(NSString*)contentType fileName:(NSString*)fileName te - (void)dealloc { unlink([_temporaryPath fileSystemRepresentation]); - [_fileName release]; - [_temporaryPath release]; + ARC_RELEASE(_fileName); + ARC_RELEASE(_temporaryPath); - [super dealloc]; + ARC_DEALLOC(super); } - (NSString*)description { @@ -340,11 +340,12 @@ - (id)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)he if ((self = [super initWithMethod:method url:url headers:headers path:path query:query])) { NSString* boundary = _ExtractHeaderParameter(self.contentType, @"boundary"); if (boundary) { - _boundary = [[[NSString stringWithFormat:@"--%@", boundary] dataUsingEncoding:NSASCIIStringEncoding] retain]; + NSData* data = [[NSString stringWithFormat:@"--%@", boundary] dataUsingEncoding:NSASCIIStringEncoding]; + _boundary = ARC_RETAIN(data); } if (_boundary == nil) { DNOT_REACHED(); - [self release]; + ARC_RELEASE(self); return nil; } @@ -369,13 +370,13 @@ - (BOOL)_parseData { NSRange range = [_parserData rangeOfData:_newlinesData options:0 range:NSMakeRange(0, _parserData.length)]; if (range.location != NSNotFound) { - [_controlName release]; + ARC_RELEASE(_controlName); _controlName = nil; - [_fileName release]; + ARC_RELEASE(_fileName); _fileName = nil; - [_contentType release]; + ARC_RELEASE(_contentType); _contentType = nil; - [_tmpPath release]; + ARC_RELEASE(_tmpPath); _tmpPath = nil; CFHTTPMessageRef message = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, true); const char* temp = "GET / HTTP/1.0\r\n"; @@ -384,7 +385,7 @@ - (BOOL)_parseData { if (CFHTTPMessageIsHeaderComplete(message)) { NSString* controlName = nil; NSString* fileName = nil; - NSDictionary* headers = [(id)CFHTTPMessageCopyAllHeaderFields(message) autorelease]; + NSDictionary* headers = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyAllHeaderFields(message)); NSString* contentDisposition = [headers objectForKey:@"Content-Disposition"]; if ([[contentDisposition lowercaseString] hasPrefix:@"form-data;"]) { controlName = _ExtractHeaderParameter(contentDisposition, @"name"); @@ -392,7 +393,7 @@ - (BOOL)_parseData { } _controlName = [controlName copy]; _fileName = [fileName copy]; - _contentType = [[headers objectForKey:@"Content-Type"] retain]; + _contentType = ARC_RETAIN([headers objectForKey:@"Content-Type"]); } CFRelease(message); if (_controlName) { @@ -434,7 +435,7 @@ - (BOOL)_parseData { _tmpFile = 0; GCDWebServerMultiPartFile* file = [[GCDWebServerMultiPartFile alloc] initWithContentType:_contentType fileName:_fileName temporaryPath:_tmpPath]; [_files setObject:file forKey:_controlName]; - [file release]; + ARC_RELEASE(file); } else { DNOT_REACHED(); success = NO; @@ -443,14 +444,14 @@ - (BOOL)_parseData { DNOT_REACHED(); success = NO; } - [_tmpPath release]; + ARC_RELEASE(_tmpPath); _tmpPath = nil; } else { NSData* data = [[NSData alloc] initWithBytesNoCopy:(void*)dataBytes length:dataLength freeWhenDone:NO]; GCDWebServerMultiPartArgument* argument = [[GCDWebServerMultiPartArgument alloc] initWithContentType:_contentType data:data]; [_arguments setObject:argument forKey:_controlName]; - [argument release]; - [data release]; + ARC_RELEASE(argument); + ARC_RELEASE(data); } } @@ -487,26 +488,31 @@ - (NSInteger)write:(const void*)buffer maxLength:(NSUInteger)length { - (BOOL)close { DCHECK(_parserData != nil); - [_parserData release]; + ARC_RELEASE(_parserData); _parserData = nil; - [_controlName release]; - [_fileName release]; - [_contentType release]; + ARC_RELEASE(_controlName); + _controlName = nil; + ARC_RELEASE(_fileName); + _fileName = nil; + ARC_RELEASE(_contentType); + _contentType = nil; if (_tmpFile > 0) { close(_tmpFile); unlink([_tmpPath fileSystemRepresentation]); + _tmpFile = 0; } - [_tmpPath release]; + ARC_RELEASE(_tmpPath); + _tmpPath = nil; return (_parserState == kParserState_End ? YES : NO); } - (void)dealloc { DCHECK(_parserData == nil); - [_arguments release]; - [_files release]; - [_boundary release]; + ARC_RELEASE(_arguments); + ARC_RELEASE(_files); + ARC_RELEASE(_boundary); - [super dealloc]; + ARC_DEALLOC(super); } @end diff --git a/CGDWebServer/GCDWebServerResponse.m b/CGDWebServer/GCDWebServerResponse.m index 069fd304..a820ad30 100644 --- a/CGDWebServer/GCDWebServerResponse.m +++ b/CGDWebServer/GCDWebServerResponse.m @@ -33,8 +33,8 @@ @implementation GCDWebServerResponse @synthesize contentType=_type, contentLength=_length, statusCode=_status, cacheControlMaxAge=_maxAge, additionalHeaders=_headers; -+(GCDWebServerResponse*) response { - return [[[[self class] alloc] init] autorelease]; ++ (GCDWebServerResponse*)response { + return ARC_AUTORELEASE([[[self class] alloc] init]); } - (id)init { @@ -57,10 +57,10 @@ - (id)initWithContentType:(NSString*)type contentLength:(NSUInteger)length { } - (void)dealloc { - [_type release]; - [_headers release]; + ARC_RELEASE(_type); + ARC_RELEASE(_headers); - [super dealloc]; + ARC_DEALLOC(super); } - (void)setValue:(NSString*)value forAdditionalHeader:(NSString*)header { @@ -95,11 +95,11 @@ - (BOOL)close { @implementation GCDWebServerResponse (Extensions) + (GCDWebServerResponse*)responseWithStatusCode:(NSInteger)statusCode { - return [[[self alloc] initWithStatusCode:statusCode] autorelease]; + return ARC_AUTORELEASE([[self alloc] initWithStatusCode:statusCode]); } + (GCDWebServerResponse*)responseWithRedirect:(NSURL*)location permanent:(BOOL)permanent { - return [[[self alloc] initWithRedirect:location permanent:permanent] autorelease]; + return ARC_AUTORELEASE([[self alloc] initWithRedirect:location permanent:permanent]); } - (id)initWithStatusCode:(NSInteger)statusCode { @@ -122,18 +122,18 @@ - (id)initWithRedirect:(NSURL*)location permanent:(BOOL)permanent { @implementation GCDWebServerDataResponse + (GCDWebServerDataResponse*)responseWithData:(NSData*)data contentType:(NSString*)type { - return [[[[self class] alloc] initWithData:data contentType:type] autorelease]; + return ARC_AUTORELEASE([[[self class] alloc] initWithData:data contentType:type]); } - (id)initWithData:(NSData*)data contentType:(NSString*)type { if (data == nil) { DNOT_REACHED(); - [self release]; + ARC_RELEASE(self); return nil; } if ((self = [super initWithContentType:type contentLength:data.length])) { - _data = [data retain]; + _data = ARC_RETAIN(data); _offset = -1; } return self; @@ -141,9 +141,9 @@ - (id)initWithData:(NSData*)data contentType:(NSString*)type { - (void)dealloc { DCHECK(_offset < 0); - [_data release]; + ARC_RELEASE(_data); - [super dealloc]; + ARC_DEALLOC(super); } - (BOOL)open { @@ -174,22 +174,22 @@ - (BOOL)close { @implementation GCDWebServerDataResponse (Extensions) + (GCDWebServerDataResponse*)responseWithText:(NSString*)text { - return [[[self alloc] initWithText:text] autorelease]; + return ARC_AUTORELEASE([[self alloc] initWithText:text]); } + (GCDWebServerDataResponse*)responseWithHTML:(NSString*)html { - return [[[self alloc] initWithHTML:html] autorelease]; + return ARC_AUTORELEASE([[self alloc] initWithHTML:html]); } + (GCDWebServerDataResponse*)responseWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables { - return [[[self alloc] initWithHTMLTemplate:path variables:variables] autorelease]; + return ARC_AUTORELEASE([[self alloc] initWithHTMLTemplate:path variables:variables]); } - (id)initWithText:(NSString*)text { NSData* data = [text dataUsingEncoding:NSUTF8StringEncoding]; if (data == nil) { DNOT_REACHED(); - [self release]; + ARC_RELEASE(self); return nil; } return [self initWithData:data contentType:@"text/plain; charset=utf-8"]; @@ -199,7 +199,7 @@ - (id)initWithHTML:(NSString*)html { NSData* data = [html dataUsingEncoding:NSUTF8StringEncoding]; if (data == nil) { DNOT_REACHED(); - [self release]; + ARC_RELEASE(self); return nil; } return [self initWithData:data contentType:@"text/html; charset=utf-8"]; @@ -211,7 +211,7 @@ - (id)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables { [html replaceOccurrencesOfString:[NSString stringWithFormat:@"%%%@%%", key] withString:value options:0 range:NSMakeRange(0, html.length)]; }]; id response = [self initWithHTML:html]; - [html release]; + ARC_RELEASE(html); return response; } @@ -220,11 +220,11 @@ - (id)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables { @implementation GCDWebServerFileResponse + (GCDWebServerFileResponse*)responseWithFile:(NSString*)path { - return [[[[self class] alloc] initWithFile:path] autorelease]; + return ARC_AUTORELEASE([[[self class] alloc] initWithFile:path]); } + (GCDWebServerFileResponse*)responseWithFile:(NSString*)path isAttachment:(BOOL)attachment { - return [[[[self class] alloc] initWithFile:path isAttachment:attachment] autorelease]; + return ARC_AUTORELEASE([[[self class] alloc] initWithFile:path isAttachment:attachment]); } - (id)initWithFile:(NSString*)path { @@ -235,7 +235,7 @@ - (id)initWithFile:(NSString*)path isAttachment:(BOOL)attachment { struct stat info; if (lstat([path fileSystemRepresentation], &info) || !(info.st_mode & S_IFREG)) { DNOT_REACHED(); - [self release]; + ARC_RELEASE(self); return nil; } NSString* type = GCDWebServerGetMimeTypeForExtension([path pathExtension]); @@ -250,7 +250,7 @@ - (id)initWithFile:(NSString*)path isAttachment:(BOOL)attachment { NSString* fileName = data ? [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding] : nil; if (fileName) { [self setValue:[NSString stringWithFormat:@"attachment; filename=\"%@\"", fileName] forAdditionalHeader:@"Content-Disposition"]; - [fileName release]; + ARC_RELEASE(fileName); } else { DNOT_REACHED(); } @@ -261,9 +261,9 @@ - (id)initWithFile:(NSString*)path isAttachment:(BOOL)attachment { - (void)dealloc { DCHECK(_file <= 0); - [_path release]; + ARC_RELEASE(_path); - [super dealloc]; + ARC_DEALLOC(super); } - (BOOL)open { diff --git a/GCDWebServer.xcodeproj/project.pbxproj b/GCDWebServer.xcodeproj/project.pbxproj index 21032ed0..aa682355 100644 --- a/GCDWebServer.xcodeproj/project.pbxproj +++ b/GCDWebServer.xcodeproj/project.pbxproj @@ -6,6 +6,21 @@ objectVersion = 46; objects = { +/* Begin PBXAggregateTarget section */ + E274F876187E77D8009E0582 /* Build All */ = { + isa = PBXAggregateTarget; + buildConfigurationList = E274F879187E77D8009E0582 /* Build configuration list for PBXAggregateTarget "Build All" */; + buildPhases = ( + ); + dependencies = ( + E274F87D187E77E5009E0582 /* PBXTargetDependency */, + E274F87B187E77E3009E0582 /* PBXTargetDependency */, + ); + name = "Build All"; + productName = "Build All"; + }; +/* End PBXAggregateTarget section */ + /* Begin PBXBuildFile section */ E208D149167B76B700500836 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E208D148167B76B700500836 /* CFNetwork.framework */; }; E208D1B3167BB17E00500836 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E208D1B2167BB17E00500836 /* CoreServices.framework */; }; @@ -25,6 +40,23 @@ E221129D1690B7BA0048D2B2 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E221129C1690B7BA0048D2B2 /* MobileCoreServices.framework */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + E274F87A187E77E3009E0582 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8DD76FA90486AB0100D96B5E; + remoteInfo = "GCDWebServer (Mac)"; + }; + E274F87C187E77E5009E0582 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = E22112591690B4DE0048D2B2; + remoteInfo = "GCDWebServer (iOS)"; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXFileReference section */ 8DD76FB20486AB0100D96B5E /* GCDWebServer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = GCDWebServer; sourceTree = BUILT_PRODUCTS_DIR; }; E208D148167B76B700500836 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; @@ -207,6 +239,7 @@ projectDirPath = ""; projectRoot = ""; targets = ( + E274F876187E77D8009E0582 /* Build All */, 8DD76FA90486AB0100D96B5E /* GCDWebServer (Mac) */, E22112591690B4DE0048D2B2 /* GCDWebServer (iOS) */, ); @@ -241,11 +274,23 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + E274F87B187E77E3009E0582 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8DD76FA90486AB0100D96B5E /* GCDWebServer (Mac) */; + targetProxy = E274F87A187E77E3009E0582 /* PBXContainerItemProxy */; + }; + E274F87D187E77E5009E0582 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = E22112591690B4DE0048D2B2 /* GCDWebServer (iOS) */; + targetProxy = E274F87C187E77E5009E0582 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin XCBuildConfiguration section */ 1DEB928608733DD80010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; MACOSX_DEPLOYMENT_TARGET = 10.7; PRODUCT_NAME = GCDWebServer; SDKROOT = macosx; @@ -255,7 +300,6 @@ 1DEB928708733DD80010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; MACOSX_DEPLOYMENT_TARGET = 10.7; PRODUCT_NAME = GCDWebServer; SDKROOT = macosx; @@ -265,6 +309,7 @@ 1DEB928A08733DD80010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_OBJC_ARC = YES; GCC_OPTIMIZATION_LEVEL = 0; ONLY_ACTIVE_ARCH = YES; WARNING_CFLAGS = "-Wall"; @@ -274,10 +319,8 @@ 1DEB928B08733DD80010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - GCC_PREPROCESSOR_DEFINITIONS = ( - NDEBUG, - NS_BLOCK_ASSERTIONS, - ); + CLANG_ENABLE_OBJC_ARC = YES; + GCC_PREPROCESSOR_DEFINITIONS = NDEBUG; WARNING_CFLAGS = "-Wall"; }; name = Release; @@ -308,6 +351,20 @@ }; name = Release; }; + E274F877187E77D8009E0582 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + E274F878187E77D8009E0582 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -338,6 +395,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + E274F879187E77D8009E0582 /* Build configuration list for PBXAggregateTarget "Build All" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E274F877187E77D8009E0582 /* Debug */, + E274F878187E77D8009E0582 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; diff --git a/Mac/main.m b/Mac/main.m index 49e7f58a..a84ad336 100644 --- a/Mac/main.m +++ b/Mac/main.m @@ -81,7 +81,9 @@ int main(int argc, const char* argv[]) { } success = [webServer runWithPort:8080]; +#if !__has_feature(objc_arc) [webServer release]; +#endif } return success ? 0 : -1; } diff --git a/iOS/AppDelegate.m b/iOS/AppDelegate.m index 651e4290..c05822cb 100644 --- a/iOS/AppDelegate.m +++ b/iOS/AppDelegate.m @@ -29,12 +29,16 @@ @implementation AppDelegate +#if !__has_feature(objc_arc) + - (void)dealloc { [_window release]; [super dealloc]; } +#endif + - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { _window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; _window.backgroundColor = [UIColor whiteColor];