OutboundPacketStream& OutboundPacketStream::operator<<( const BeginMessage& rhs )
{
    if( IsMessageInProgress() )
        throw MessageInProgressException();

    CheckForAvailableMessageSpace( rhs.addressPattern );

    messageCursor_ = BeginElement( messageCursor_ );

    strcpy( messageCursor_, rhs.addressPattern );
    unsigned long rhsLength = strlen(rhs.addressPattern);
    messageCursor_ += rhsLength + 1;

    // zero pad to 4-byte boundary
    unsigned long i = rhsLength + 1;
    while( i & 0x3 ){
        *messageCursor_++ = '\0';
        ++i;
    }

    argumentCurrent_ = messageCursor_;
    typeTagsCurrent_ = end_;

    messageIsInProgress_ = true;

    return *this;
}
OutboundPacketStream& OutboundPacketStream::operator<<( const BeginMessage& rhs )
{
    check( !IsMessageInProgress() )

    state_ = CheckForAvailableMessageSpace( rhs.addressPattern );

    if(state_ == SUCCESS)
    {
        messageCursor_ = BeginElement( messageCursor_ );

        std::strcpy( messageCursor_, rhs.addressPattern );
        std::size_t rhsLength = std::strlen(rhs.addressPattern);
        messageCursor_ += rhsLength + 1;

        // zero pad to 4-byte boundary
        std::size_t i = rhsLength + 1;
        while( i & 0x3 ){
            *messageCursor_++ = '\0';
            ++i;
        }

        argumentCurrent_ = messageCursor_;
        typeTagsCurrent_ = end_;

        messageIsInProgress_ = true;
    }

    return *this;
}
unsigned int OutboundPacketStream::Size() const
{
    unsigned int result = argumentCurrent_ - data_;
    if( IsMessageInProgress() ){
        // account for the length of the type tag string. the total type tag
        // includes an initial comma, plus at least one terminating \0
        result += RoundUp4( (end_ - typeTagsCurrent_) + 2 );
    }

    return result;
}
OutboundPacketStream& OutboundPacketStream::operator<<( const BundleTerminator& rhs )
{
    (void) rhs;

    check( IsBundleInProgress() )
    check( !IsMessageInProgress() )

    EndElement( messageCursor_ );

    return *this;
}
OutboundPacketStream& OutboundPacketStream::operator<<( const BundleTerminator& rhs )
{
    (void) rhs;

    if( !IsBundleInProgress() )
        throw BundleNotInProgressException();
    if( IsMessageInProgress() )
        throw MessageInProgressException();

    EndElement( messageCursor_ );

    return *this;
}
	NxDeviceOscOutputMessage& NxDeviceOscOutputMessage::operator<<( const NxDeviceOscBundleTerminator& rhs )
	{
		(void) rhs;

		if( !IsBundleInProgress() )
			throw BundleNotInProgressException();
		if( IsMessageInProgress() )
			throw MessageInProgressException();

		EndElement( messageCursor_ );

		return *this;
	}
OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator& rhs )
{
    (void) rhs;

    if( !IsMessageInProgress() )
        throw MessageNotInProgressException();

    int typeTagsCount = end_ - typeTagsCurrent_;

    if( typeTagsCount ){

        char *tempTypeTags = (char*)alloca(typeTagsCount);
        memcpy( tempTypeTags, typeTagsCurrent_, typeTagsCount );

        // slot size includes comma and null terminator
        int typeTagSlotSize = RoundUp4( typeTagsCount + 2 );

        uint32 argumentsSize = argumentCurrent_ - messageCursor_;

        memmove( messageCursor_ + typeTagSlotSize, messageCursor_, argumentsSize );

        messageCursor_[0] = ',';
        // copy type tags in reverse (really forward) order
        for( int i=0; i < typeTagsCount; ++i )
            messageCursor_[i+1] = tempTypeTags[ (typeTagsCount-1) - i ];

        char *p = messageCursor_ + 1 + typeTagsCount;
        for( int i=0; i < (typeTagSlotSize - (typeTagsCount + 1)); ++i )
            *p++ = '\0';

        typeTagsCurrent_ = end_;

        // advance messageCursor_ for next message
        messageCursor_ += typeTagSlotSize + argumentsSize;

    }else{
        // send an empty type tags string
        memcpy( messageCursor_, ",\0\0\0", 4 );

        // advance messageCursor_ for next message
        messageCursor_ += 4;
    }

    argumentCurrent_ = messageCursor_;

    EndElement( messageCursor_ );

    messageIsInProgress_ = false;

    return *this;
}
OutboundPacketStream& OutboundPacketStream::operator<<( const BundleInitiator& rhs )
{
    if( IsMessageInProgress() )
        throw MessageInProgressException();

    CheckForAvailableBundleSpace();

    messageCursor_ = BeginElement( messageCursor_ );

    memcpy( messageCursor_, "#bundle\0", 8 );
    FromUInt64( messageCursor_ + 8, rhs.timeTag );

    messageCursor_ += 16;
    argumentCurrent_ = messageCursor_;

    return *this;
}
OutboundPacketStream& OutboundPacketStream::operator<<( const BundleInitiator& rhs )
{
    check( !IsMessageInProgress() )

    state_ = CheckForAvailableBundleSpace();
    if(state_ == SUCCESS)
    {
        messageCursor_ = BeginElement( messageCursor_ );

        std::memcpy( messageCursor_, "#bundle\0", 8 );
        FromUInt64( messageCursor_ + 8, rhs.timeTag );

        messageCursor_ += 16;
        argumentCurrent_ = messageCursor_;
    }

    return *this;
}
bool OutboundPacketStream::IsReady() const
{
    return (!IsMessageInProgress() && !IsBundleInProgress());
}
	bool NxDeviceOscOutputMessage::IsReady() const
	{
		return (!IsMessageInProgress() && !IsBundleInProgress());
	}