{	CFStream.h
	Copyright (c) 2000-2005, Apple, Inc. All rights reserved.
}
{	  Pascal Translation:  Peter N Lewis, <peter@stairways.com.au>, 2004 }
{	  Pascal Translation Updated:  Peter N Lewis, <peter@stairways.com.au>, November 2005 }
{
    Modified for use with Free Pascal
    Version 200
    Please report any bugs to <gpc@microbizz.nl>
}

{$mode macpas}
{$packenum 1}
{$macro on}
{$inline on}
{$CALLING MWPASCAL}

unit CFStream;
interface
{$setc UNIVERSAL_INTERFACES_VERSION := $0342}
{$setc GAP_INTERFACES_VERSION := $0200}

{$ifc not defined USE_CFSTR_CONSTANT_MACROS}
    {$setc USE_CFSTR_CONSTANT_MACROS := TRUE}
{$endc}

{$ifc defined CPUPOWERPC and defined CPUI386}
	{$error Conflicting initial definitions for CPUPOWERPC and CPUI386}
{$endc}
{$ifc defined FPC_BIG_ENDIAN and defined FPC_LITTLE_ENDIAN}
	{$error Conflicting initial definitions for FPC_BIG_ENDIAN and FPC_LITTLE_ENDIAN}
{$endc}

{$ifc not defined __ppc__ and defined CPUPOWERPC}
	{$setc __ppc__ := 1}
{$elsec}
	{$setc __ppc__ := 0}
{$endc}
{$ifc not defined __i386__ and defined CPUI386}
	{$setc __i386__ := 1}
{$elsec}
	{$setc __i386__ := 0}
{$endc}

{$ifc defined __ppc__ and __ppc__ and defined __i386__ and __i386__}
	{$error Conflicting definitions for __ppc__ and __i386__}
{$endc}

{$ifc defined __ppc__ and __ppc__}
	{$setc TARGET_CPU_PPC := TRUE}
	{$setc TARGET_CPU_X86 := FALSE}
{$elifc defined __i386__ and __i386__}
	{$setc TARGET_CPU_PPC := FALSE}
	{$setc TARGET_CPU_X86 := TRUE}
{$elsec}
	{$error Neither __ppc__ nor __i386__ is defined.}
{$endc}
{$setc TARGET_CPU_PPC_64 := FALSE}

{$ifc defined FPC_BIG_ENDIAN}
	{$setc TARGET_RT_BIG_ENDIAN := TRUE}
	{$setc TARGET_RT_LITTLE_ENDIAN := FALSE}
{$elifc defined FPC_LITTLE_ENDIAN}
	{$setc TARGET_RT_BIG_ENDIAN := FALSE}
	{$setc TARGET_RT_LITTLE_ENDIAN := TRUE}
{$elsec}
	{$error Neither FPC_BIG_ENDIAN nor FPC_LITTLE_ENDIAN are defined.}
{$endc}
{$setc ACCESSOR_CALLS_ARE_FUNCTIONS := TRUE}
{$setc CALL_NOT_IN_CARBON := FALSE}
{$setc OLDROUTINENAMES := FALSE}
{$setc OPAQUE_TOOLBOX_STRUCTS := TRUE}
{$setc OPAQUE_UPP_TYPES := TRUE}
{$setc OTCARBONAPPLICATION := TRUE}
{$setc OTKERNEL := FALSE}
{$setc PM_USE_SESSION_APIS := TRUE}
{$setc TARGET_API_MAC_CARBON := TRUE}
{$setc TARGET_API_MAC_OS8 := FALSE}
{$setc TARGET_API_MAC_OSX := TRUE}
{$setc TARGET_CARBON := TRUE}
{$setc TARGET_CPU_68K := FALSE}
{$setc TARGET_CPU_MIPS := FALSE}
{$setc TARGET_CPU_SPARC := FALSE}
{$setc TARGET_OS_MAC := TRUE}
{$setc TARGET_OS_UNIX := FALSE}
{$setc TARGET_OS_WIN32 := FALSE}
{$setc TARGET_RT_MAC_68881 := FALSE}
{$setc TARGET_RT_MAC_CFM := FALSE}
{$setc TARGET_RT_MAC_MACHO := TRUE}
{$setc TYPED_FUNCTION_POINTERS := TRUE}
{$setc TYPE_BOOL := FALSE}
{$setc TYPE_EXTENDED := FALSE}
{$setc TYPE_LONGLONG := TRUE}
uses MacTypes,CFBase,CFString,CFDictionary,CFURL,CFRunLoop,CFSocket;
{$ALIGN POWER}


type
	CFStreamStatus = SInt32;
