static void formEventCallback(CFReadStreamRef stream, CFStreamEventType type, void* context) { FormStreamFields* form = static_cast<FormStreamFields*>(context); switch (type) { case kCFStreamEventHasBytesAvailable: CFReadStreamSignalEvent(form->formStream, kCFStreamEventHasBytesAvailable, 0); break; case kCFStreamEventErrorOccurred: { CFStreamError readStreamError = CFReadStreamGetError(stream); CFReadStreamSignalEvent(form->formStream, kCFStreamEventErrorOccurred, &readStreamError); break; } case kCFStreamEventEndEncountered: openNextStream(form); if (!form->currentStream) CFReadStreamSignalEvent(form->formStream, kCFStreamEventEndEncountered, 0); break; case kCFStreamEventNone: LOG_ERROR("unexpected kCFStreamEventNone"); break; case kCFStreamEventOpenCompleted: LOG_ERROR("unexpected kCFStreamEventOpenCompleted"); break; case kCFStreamEventCanAcceptBytes: LOG_ERROR("unexpected kCFStreamEventCanAcceptBytes"); break; } }
static Boolean readDataOpen(struct _CFStream *stream, CFStreamError *errorCode, Boolean *openComplete, void *info) { _CFReadDataStreamContext *dataStream = (_CFReadDataStreamContext *)info; if (dataStream->scheduled) { if (CFDataGetLength(dataStream->data) != 0) { CFReadStreamSignalEvent((CFReadStreamRef)stream, kCFStreamEventHasBytesAvailable, NULL); } else { CFReadStreamSignalEvent((CFReadStreamRef)stream, kCFStreamEventEndEncountered, NULL); } } errorCode->error = 0; *openComplete = TRUE; return TRUE; }
static void readDataSchedule(struct _CFStream *stream, CFRunLoopRef rl, CFStringRef rlMode, void *info) { _CFReadDataStreamContext *dataStream = (_CFReadDataStreamContext *)info; if (dataStream->scheduled == FALSE) { dataStream->scheduled = TRUE; if (CFReadStreamGetStatus((CFReadStreamRef)stream) != kCFStreamStatusOpen) return; if (CFDataGetBytePtr(dataStream->data) + CFDataGetLength(dataStream->data) > dataStream->loc) { CFReadStreamSignalEvent((CFReadStreamRef)stream, kCFStreamEventHasBytesAvailable, NULL); } else { CFReadStreamSignalEvent((CFReadStreamRef)stream, kCFStreamEventEndEncountered, NULL); } } }
static void fileSchedule(struct _CFStream *stream, CFRunLoopRef runLoop, CFStringRef runLoopMode, void *info) { _CFFileStreamContext *fileStream = (_CFFileStreamContext *)info; Boolean isReadStream = (CFGetTypeID(stream) == CFReadStreamGetTypeID()); CFStreamStatus status = isReadStream ? CFReadStreamGetStatus((CFReadStreamRef)stream) : CFWriteStreamGetStatus((CFWriteStreamRef)stream); if (fileStream->fd < 0 && status != kCFStreamStatusNotOpen) { // Stream's already closed or error-ed out return; } #ifdef REAL_FILE_SCHEDULING if (status == kCFStreamStatusNotOpen) { if (!fileStream->rlInfo.rlArray) { fileStream->rlInfo.rlArray = CFArrayCreateMutable(CFGetAllocator(stream), 0, &kCFTypeArrayCallBacks); } CFArrayAppendValue(fileStream->rlInfo.rlArray, runLoop); CFArrayAppendValue(fileStream->rlInfo.rlArray, runLoopMode); } else { CFRunLoopSourceRef rlSrc; if (!fileStream->rlInfo.cffd) { constructCFFD(fileStream, isReadStream, stream); } rlSrc = CFFileDescriptorCreateRunLoopSource(CFGetAllocator(stream), fileStream->rlInfo.cffd, 0); CFRunLoopAddSource(runLoop, rlSrc, runLoopMode); CFRelease(rlSrc); } #else fileStream->scheduled++; if (fileStream->scheduled == 1 && fileStream->fd > 0 && status == kCFStreamStatusOpen) { if (isReadStream) CFReadStreamSignalEvent((CFReadStreamRef)stream, kCFStreamEventHasBytesAvailable, NULL); else CFWriteStreamSignalEvent((CFWriteStreamRef)stream, kCFStreamEventCanAcceptBytes, NULL); } #endif }
static CFIndex fileRead(CFReadStreamRef stream, UInt8 *buffer, CFIndex bufferLength, CFStreamError *errorCode, Boolean *atEOF, void *info) { _CFFileStreamContext *ctxt = (_CFFileStreamContext *)info; CFIndex result; result = fdRead(ctxt->fd, buffer, bufferLength, errorCode, atEOF); #ifdef REAL_FILE_SCHEDULING if (__CFBitIsSet(ctxt->flags, SCHEDULE_AFTER_READ)) { __CFBitClear(ctxt->flags, SCHEDULE_AFTER_READ); if (!*atEOF && ctxt->rlInfo.cffd) { struct stat statbuf; int ret = fstat(ctxt->fd, &statbuf); if (0 <= ret && (S_IFREG == (statbuf.st_mode & S_IFMT))) { off_t offset = lseek(ctxt->fd, 0, SEEK_CUR); if (statbuf.st_size == offset) { _CFFileDescriptorInduceFakeReadCallBack(ctxt->rlInfo.cffd); } } } if (ctxt->rlInfo.cffd) { CFFileDescriptorEnableCallBacks(ctxt->rlInfo.cffd, kCFFileDescriptorReadCallBack); } } #else if (*atEOF) __CFBitSet(ctxt->flags, AT_EOF); if (ctxt->scheduled > 0 && !*atEOF) { CFReadStreamSignalEvent(stream, kCFStreamEventHasBytesAvailable, NULL); } #endif return result; }
static Boolean fileOpen(struct _CFStream *stream, CFStreamError *errorCode, Boolean *openComplete, void *info) { _CFFileStreamContext *ctxt = (_CFFileStreamContext *)info; Boolean forRead = (CFGetTypeID(stream) == CFReadStreamGetTypeID()); *openComplete = TRUE; if (ctxt->url) { if (constructFD(ctxt, errorCode, forRead, stream)) { #ifndef REAL_FILE_SCHEDULING if (ctxt->scheduled > 0) { if (forRead) CFReadStreamSignalEvent((CFReadStreamRef)stream, kCFStreamEventHasBytesAvailable, NULL); else CFWriteStreamSignalEvent((CFWriteStreamRef)stream, kCFStreamEventCanAcceptBytes, NULL); } #endif return TRUE; } else { return FALSE; } #ifdef REAL_FILE_SCHEDULING } else if (ctxt->rlInfo.rlArray != NULL) { constructCFFD(ctxt, forRead, stream); #endif } return TRUE; }
static void fileCallBack(CFFileDescriptorRef f, CFOptionFlags type, void *info) { struct _CFStream *stream = (struct _CFStream *)info; Boolean isReadStream = (CFGetTypeID(stream) == CFReadStreamGetTypeID()); _CFFileStreamContext *fileStream = isReadStream ? CFReadStreamGetInfoPointer((CFReadStreamRef)stream) : CFWriteStreamGetInfoPointer((CFWriteStreamRef)stream); if (type == kCFFileDescriptorWriteCallBack) { __CFBitSet(fileStream->flags, SCHEDULE_AFTER_WRITE); CFWriteStreamSignalEvent((CFWriteStreamRef)stream, kCFStreamEventCanAcceptBytes, NULL); } else { __CFBitSet(fileStream->flags, SCHEDULE_AFTER_READ); CFReadStreamSignalEvent((CFReadStreamRef)stream, kCFStreamEventHasBytesAvailable, NULL); } }
static Boolean formCanRead(CFReadStreamRef stream, void* context) { FormStreamFields* form = static_cast<FormStreamFields*>(context); while (form->currentStream && CFReadStreamGetStatus(form->currentStream) == kCFStreamStatusAtEnd) openNextStream(form); if (!form->currentStream) { CFReadStreamSignalEvent(stream, kCFStreamEventEndEncountered, 0); return FALSE; } return CFReadStreamHasBytesAvailable(form->currentStream); }
static const UInt8 *dataGetBuffer(CFReadStreamRef stream, CFIndex maxBytesToRead, CFIndex *numBytesRead, CFStreamError *error, Boolean *atEOF, void *info) { _CFReadDataStreamContext *dataCtxt = (_CFReadDataStreamContext *)info; const UInt8 *bytes = CFDataGetBytePtr(dataCtxt->data); if (dataCtxt->loc - bytes > maxBytesToRead) { *numBytesRead = maxBytesToRead; *atEOF = FALSE; } else { *numBytesRead = dataCtxt->loc - bytes; *atEOF = TRUE; } error->error = 0; bytes = dataCtxt->loc; dataCtxt->loc += *numBytesRead; if (dataCtxt->scheduled && !*atEOF) { CFReadStreamSignalEvent(stream, kCFStreamEventHasBytesAvailable, NULL); } return bytes; }
static CFIndex dataRead(CFReadStreamRef stream, UInt8 *buffer, CFIndex bufferLength, CFStreamError *error, Boolean *atEOF, void *info) { _CFReadDataStreamContext *dataCtxt = (_CFReadDataStreamContext *)info; const UInt8 *bytePtr = CFDataGetBytePtr(dataCtxt->data); CFIndex length = CFDataGetLength(dataCtxt->data); CFIndex bytesToCopy = bytePtr + length - dataCtxt->loc; if (bytesToCopy > bufferLength) { bytesToCopy = bufferLength; } if (bytesToCopy < 0) { bytesToCopy = 0; } if (bytesToCopy != 0) { memmove(buffer, dataCtxt->loc, bytesToCopy); dataCtxt->loc += bytesToCopy; } error->error = 0; *atEOF = (dataCtxt->loc < bytePtr + length) ? FALSE : TRUE; if (dataCtxt->scheduled && !*atEOF) { CFReadStreamSignalEvent(stream, kCFStreamEventHasBytesAvailable, NULL); } return bytesToCopy; }