//
// $Id: OutStream.h,v 1.9 2005/07/12 19:15:37 will_mason Exp $
//
// vi: set ft=objc:

/*
 * ObjectiveLib - a library of containers and algorithms for Objective-C
 *
 * Copyright (c) 2004
 * Will Mason
 *
 * Portions:
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Copyright (c) 1996,1997
 * Silicon Graphics Computer Systems, Inc.
 *
 * Copyright (c) 1997
 * Moscow Center for SPARC Technology
 *
 * Copyright (c) 1999 
 * Boris Fomitchev
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * You may contact the author at will_mason@users.sourceforge.net.
 */

#if !defined(OUTSTREAM_OL_GUARD)
#define OUTSTREAM_OL_GUARD

#import <ObjectiveLib/Memory.h>
#import <Foundation/NSCoder.h>

@class NSData;

extern NSString* const OLInputOutputException;

/**
 * @class OLOutStream OutStream.h ObjectiveLib/OutStream.h
 *
 * Base class for writing data. OLOutStream provides the basic stream services
 * which include writing primitive data types, strings encoded with UTF-8 and
 * services of NSCoder. The NSCoder services are provided in order to allow
 * objects which already support the NSCoding protocol to write themselves
 * through an instance of OLObjectOutStream. The lower-level methods provided
 * by OLOutStream are preferred for new code.
 *
 * @note Object instances and classes cannot be written using OLOutStream. An instance
 * of OLObjectOutStream must be used instead. The NSCoder support provided in
 * OLOutStream is merely a byproduct of the class hierarchy imposed by NSCoder.
 *
 * @ingroup Streams
 */
@interface OLOutStream : NSCoder
{
}

/**
 * Close the stream. After receiving this message the stream will no longer
 * be available for writing.
 *
 * @exception OLInputOutputException if there is an error closing the stream
 */
- (void) close;

/**
 * Flush the stream. Any data that is pending or buffered will be written and
 * the stream will be restored to a pristine state.
 *
 * @exception OLInputOutputException if there is an error flushing the stream
 */
- (void) flush;

/**
 * Write a boolean value to the stream. The value is written in a platform-independent
 * way and can be read using OLInStream#readBool. Specifically, the value is written
 * as a single byte with a value of 1 if @a value is YES (or non-zero), and as a
 * single byte with a value of 0 if @a value is NO (or zero).
 *
 * @exception OLInputOutputException if there is an error writing to the stream
 * @param value the boolean value to write
 */
- (void) writeBool: (BOOL)value;

/**
 * Write a byte to the stream. The default implementation of this method is to
 * call #writeBytes:count:, so subclasses that can optimize writing one byte
 * should do so.
 *
 * @exception OLInputOutputException if there is an error writing to the stream
 * @param byte the byte to write
 */
- (void) writeByte: (uint8_t)byte;

/**
 * Write a sequence of bytes to the stream. This is the fundamental method for writing
 * to a stream, and subclasses must override this method.
 *
 * @exception OLInputOutputException if there is an error writing to the stream
 * @param bytes the bytes to write
 * @param count the number of bytes to write
 * @return the number of bytes written
 */
- (unsigned) writeBytes: (const uint8_t*)bytes count: (unsigned)count;

/**
 * Write a double value to the stream. The double is written in a platform-independent
 * way and can be read using OLInStream#readDouble. Specifically, the value is written
 * as an 8-byte array in network byte order.
 *
 * @exception OLInputOutputException if there is an error writing to the stream
 * @param value the double value to write
 */
- (void) writeDouble: (double)value;

/**
 * Write a float value to the stream. The float is written in a platform-independent
 * way and can be read using OLInStream#readFloat. Specifically, the value is written
 * as a 4-byte array in network byte order.
 *
 * @exception OLInputOutputException if there is an error writing to the stream
 * @param value the float value to write
 */
- (void) writeFloat: (float)value;

/**
 * Write a integer value to the stream. The integer is written in a platform-independent
 * way and can be read using OLInStream#readInt. Specifically, the value is written
 * as a 4-byte array in network byte order.
 *
 * @note Regardless of the size of the type @c int on the platform being used, the value
 * written will always be exactly four bytes long.
 *
 * @exception OLInputOutputException if there is an error writing to the stream
 * @param value the integer value to write
 */