const
    kCFStreamStatusNotOpen = 0;
    kCFStreamStatusOpening = 1;  { open is in-progress }
    kCFStreamStatusOpen = 2;
    kCFStreamStatusReading = 3;
    kCFStreamStatusWriting = 4;
    kCFStreamStatusAtEnd = 5;    { no further bytes can be read/written }
    kCFStreamStatusClosed = 6;
    kCFStreamStatusError = 7;

type
	CFStreamErrorDomain = SInt32;
const
    kCFStreamErrorDomainCustom = -1;      { custom to the kind of stream in question }
    kCFStreamErrorDomainPOSIX = 1;        { POSIX errno; interpret using <sys/errno.h> }
    kCFStreamErrorDomainMacOSStatus = 2;      { OSStatus type from Carbon APIs; interpret using <MacTypes.h> }

type
	CFStreamError = record
		domain: CFStreamErrorDomain;
		error: SInt32;
	end;
	CFStreamErrorPtr = ^CFStreamError;

type
	CFStreamEventType = SInt32;
const
    kCFStreamEventNone = 0;
    kCFStreamEventOpenCompleted = 1;
    kCFStreamEventHasBytesAvailable = 2;
    kCFStreamEventCanAcceptBytes = 4; 
    kCFStreamEventErrorOccurred = 8;
    kCFStreamEventEndEncountered = 16;

type
	CFStreamClientContext = record
		version: CFIndex;
		info: UnivPtr;
		retain: function( info: {const} UnivPtr ): UnivPtr;
		release: procedure( info: {const} UnivPtr );
		copyDescription: function( info: {const} UnivPtr ): CFStringRef;
	end;

type
	CFReadStreamRef = ^SInt32; { an opaque 32-bit type }
	CFReadStreamRefPtr = ^CFReadStreamRef;
	CFWriteStreamRef = ^SInt32; { an opaque 32-bit type }
	CFWriteStreamRefPtr = ^CFWriteStreamRef;

type
	CFReadStreamClientCallBack = procedure( stream: CFReadStreamRef; typ: CFStreamEventType; clientCallBackInfo: UnivPtr );
	CFWriteStreamClientCallBack = procedure( stream: CFWriteStreamRef; typ: CFStreamEventType; clientCallBackInfo: UnivPtr );

function CFReadStreamGetTypeID: CFTypeID; external name '_CFReadStreamGetTypeID';
function CFWriteStreamGetTypeID: CFTypeID; external name '_CFWriteStreamGetTypeID';

{ Memory streams }

{ Value will be a CFData containing all bytes thusfar written; used to recover the data written to a memory write stream. }
var kCFStreamPropertyDataWritten: CFStringRef; external name '_kCFStreamPropertyDataWritten'; (* attribute const *)

{ Pass kCFAllocatorNull for bytesDeallocator to prevent CFReadStream from deallocating bytes; otherwise, CFReadStream will deallocate bytes when the stream is destroyed }
function CFReadStreamCreateWithBytesNoCopy( alloc: CFAllocatorRef; bytes: UnivPtr; length: CFIndex; bytesDeallocator: CFAllocatorRef ): CFReadStreamRef; external name '_CFReadStreamCreateWithBytesNoCopy';

{ The stream writes into the buffer given; when bufferCapacity is exhausted, the stream is exhausted (status becomes kCFStreamStatusAtEnd) }
function CFWriteStreamCreateWithBuffer( alloc: CFAllocatorRef; buffer: UnivPtr; bufferCapacity: CFIndex ): CFWriteStreamRef; external name '_CFWriteStreamCreateWithBuffer';

{ New buffers are allocated from bufferAllocator as bytes are written to the stream.  At any point, you can recover the bytes thusfar written by asking for the property kCFStreamPropertyDataWritten, above }
function CFWriteStreamCreateWithAllocatedBuffers( alloc: CFAllocatorRef; bufferAllocator: CFAllocatorRef ): CFWriteStreamRef; external name '_CFWriteStreamCreateWithAllocatedBuffers';

{ File streams }
function CFReadStreamCreateWithFile( alloc: CFAllocatorRef; fileURL: CFURLRef ): CFReadStreamRef; external name '_CFReadStreamCreateWithFile';
function CFWriteStreamCreateWithFile( alloc: CFAllocatorRef; fileURL: CFURLRef ): CFWriteStreamRef; external name '_CFWriteStreamCreateWithFile';

