PageRenderTime 66ms CodeModel.GetById 19ms app.highlight 43ms RepoModel.GetById 1ms app.codeStats 0ms

/Source/externals/GData/Source/HTTPFetcher/GTMGatherInputStream.m

http://google-email-uploader-mac.googlecode.com/
Objective C | 197 lines | 121 code | 46 blank | 30 comment | 12 complexity | cbaad9311b824ba582771db71829ecf5 MD5 | raw file
  1/* Copyright (c) 2010 Google Inc.
  2 *
  3 * Licensed under the Apache License, Version 2.0 (the "License");
  4 * you may not use this file except in compliance with the License.
  5 * You may obtain a copy of the License at
  6 *
  7 *     http://www.apache.org/licenses/LICENSE-2.0
  8 *
  9 * Unless required by applicable law or agreed to in writing, software
 10 * distributed under the License is distributed on an "AS IS" BASIS,
 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 * See the License for the specific language governing permissions and
 13 * limitations under the License.
 14 */
 15
 16#import "GTMGatherInputStream.h"
 17
 18@implementation GTMGatherInputStream
 19
 20+ (NSInputStream *)streamWithArray:(NSArray *)dataArray {
 21  return [[[self alloc] initWithArray:dataArray] autorelease];
 22}
 23
 24- (id)initWithArray:(NSArray *)dataArray {
 25  self = [super init];
 26  if (self) {
 27    dataArray_ = [dataArray retain];
 28    arrayIndex_ = 0;
 29    dataOffset_ = 0;
 30
 31    [self setDelegate:self];  // An NSStream's default delegate should be self.
 32
 33    // We use a dummy input stream to handle all the various undocumented
 34    // messages the system sends to an input stream.
 35    //
 36    // Contrary to documentation, inputStreamWithData neither copies nor
 37    // retains the data in Mac OS X 10.4, so we must retain it.
 38    // (Radar 5167591)
 39
 40    dummyData_ = [[NSData alloc] initWithBytes:"x" length:1];
 41    dummyStream_ = [[NSInputStream alloc] initWithData:dummyData_];
 42  }
 43  return self;
 44}
 45
 46- (void)dealloc {
 47  [dataArray_ release];
 48  [dummyStream_ release];
 49  [dummyData_ release];
 50
 51  [super dealloc];
 52}
 53
 54- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len {
 55
 56  NSInteger bytesRead = 0;
 57  NSUInteger bytesRemaining = len;
 58
 59  // read bytes from the currently-indexed array
 60  while ((bytesRemaining > 0) && (arrayIndex_ < [dataArray_ count])) {
 61
 62    NSData* data = [dataArray_ objectAtIndex:arrayIndex_];
 63
 64    NSUInteger dataLen = [data length];
 65    NSUInteger dataBytesLeft = dataLen - (NSUInteger)dataOffset_;
 66
 67    NSUInteger bytesToCopy = MIN(bytesRemaining, dataBytesLeft);
 68    NSRange range = NSMakeRange((NSUInteger) dataOffset_, bytesToCopy);
 69
 70    [data getBytes:(buffer + bytesRead) range:range];
 71
 72    bytesRead += bytesToCopy;
 73    dataOffset_ += bytesToCopy;
 74    bytesRemaining -= bytesToCopy;
 75
 76    if (dataOffset_ == (long long)dataLen) {
 77      dataOffset_ = 0;
 78      arrayIndex_++;
 79    }
 80  }
 81
 82  if (bytesRead == 0) {
 83    // We are at the end our our stream, so we read all of the data on our
 84    // dummy input stream to make sure it is in the "fully read" state.
 85    uint8_t leftOverBytes[2];
 86    (void) [dummyStream_ read:leftOverBytes maxLength:sizeof(leftOverBytes)];
 87  }
 88
 89  return bytesRead;
 90}
 91
 92- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len {
 93  return NO;  // We don't support this style of reading.
 94}
 95
 96- (BOOL)hasBytesAvailable {
 97  // if we return no, the read never finishes, even if we've already
 98  // delivered all the bytes
 99  return YES;
100}
101
102#pragma mark -
103
104// Pass other expected messages on to the dummy input stream
105
106- (void)open {
107  [dummyStream_ open];
108}
109
110- (void)close {
111  [dummyStream_ close];
112
113  // 10.4's NSURLConnection tends to retain streams needlessly,
114  // so we'll free up the data array right away
115  [dataArray_ release];
116  dataArray_ = nil;
117}
118
119- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
120  if (delegate_ != self) {
121    [delegate_ stream:self handleEvent:streamEvent];
122  }
123}
124
125- (id)delegate {
126  return delegate_;
127}
128
129- (void)setDelegate:(id)delegate {
130  if (delegate == nil) {
131    delegate_ = self;
132    [dummyStream_ setDelegate:nil];
133  } else {
134    delegate_ = delegate;
135    [dummyStream_ setDelegate:self];
136  }
137}
138
139- (id)propertyForKey:(NSString *)key {
140  return [dummyStream_ propertyForKey:key];
141}
142
143- (BOOL)setProperty:(id)property forKey:(NSString *)key {
144  return [dummyStream_ setProperty:property forKey:key];
145}
146
147- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode {
148  [dummyStream_ scheduleInRunLoop:aRunLoop forMode:mode];
149}
150
151- (void)removeFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode {
152  [dummyStream_ removeFromRunLoop:aRunLoop forMode:mode];
153}
154
155- (NSStreamStatus)streamStatus {
156  return [dummyStream_ streamStatus];
157}
158- (NSError *)streamError {
159  return [dummyStream_ streamError];
160}
161
162#pragma mark -
163
164// We'll forward all unexpected messages to our dummy stream
165
166+ (NSMethodSignature*)methodSignatureForSelector:(SEL)selector {
167  return [NSInputStream methodSignatureForSelector:selector];
168}
169
170+ (void)forwardInvocation:(NSInvocation*)invocation {
171  [invocation invokeWithTarget:[NSInputStream class]];
172}
173
174- (BOOL)respondsToSelector:(SEL)selector {
175  return [dummyStream_ respondsToSelector:selector];
176}
177
178- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector {
179  return [dummyStream_ methodSignatureForSelector:selector];
180}
181
182- (void)forwardInvocation:(NSInvocation*)invocation {
183
184#if 0
185  // uncomment this section to see the messages the NSInputStream receives
186  SEL selector;
187  NSString *selName;
188
189  selector=[invocation selector];
190  selName=NSStringFromSelector(selector);
191  NSLog(@"-forwardInvocation: %@",selName);
192#endif
193
194  [invocation invokeWithTarget:dummyStream_];
195}
196
197@end