- (void) writeInt: (unsigned)value;

/**
 * Write a 16-bite integer value to the stream. The integer is written in a platform-independent
 * way and can be read using OLInStream#readInt16. Specifically, the value is written
 * as a 2-byte array in network byte order.
 *
 * @exception OLInputOutputException if there is an error writing to the stream
 * @param value the integer value to write
 */
- (void) writeInt16: (uint16_t)value;

/**
 * Write a 32-bit integer value to the stream. The integer is written in a platform-independent
 * way and can be read using OLInStream#readInt32. Specifically, the value is written
 * as a 4-byte array in network byte order.
 *
 * @exception OLInputOutputException if there is an error writing to the stream
 * @param value the integer value to write
 */
- (void) writeInt32: (uint32_t)value;

/**
 * Write a 64-bit integer value to the stream. The integer is written in a platform-independent
 * way and can be read using OLInStream#readInt64. Specifically, the value is written
 * as an 8-byte array in network byte order.
 *
 * @exception OLInputOutputException if there is an error writing to the stream
 * @param value the integer value to write
 */
- (void) writeInt64: (uint64_t)value;

/**
 * Write a string to the stream. The string is written in a platform-independent way
 * and can be read using OLInStream#readStringAsUTF8. The string is encoded as UTF-8
 * and can be arbitrarily long.
 *
 * @exception OLInputOutputException if there is an error writing to the stream
 * @param str the string to write
 */
- (void) writeStringAsUTF8: (NSString*)str;

/**
 * @name NSCoder Support
 *
 * Support the streaming of objects that adopt the NSCoding protocol
 */
/* @{ */
/**
 * Return whether the stream supports keyed coding. No stream classes in @b ObjectiveLib
 * support keyed coding, so this method will always return NO.
 *
 * @return NO, always
 */
- (BOOL) allowsKeyedCoding;

/**
 * Encode a buffer of data. This method is included solely to support objects that already
 * support the NSCoding protocol, and relies on the lower-level message #writeBytes:count:.
 * There is nothing to be gained by choosing to call this method explicitly over the
 * preferred method #writeBytes:count:.
 *
 * @exception OLInputOutputException if there is an error writing to the stream
 * @param address the address of the data to write
 * @param numBytes the number of bytes to write
 */
- (void) encodeBytes: (const void*)address length: (unsigned)numBytes;

/**
 * Encode a data object. This method is included solely to support objects that already
 * support the NSCoding protocol, and relies on the lower-level message #writeBytes:count:.
 * There is nothing to be gained by choosing to call this method explicitly over the
 * preferred method #writeBytes:count:.
 *
 * @exception OLInputOutputException if there is an error writing to the stream
 * @param data the data object to write
 */
- (void) encodeDataObject: (NSData*)data;

/**
 * Encode an object. This method is not implemented in OLOutStream. In order to write object
 * instances to a stream one must use the layered stream class OLObjectOutStream.
 *
 * @param object the object that this class should fail to write
 */
- (void) encodeObject: (id)object;

/**
 * Encode a value of a specified Objective-C type. Write a value of an arbitrary type to
 * the stream. Note that in order to preserve platform-independence in the resulting
 * stream, constraints are placed on how the data are written. Types that otherwise have
 * indeterminate sizes will always be normalized to sizes chosen by @b ObjectiveLib. The
 * sizes written are as follows:
 * <table border=0>
 * <tr><td><b>Type</b></td><td><b>Size</b></td></tr>
 * <tr><td>char</td><td>1</td></tr>
 * <tr><td>short</td><td>2</td></tr>
 * <tr><td>int</td><td>4</td></tr>
 * <tr><td>long</td><td>4</td></tr>
 * <tr><td>long long</td><td>8</td></tr>
 * </table>
 * @note Object instances and classes cannot be written using OLOutStream's implementation
 * of this method. OLObjectOutStream must be used.
 *
 * @exception OLInputOutputException if there is an error writing to the stream
 * @param valueType the type of the value at @a address
 * @param address the location of the value
 */
- (void) encodeValueOfObjCType: (const char*)valueType at: (const void*)address;
/* @} */

@end

#endif
