1 #include "StreamSource.h"
4 #include "SecCFRelease.h"
8 CFStringRef gStreamSourceName
= CFSTR("StreamSource");
10 const CFIndex kMaximumSize
= 2048;
12 StreamSource::StreamSource(CFReadStreamRef input
, Transform
* transform
, CFStringRef name
)
13 : Source(gStreamSourceName
, transform
, name
),
15 mReading(dispatch_group_create())
17 dispatch_group_enter(mReading
);
18 CFRetainSafe(mReadStream
);
21 void StreamSource::BackgroundActivate()
27 // make a buffer big enough to handle the object
28 // NOTE: allocating this on the stack and letting CFDataCreate copy it is _faster_ then malloc and CFDataCreateWithBytes(..., kCFAllactorMalloc) by a fair margin. At least for 2K chunks. Retest if changing the size.
29 UInt8 buffer
[kMaximumSize
];
31 result
= CFReadStreamRead(mReadStream
, buffer
, kMaximumSize
);
33 if (result
> 0) // was data returned?
35 // make the data and send it to the transform
36 CFDataRef data
= CFDataCreate(NULL
, buffer
, result
);
38 CFErrorRef error
= mDestination
->SetAttribute(mDestinationName
, data
);
42 if (error
!= NULL
) // we have a problem, there was probably an abort on the chain
44 return; // quiesce the source
52 CFErrorRef error
= CFReadStreamCopyError(mReadStream
);
53 mDestination
->SetAttribute(mDestinationName
, error
);
56 // NOTE: CF doesn't always tell us about this error. Arguably it could be better to
57 // "invent" a generic error, but it is a hard argument that we want to crash in CFReleaseNull(NULL)...
64 mDestination
->SetAttribute(mDestinationName
, NULL
); // end of stream
68 void StreamSource::DoActivate()
70 CFRetainSafe(mDestination
->GetCFObject());
71 dispatch_group_async(mReading
, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW
, 0), ^{
72 this->BackgroundActivate();
73 CFReleaseSafe(mDestination
->GetCFObject());
75 dispatch_group_leave(mReading
);
78 void StreamSource::Finalize()
80 dispatch_group_notify(mReading
, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH
, 0), ^{
85 StreamSource::~StreamSource()
87 CFReleaseNull(mReadStream
);
89 dispatch_release(mReading
);
94 Boolean
StreamSource::Equal(const CoreFoundationObject
* object
)
96 // not equal if we are not the same object
97 if (Source::Equal(object
))
99 const StreamSource
* ss
= (StreamSource
*) object
;
100 return CFEqual(ss
->mReadStream
, mReadStream
);
108 CFTypeRef
StreamSource::Make(CFReadStreamRef input
, Transform
* transform
, CFStringRef name
)
110 return CoreFoundationHolder::MakeHolder(gInternalCFObjectName
, new StreamSource(input
, transform
, name
));
115 string
StreamSource::DebugDescription()
117 string result
= Source::DebugDescription() + ": Stream ";
120 snprintf(buffer
, sizeof(buffer
), "(mReadStream = %p)", mReadStream
);