{#if MAC_OS_X_VERSION_10_2 <= MAC_OS_X_VERSION_MAX_ALLOWED}
{ Property for file write streams; value should be a CFBoolean.  Set to TRUE to append to a file, rather than to replace its contents }
var kCFStreamPropertyAppendToFile: CFStringRef; external name '_kCFStreamPropertyAppendToFile'; (* attribute const *)
{#endif}

var kCFStreamPropertyFileCurrentOffset: CFStringRef; external name '_kCFStreamPropertyFileCurrentOffset'; (* attribute const *)
(* AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER *)

{ Socket stream properties }

{ Value will be a CFData containing the native handle }
var kCFStreamPropertySocketNativeHandle: CFStringRef; external name '_kCFStreamPropertySocketNativeHandle'; (* attribute const *)

{ Value will be a CFString, or NULL if unknown }
var kCFStreamPropertySocketRemoteHostName: CFStringRef; external name '_kCFStreamPropertySocketRemoteHostName'; (* attribute const *)

{ Value will be a CFNumber, or NULL if unknown }
var kCFStreamPropertySocketRemotePortNumber: CFStringRef; external name '_kCFStreamPropertySocketRemotePortNumber'; (* attribute const *)

{ Socket streams; the returned streams are paired such that they use the same socket; pass NULL if you want only the read stream or the write stream }
procedure CFStreamCreatePairWithSocket( alloc: CFAllocatorRef; sock: CFSocketNativeHandle; var readStream: CFReadStreamRef; var writeStream: CFWriteStreamRef ); external name '_CFStreamCreatePairWithSocket';
procedure CFStreamCreatePairWithSocketToHost( alloc: CFAllocatorRef; host: CFStringRef; port: UInt32; var readStream: CFReadStreamRef; var writeStream: CFWriteStreamRef ); external name '_CFStreamCreatePairWithSocketToHost';
{#if MAC_OS_X_VERSION_10_2 <= MAC_OS_X_VERSION_MAX_ALLOWED}
procedure CFStreamCreatePairWithPeerSocketSignature( alloc: CFAllocatorRef; const (*var*) signature: CFSocketSignature; var readStream: CFReadStreamRef; var writeStream: CFWriteStreamRef ); external name '_CFStreamCreatePairWithPeerSocketSignature';
{#endif}


{ Returns the current state of the stream }
function CFReadStreamGetStatus( stream: CFReadStreamRef ): CFStreamStatus; external name '_CFReadStreamGetStatus';
function CFWriteStreamGetStatus( stream: CFWriteStreamRef ): CFStreamStatus; external name '_CFWriteStreamGetStatus';

{ 0 is returned if no error has occurred.  errorDomain specifies the domain
   in which the error code should be interpretted; pass NULL if you are not 
   interested. }
function CFReadStreamGetError( stream: CFReadStreamRef ): CFStreamError; external name '_CFReadStreamGetError';
function CFWriteStreamGetError( stream: CFWriteStreamRef ): CFStreamError; external name '_CFWriteStreamGetError';

{ Returns success/failure.  Opening a stream causes it to reserve all the system
   resources it requires.  If the stream can open non-blocking, this will always 
   return TRUE; listen to the run loop source to find out when the open completes
   and whether it was successful, or poll using CFRead/WriteStreamGetStatus(), waiting 
   for a status of kCFStreamStatusOpen or kCFStreamStatusError.  }
function CFReadStreamOpen( stream: CFReadStreamRef ): Boolean; external name '_CFReadStreamOpen';
function CFWriteStreamOpen( stream: CFWriteStreamRef ): Boolean; external name '_CFWriteStreamOpen';

{ Terminates the flow of bytes; releases any system resources required by the 
   stream.  The stream may not fail to close.  You may call CFStreamClose() to 
   effectively abort a stream. }
procedure CFReadStreamClose( stream: CFReadStreamRef ); external name '_CFReadStreamClose';
procedure CFWriteStreamClose( stream: CFWriteStreamRef ); external name '_CFWriteStreamClose';

{ Whether there is data currently available for reading; returns TRUE if it's 
   impossible to tell without trying }
function CFReadStreamHasBytesAvailable( stream: CFReadStreamRef ): Boolean; external name '_CFReadStreamHasBytesAvailable';

{ Returns the number of bytes read, or -1 if an error occurs preventing any 
   bytes from being read, or 0 if the stream's end was encountered.  
   It is an error to try and read from a stream that hasn't been opened first.  
   This call will block until at least one byte is available; it will NOT block
   until the entire buffer can be filled.  To avoid blocking, either poll using
   CFReadStreamHasBytesAvailable() or use the run loop and listen for the 
   kCFStreamCanRead event for notification of data available. }
function CFReadStreamRead( stream: CFReadStreamRef; buffer: UnivPtr; bufferLength: CFIndex ): CFIndex; external name '_CFReadStreamRead';

{ Returns a pointer to an internal buffer if possible (setting *numBytesRead
   to the length of the returned buffer), otherwise returns NULL; guaranteed 
   to return in O(1).  Bytes returned in the buffer are considered read from 
   the stream; if maxBytesToRead is greater than 0, not more than maxBytesToRead
   will be returned.  If maxBytesToRead is less than or equal to zero, as many bytes
   as are readily available will be returned.  The returned buffer is good only 
   until the next stream operation called on the stream.  Caller should neither 
   change the contents of the returned buffer nor attempt to deallocate the buffer;
   it is still owned by the stream. }
function CFReadStreamGetBuffer( stream: CFReadStreamRef; maxBytesToRead: CFIndex; var numBytesRead: CFIndex ): UInt8Ptr; external name '_CFReadStreamGetBuffer';

{ Whether the stream can currently be written to without blocking;
   returns TRUE if it's impossible to tell without trying }
function CFWriteStreamCanAcceptBytes( stream: CFWriteStreamRef ): Boolean; external name '_CFWriteStreamCanAcceptBytes';

{ Returns the number of bytes successfully written, -1 if an error has
   occurred, or 0 if the stream has been filled to capacity (for fixed-length
   streams).  If the stream is not full, this call will block until at least
   one byte is written.  To avoid blocking, either poll via CFWriteStreamCanAcceptBytes
   or use the run loop and listen for the kCFStreamCanWrite event. }
function CFWriteStreamWrite( stream: CFWriteStreamRef; buffer: UnivPtr; bufferLength: CFIndex ): CFIndex; external name '_CFWriteStreamWrite';

{ Particular streams can name properties and assign meanings to them; you
   access these properties through the following calls.  A property is any interesting
   information about the stream other than the data being transmitted itself.
   Examples include the headers from an HTTP transmission, or the expected 
   number of bytes, or permission information, etc.  Properties that can be set
   configure the behavior of the stream, and may only be settable at particular times
   (like before the stream has been opened).  See the documentation for particular 
   properties to determine their get- and set-ability. }
function CFReadStreamCopyProperty( stream: CFReadStreamRef; propertyName: CFStringRef ): CFTypeRef; external name '_CFReadStreamCopyProperty';
function CFWriteStreamCopyProperty( stream: CFWriteStreamRef; propertyName: CFStringRef ): CFTypeRef; external name '_CFWriteStreamCopyProperty';

{#if MAC_OS_X_VERSION_10_2 <= MAC_OS_X_VERSION_MAX_ALLOWED}
{ Returns TRUE if the stream recognizes and accepts the given property-value pair; 
   FALSE otherwise. }
function CFReadStreamSetProperty( stream: CFReadStreamRef; propertyName: CFStringRef; propertyValue: CFTypeRef ): Boolean; external name '_CFReadStreamSetProperty';
function CFWriteStreamSetProperty( stream: CFWriteStreamRef; propertyName: CFStringRef; propertyValue: CFTypeRef ): Boolean; external name '_CFWriteStreamSetProperty';
{#endif}

{ Asynchronous processing - If you wish to neither poll nor block, you may register 
   a client to hear about interesting events that occur on a stream.  Only one client
   per stream is allowed; registering a new client replaces the previous one.

   Once you have set a client, you need to schedule a run loop on which that client
   can be notified.  You may schedule multiple run loops (for instance, if you are 
   using a thread pool).  The client callback will be triggered via one of the scheduled
   run loops; It is the caller's responsibility to ensure that at least one of the 
   scheduled run loops is being run.

   NOTE: not all streams provide these notifications.  If a stream does not support
   asynchronous notification, CFStreamSetClient() will return NO; typically, such
   streams will never block for device I/O (e.g. a stream on memory)
}

function CFReadStreamSetClient( stream: CFReadStreamRef; streamEvents: CFOptionFlags; clientCB: CFReadStreamClientCallBack; var clientContext: CFStreamClientContext ): Boolean; external name '_CFReadStreamSetClient';
function CFWriteStreamSetClient( stream: CFWriteStreamRef; streamEvents: CFOptionFlags; clientCB: CFWriteStreamClientCallBack; var clientContext: CFStreamClientContext ): Boolean; external name '_CFWriteStreamSetClient';

procedure CFReadStreamScheduleWithRunLoop( stream: CFReadStreamRef; runLoop: CFRunLoopRef; runLoopMode: CFStringRef ); external name '_CFReadStreamScheduleWithRunLoop';
procedure CFWriteStreamScheduleWithRunLoop( stream: CFWriteStreamRef; runLoop: CFRunLoopRef; runLoopMode: CFStringRef ); external name '_CFWriteStreamScheduleWithRunLoop';

procedure CFReadStreamUnscheduleFromRunLoop( stream: CFReadStreamRef; runLoop: CFRunLoopRef; runLoopMode: CFStringRef ); external name '_CFReadStreamUnscheduleFromRunLoop';
procedure CFWriteStreamUnscheduleFromRunLoop( stream: CFWriteStreamRef; runLoop: CFRunLoopRef; runLoopMode: CFStringRef ); external name '_CFWriteStreamUnscheduleFromRunLoop';


end.
