/ NSOutputStream.m
NSOutputStream.m
  1  //
  2  //  NSOutputStream.m
  3  //  CoreFoundation
  4  //
  5  //  Copyright (c) 2014 Apportable. All rights reserved.
  6  //
  7  
  8  #import <Foundation/NSError.h>
  9  #import <Foundation/NSRunLoop.h>
 10  #import "NSStreamInternal.h"
 11  #import "NSObjectInternal.h"
 12  
 13  @implementation NSOutputStream
 14  
 15  + (id)allocWithZone:(NSZone *)zone
 16  {
 17      if (self == [NSOutputStream class])
 18      {
 19          return [__NSCFOutputStream allocWithZone:zone];
 20      }
 21      else
 22      {
 23          return [super allocWithZone:zone];
 24      }
 25  }
 26  
 27  - (NSInteger)write:(const uint8_t *)buffer maxLength:(NSUInteger)len
 28  {
 29      NSRequestConcreteImplementation();
 30      return 0;
 31  }
 32  
 33  - (BOOL)hasSpaceAvailable
 34  {
 35      NSRequestConcreteImplementation();
 36      return NO;
 37  }
 38  
 39  @end
 40  
 41  @implementation NSOutputStream (NSOutputStreamExtensions)
 42  
 43  + (id)outputStreamToMemory
 44  {
 45      return [[[self alloc] initToMemory] autorelease];
 46  }
 47  
 48  + (id)outputStreamToBuffer:(uint8_t *)buffer capacity:(NSUInteger)capacity
 49  {
 50      return [[[self alloc] initToBuffer:buffer capacity:capacity] autorelease];
 51  }
 52  
 53  + (id)outputStreamToFileAtPath:(NSString *)path append:(BOOL)shouldAppend
 54  {
 55      return [[[self alloc] initToFileAtPath:path append:shouldAppend] autorelease];
 56  }
 57  
 58  + (id)outputStreamWithURL:(NSURL *)url append:(BOOL)shouldAppend
 59  {
 60      return [[[self alloc] initWithURL:url append:shouldAppend] autorelease];
 61  }
 62  
 63  - (id)initToMemory
 64  {
 65      NSRequestConcreteImplementation();
 66      [self release];
 67      return nil;
 68  }
 69  
 70  - (id)initToBuffer:(uint8_t *)buffer capacity:(NSUInteger)capacity
 71  {
 72      NSRequestConcreteImplementation();
 73      [self release];
 74      return nil;
 75  }
 76  
 77  - (id)initToFileAtPath:(NSString *)path append:(BOOL)shouldAppend
 78  {
 79      NSRequestConcreteImplementation();
 80      [self release];
 81      return nil;
 82  }
 83  
 84  - (id)initWithURL:(NSURL *)url append:(BOOL)shouldAppend
 85  {
 86      NSRequestConcreteImplementation();
 87      [self release];
 88      return nil;
 89  }
 90  
 91  @end
 92  
 93  @implementation __NSCFOutputStream
 94  
 95  
 96  + (id)allocWithZone:(NSZone *)zone
 97  {
 98      static __NSCFOutputStream *placeholder = nil;
 99      static dispatch_once_t once = 0L;
100      dispatch_once(&once, ^{
101          placeholder = [super allocWithZone:zone];
102      });
103      return placeholder;
104  }
105  
106  + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
107  {
108      return NO;
109  }
110  
111  - (void)_unscheduleFromCFRunLoop:(CFRunLoopRef)runLoop forMode:(CFStringRef)mode
112  {
113      CFWriteStreamUnscheduleFromRunLoop((CFWriteStreamRef)self, runLoop, mode);
114  }
115  
116  - (void)_scheduleInCFRunLoop:(CFRunLoopRef)runLoop forMode:(CFStringRef)mode
117  {
118      CFWriteStreamUnscheduleFromRunLoop((CFWriteStreamRef)self, runLoop, mode);
119  }
120  
121  - (BOOL)_setCFClientFlags:(CFOptionFlags)flags callback:(CFWriteStreamClientCallBack)callback context:(CFStreamClientContext *)context
122  {
123      return CFWriteStreamSetClient((CFWriteStreamRef)self, flags, callback, context);
124  }
125  
126  - (BOOL)hasSpaceAvailable
127  {
128      return CFWriteStreamCanAcceptBytes((CFWriteStreamRef)self);
129  }
130  
131  - (NSInteger)write:(const uint8_t *)buffer maxLength:(NSUInteger)len
132  {
133      return CFWriteStreamWrite((CFWriteStreamRef)self, buffer, len);
134  }
135  
136  - (NSError *)streamError
137  {
138      return [CFWriteStreamCopyError((CFWriteStreamRef)self) autorelease];
139  }
140  
141  - (NSStreamStatus)streamStatus
142  {
143      return (NSStreamStatus)CFWriteStreamGetStatus((CFWriteStreamRef)self);
144  }
145  
146  - (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode
147  {
148      if (aRunLoop == nil)
149      {
150          return;
151      }
152  
153      CFWriteStreamScheduleWithRunLoop((CFWriteStreamRef)self, [aRunLoop getCFRunLoop], (CFStringRef)mode);
154  }
155  
156  - (void)removeFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode
157  {
158      if (aRunLoop == nil)
159      {
160          return;
161      }
162      
163      CFWriteStreamUnscheduleFromRunLoop((CFWriteStreamRef)self, [aRunLoop getCFRunLoop], (CFStringRef)mode);
164  }
165  
166  - (id)propertyForKey:(NSString *)key
167  {
168      return [(id)CFWriteStreamCopyProperty((CFWriteStreamRef)self, (CFStringRef)key) autorelease];
169  }
170  
171  - (BOOL)setProperty:(id)property forKey:(NSString *)key
172  {
173      return CFWriteStreamSetProperty((CFWriteStreamRef)self, (CFStringRef)key, (CFTypeRef)property);
174  }
175  
176  - (id <NSStreamDelegate>)delegate
177  {
178      return _CFWriteStreamGetClient((CFWriteStreamRef)self);
179  }
180  
181  static void __NSCFOutputStreamCallback(CFWriteStreamRef stream, CFStreamEventType type, void *clientCallBackInfo)
182  {
183      id<NSStreamDelegate> delegate = [(NSStream *)stream delegate];
184      [delegate stream:(NSStream *)stream handleEvent:(NSStreamEvent)type];
185  }
186  
187  - (void)setDelegate:(id <NSStreamDelegate>)delegate
188  {
189      CFStreamClientContext ctx = {
190          0,
191          delegate,
192          NULL,
193          NULL,
194          (CFStringRef (*)(void *))&_NSCFCopyDescription
195      };
196      CFOptionFlags flags = kCFStreamEventOpenCompleted | kCFStreamEventHasBytesAvailable | kCFStreamEventCanAcceptBytes | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered;
197      [self _setCFClientFlags:flags callback:&__NSCFOutputStreamCallback context:&ctx];
198  }
199  
200  - (void)close
201  {
202      CFWriteStreamClose((CFWriteStreamRef)self);
203  }
204  
205  - (void)open
206  {
207      CFWriteStreamOpen((CFWriteStreamRef)self);
208  }
209  
210  - (id)initWithURL:(NSURL *)url append:(BOOL)shouldAppend
211  {
212      CFWriteStreamRef stream = CFWriteStreamCreateWithFile(kCFAllocatorDefault, (CFURLRef)url);
213      if (stream != NULL && shouldAppend)
214      {
215          CFWriteStreamSetProperty(stream, kCFStreamPropertyAppendToFile, kCFBooleanTrue);
216      }
217      return (id)stream;
218  }
219  
220  - (id)initToFileAtPath:(NSString *)path append:(BOOL)shouldAppend
221  {
222      NSURL *url = [[NSURL alloc] initFileURLWithPath:path];
223      id stream = [self initWithURL:url append:shouldAppend];
224      [url release];
225      return stream;
226  }
227  
228  - (id)initToBuffer:(uint8_t *)buffer capacity:(NSUInteger)capacity
229  {
230      return (id)CFWriteStreamCreateWithBuffer(kCFAllocatorDefault, buffer, capacity);
231  }
232  
233  - (id)initToMemory
234  {
235      return (id)CFWriteStreamCreateWithAllocatedBuffers(kCFAllocatorDefault, kCFAllocatorDefault);
236  }
237  
238  - (NSUInteger)retainCount
239  {
240      return CFGetRetainCount((CFTypeRef)self);
241  }
242  
243  - (BOOL)_isDeallocating
244  {
245      return _CFIsDeallocating((CFTypeRef)self);
246  }
247  
248  - (BOOL)_tryRetain
249  {
250      return _CFTryRetain((CFTypeRef)self) != NULL;
251  }
252  
253  - (oneway void)release
254  {
255      CFRelease((CFTypeRef)self);
256  }
257  
258  - (id)retain
259  {
260      return (id)CFRetain((CFTypeRef)self);
261  }
262  
263  - (NSUInteger)hash
264  {
265      return CFHash((CFTypeRef)self);
266  }
267  
268  - (BOOL)isEqual:(id)other
269  {
270      if (other == nil)
271      {
272          return NO;
273      }
274      return CFEqual((CFTypeRef)self, (CFTypeRef)other);
275  }
276  
277  - (CFTypeID)_cfTypeID
278  {
279      return CFWriteStreamGetTypeID();
280  }
281  
282  @end