// Copyright 1997-2002 Omni Development, Inc.  All rights reserved.
//
// This software may only be used and reproduced according to the
// terms in the file OmniSourceLicense.html, which should be
// distributed with this project and can also be found at
// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.
//
// $Header: /Network/Source/CVS/OmniGroup/Frameworks/OWF/Content.subproj/OWDataStream.h,v 1.28 2002/03/09 01:53:49 kc Exp $

#import <OWF/OWStream.h>

@class NSData, NSFileHandle, NSLock, NSMutableData;
@class OFCondition;
@class OWContentCache, OWDataStreamCursor;

#import <Foundation/NSByteOrder.h>
#import <Foundation/NSString.h> // For NSStringEncoding
#import <CoreFoundation/CFString.h> // For CFStringEncoding
#import <OmniFoundation/OFByte.h>

typedef struct _OWDataStreamBufferDescriptor {
    OFByte *buffer;
    unsigned int bufferSize;
    volatile unsigned int bufferUsed;
    struct _OWDataStreamBufferDescriptor * volatile next;
} OWDataStreamBufferDescriptor;

enum OWStringEncodingProvenance {
        // these are ordered: later enums in this list can override earlier ones.
        OWStringEncodingProvenance_Default,             // Global default encoding
        OWStringEncodingProvenance_Preference,          // App preference
        OWStringEncodingProvenance_MetaTag,             // Specified in META tag
        OWStringEncodingProvenance_ProtocolHeader,      // Specified in HTTP header
        OWStringEncodingProvenance_WindowPreference,    // Window-specific override
        OWStringEncodingProvenance_Generated            // We created this stream from character data and we KNOW what encoding we're using, so there
};

@interface OWDataStream : OWStream
{
    OWContentType *contentEncoding;

    OFCondition *dataAvailableCondition;
    OFCondition *endOfDataCondition;

    
    OWDataStreamBufferDescriptor *_first, *_last;
    unsigned int dataLength;      // total number of bytes in stream, if EOF reached or if known ahead of time
    unsigned int readLength;      // total number of bytes written to stream (available for reading) so far

    CFStringEncoding stringEncoding;
    enum OWStringEncodingProvenance stringEncodingProvenance;
    
    struct {
        unsigned int endOfData:1;
        unsigned int hasThrownAwayData:1;
        unsigned int hasIssuedCursor:1;
        unsigned int hasResetContentTypeAndEncoding:1;
    } flags;

    NSString *saveFilename;
    NSFileHandle *saveFileHandle;
    NSLock *saveFileHandleLock;
    unsigned int savedInBuffer;
    OWDataStreamBufferDescriptor *savedBuffer;
}

- init;
- initWithLength:(unsigned int)newLength;

- (id)newCursor;
    // Returns a new OWDataStreamCursor.

- (void)writeData:(NSData *)newData;
- (void)writeString:(NSString *)string;
- (void)writeFormat:(NSString *)formatString, ...;

- (unsigned int)appendToUnderlyingBuffer:(void **)returnedBufferPtr;
    // Returns the number of bytes which can be safely written to the returned pointer (always >0)
- (void)wroteBytesToUnderlyingBuffer:(unsigned int)count;    
    // Tell the data stream how many bytes you actually wrote

- (NSData *)bufferedData;
- (unsigned int)bufferedDataLength;

- (unsigned int)accessUnderlyingBuffer:(void **)returnedBufferPtr startingAtLocation:(unsigned int)dataOffset;
    // Returns 0 if there isn't any remaining data, otherwise returns a portion of a _OWDataStreamBuffer


- (unsigned int)dataLength;
- (BOOL)knowsDataLength;

- (BOOL)getBytes:(void *)buffer range:(NSRange)range;
    // Returns NO if there isn't enough data for the range requested
- (NSData *)dataWithRange:(NSRange)range;
    // Returns nil if there isn't enough data for the range requested

- (BOOL)waitForMoreData;
- (BOOL)waitForBufferedDataLength:(unsigned int)length;
    // Returns NO if the stream ends and isn't long enough.

//

- (CFStringEncoding)stringEncoding;
- (enum OWStringEncodingProvenance)stringEncodingProvenance;
- (void)setCFStringEncoding:(CFStringEncoding)aStringEncoding provenance:(enum OWStringEncodingProvenance)whence;

//

- (OWContentType *)contentEncoding;
- (OWContentType *)encodedContentType;
- (void)setContentEncoding:(OWContentType *)aContentEncoding;
- (void)setContentTypeAndEncodingFromFilename:(NSString *)aFilename isLocalFile:(BOOL)isLocalFile;
- (NSString *)pathExtensionForContentTypeAndEncoding;
- (BOOL)resetContentTypeAndEncoding;
    // Can only reset once.  After that, returns NO and does nothing.

//

- (BOOL)pipeToFilename:(NSString *)aFilename;
    // Returns YES if data is piped to aFilename, returns NO if data is saved to disk, but to some other filename (use -filename to find out where).  Raises an exception if it can't save.
- (NSString *)filename;
- (BOOL)hasThrownAwayData;
- (unsigned int)bytesWrittenToFile;

@end

#import <OWF/FrameworkDefines.h>

OWF_EXTERN const unsigned int OWDataStreamUnknownLength;
OWF_EXTERN NSString *OWDataStreamNoLongerValidException;
