Added GCDWebServerChunkedResponse

This commit is contained in:
Pierre-Olivier Latour
2014-04-03 15:25:34 -07:00
parent 8116d88ec4
commit 6a4f74c2e4
2 changed files with 87 additions and 0 deletions

View File

@@ -55,6 +55,15 @@
}
@end
@interface GCDWebServerChunkedResponse () {
@private
GCDWebServerChunkBlock _block;
NSData* _chunk;
NSUInteger _offset;
BOOL _terminated;
}
@end
@implementation GCDWebServerResponse
@synthesize contentType=_type, contentLength=_length, statusCode=_status, cacheControlMaxAge=_maxAge, additionalHeaders=_headers;
@@ -378,3 +387,74 @@
}
@end
@implementation GCDWebServerChunkedResponse
+ (GCDWebServerChunkedResponse*)responseWithContentType:(NSString*)type chunkBlock:(GCDWebServerChunkBlock)block {
return ARC_AUTORELEASE([[[self class] alloc] initWithContentType:type chunkBlock:block]);
}
- (id)initWithContentType:(NSString*)type chunkBlock:(GCDWebServerChunkBlock)block {
if ((self = [super init])) {
_block = [block copy];
self.contentType = type;
[self setValue:@"chunked" forAdditionalHeader:@"Transfer-Encoding"];
}
return self;
}
- (BOOL)open {
DCHECK(_chunk == nil);
return YES;
}
- (NSInteger)read:(void*)buffer maxLength:(NSUInteger)length {
if (_offset >= _chunk.length) {
ARC_RELEASE(_chunk);
_chunk = nil;
}
if (_chunk == nil) {
if (_terminated) {
return 0;
}
NSData* data = _block();
if (data.length > 0) {
const char* hexString = [[NSString stringWithFormat:@"%lx", (unsigned long)data.length] UTF8String];
size_t hexLength = strlen(hexString);
_chunk = [[NSMutableData alloc] initWithLength:(hexLength + 2 + data.length + 2)];
char* ptr = (char*)_chunk.bytes;
bcopy(hexString, ptr, hexLength);
ptr += hexLength;
*ptr++ = '\r';
*ptr++ = '\n';
bcopy(data.bytes, ptr, data.length);
ptr += data.length;
*ptr++ = '\r';
*ptr = '\n';
} else {
_chunk = [[NSData alloc] initWithBytes:"0\r\n\r\n" length:5];
_terminated = YES;
}
_offset = 0;
}
NSInteger size = MIN(_chunk.length - _offset, length);
bcopy((char*)_chunk.bytes + _offset, buffer, size);
_offset += size;
return size;
}
- (BOOL)close {
ARC_RELEASE(_chunk);
_chunk = nil;
return YES;
}
- (void)dealloc {
DCHECK(_chunk == nil);
ARC_RELEASE(_chunk);
ARC_DEALLOC(super);
}
@end