/*
 * Copyright (C) 1997-2003 by Objective Systems, Inc.
 *
 * This software is furnished under a license and may be used and copied
 * only in accordance with the terms of such license and with the
 * inclusion of the above copyright notice. This software or any other
 * copies thereof may not be provided or otherwise made available to any
 * other person. No title to and ownership of the software is hereby
 * transferred.
 *
 * The information in this software is subject to change without notice
 * and should not be construed as a commitment by Objective Systems, Inc.
 *
 * PROPRIETARY NOTICE
 *
 * This software is an unpublished work subject to a confidentiality agreement
 * and is protected by copyright and trade secret law.  Unauthorized copying,
 * redistribution or other use of this work is prohibited.
 *
 * The above notice of copyright on this source code product does not indicate
 * any actual or intended publication of such source code.
 *
 *****************************************************************************/

/** 
 * @file ASN1BEROutputStream.h 
 * The C++ definitions for ASN.1 BER output streams.
 */

#ifndef _ASN1BEROUTPUTSTREAM_H_
#define _ASN1BEROUTPUTSTREAM_H_

#include "asn1berStream.h"
#include "ASN1Stream.h"
#include "OSCSocket.h"

/** @defgroup oberstrmclas C++ classes for streaming BER encoding.
 * @ingroup bercppruntime 
 * These classes are used to perform BER encoding directly to a stream (file,
 * network, memory). @{
 */

/** @defgroup berstrmencwrappers Wrapper classes for BER encoding by using operator <<
 * These wrapper classes can be used for encoding with using the << operator.
 * For example: ASN1BEROutputStream os; ..... os << OSEncStrmTag (v1) <<
 * OSEncStrmLength (v2) << OSEncStrmNull (); @{
 */

/**
 * A wrapper class for encoding a tag value.
 */
struct EXTERNBER OSEncStrmTag {
   ASN1TAG value; ///< a value

   /** A constructor */
   OSEncStrmTag (ASN1TAG val) {
      value = val;
   }
   /** A constructor */
   OSEncStrmTag (const OSEncStrmTag& val) {
      value = val.value;
   }
} ;

/**
 * A wrapper class for encoding an indefinite length indicator value.
 */
struct EXTERNBER OSEncStrmIndefLen {
   /** A constructor */
   OSEncStrmIndefLen () {}
} ;
#define OSENCSTRMINDEFLEN OSEncStrmIndefLen()

/**
 * A wrapper class for encoding a tag value and indefinite length indicator.
 */
struct EXTERNBER OSEncStrmTagAndIndefLen : public OSEncStrmTag {
   /** A constructor */
   OSEncStrmTagAndIndefLen (ASN1TAG val) : OSEncStrmTag (val) { }
   /** A constructor */
   OSEncStrmTagAndIndefLen (const OSEncStrmTag& val) : OSEncStrmTag (val) { }
} ;

/**
 * A wrapper class for encoding a tag and length values.
 */
struct EXTERNBER OSEncStrmTagAndLen {
   ASN1TAG tag; ///< a tag
   ASN1INT len; ///< a length

   /** A constructor */
   OSEncStrmTagAndLen (ASN1TAG _tag, ASN1INT _len) : tag (_tag), len (_len) {}
   /** A constructor */
   OSEncStrmTagAndLen (const OSEncStrmTagAndLen& val) {
      tag = val.tag;
      len = val.len;
   }
} ;

/**
 * A wrapper class for encoding the end-of-contents octets.
 */
struct EXTERNBER OSEncStrmEoc {
   /** A constructor */
   OSEncStrmEoc () {}
} ;

#define OSENCSTRMEOC OSEncStrmEoc()

/**
 * A wrapper class for encoding an implicit integer value.
 */
struct EXTERNBER OSEncStrmImplInt : public OSEncStrmInt {
   /** A constructor */
   OSEncStrmImplInt (ASN1INT val) : OSEncStrmInt (val) { }
   /** A constructor */
   OSEncStrmImplInt (const OSEncStrmImplInt& val) : OSEncStrmInt (val) { }
} ;

/**
 * A wrapper class for encoding an implicit 8-bit integer value.
 */
struct EXTERNBER OSEncStrmImplInt8 : public OSEncStrmInt8 {
   /** A constructor */
   OSEncStrmImplInt8 (ASN1INT8 val) : OSEncStrmInt8 (val) { }
   /** A constructor */
   OSEncStrmImplInt8 (const OSEncStrmImplInt8& val) : OSEncStrmInt8 (val) { }
} ;

/**
 * A wrapper class for encoding an implicit 16-bit integer value.
 */
struct EXTERNBER OSEncStrmImplInt16 : public OSEncStrmInt16 {
   /** A constructor */
   OSEncStrmImplInt16 (ASN1SINT val) : OSEncStrmInt16 (val) { }
   /** A constructor */
   OSEncStrmImplInt16 (const OSEncStrmImplInt16& val) : OSEncStrmInt16 (val) { }
} ;

/**
 * A wrapper class for encoding an implicit 64-bit integer value.
 */
struct EXTERNBER OSEncStrmImplInt64 : public OSEncStrmInt64 {
   /** A constructor */
   OSEncStrmImplInt64 (ASN1INT64 val) : OSEncStrmInt64 (val) { }
   /** A constructor */
   OSEncStrmImplInt64 (const OSEncStrmImplInt64& val) : OSEncStrmInt64 (val) { }
} ;

/**
 * A wrapper class for encoding an implicit unsigned integer value.
 */
struct EXTERNBER OSEncStrmImplUInt : public OSEncStrmUInt {
   /** A constructor */
   OSEncStrmImplUInt (ASN1UINT val) : OSEncStrmUInt (val) { }
   /** A constructor */
   OSEncStrmImplUInt (const OSEncStrmImplUInt& val) : OSEncStrmUInt (val) { }
} ;

/**
 * A wrapper class for encoding an implicit 8-bit unsigned integer value.
 */
struct EXTERNBER OSEncStrmImplUInt8 : public OSEncStrmUInt8 {
   /** A constructor */
   OSEncStrmImplUInt8 (ASN1UINT8 val) : OSEncStrmUInt8 (val) { }
   /** A constructor */
   OSEncStrmImplUInt8 (const OSEncStrmImplUInt8& val) : OSEncStrmUInt8 (val) { }
} ;

/**
 * A wrapper class for encoding an implicit 16-bit unsigned integer value.
 */
struct EXTERNBER OSEncStrmImplUInt16 : public OSEncStrmUInt16 {
   /** A constructor */
   OSEncStrmImplUInt16 (ASN1USINT val) : OSEncStrmUInt16 (val) { }
   /** A constructor */
   OSEncStrmImplUInt16 (const OSEncStrmImplUInt16& val) : OSEncStrmUInt16 (val) { }
} ;

/**
 * A wrapper class for encoding an implicit 64-bit unsigned integer value.
 */
struct EXTERNBER OSEncStrmImplUInt64 : public OSEncStrmUInt64 {
   /** A constructor */
   OSEncStrmImplUInt64 (ASN1UINT64 val) : OSEncStrmUInt64 (val) { }
   /** A constructor */
   OSEncStrmImplUInt64 (const OSEncStrmImplUInt64& val) : OSEncStrmUInt64 (val) { }
} ;

/**
 * A wrapper class for encoding an implicit ENUMERATED value.
 */
struct EXTERNBER OSEncStrmImplEnum : public OSEncStrmEnum {
   /** A constructor */
   OSEncStrmImplEnum (ASN1ENUM val) : OSEncStrmEnum (val) { }
   /** A constructor */
   OSEncStrmImplEnum (const OSEncStrmUInt& val) : OSEncStrmEnum (val.value) {}
} ;

/**
 * A wrapper class for encoding an implicit big integer value.
 */
struct EXTERNBER OSEncStrmImplBigInt : public OSEncStrmBigInt {
   /** A constructor */
   OSEncStrmImplBigInt (const char* pval) : OSEncStrmBigInt (pval) { }
   /** A constructor */
   OSEncStrmImplBigInt (const OSEncStrmImplBigInt& val) : OSEncStrmBigInt (val) { }
} ;

/**
 * A wrapper class for encoding an implicit REAL value.
 */
struct EXTERNBER OSEncStrmImplReal : public OSEncStrmReal {
   /** A constructor */
   OSEncStrmImplReal (ASN1REAL val) : OSEncStrmReal (val) { }
   /** A constructor */
   OSEncStrmImplReal (const OSEncStrmImplReal& val) : OSEncStrmReal (val) { }
} ;

/**
 * A wrapper class for encoding an implicit bit string value.
 */
struct EXTERNBER OSEncStrmImplBitStr : public OSEncStrmBitStr {
   /** A constructor */
   OSEncStrmImplBitStr (ASN1UINT _numbits, const ASN1OCTET* _data) : 
      OSEncStrmBitStr (_numbits, _data) { }

   /** A constructor */
   OSEncStrmImplBitStr (ASN1DynBitStr& _bs) : OSEncStrmBitStr (_bs) { } 
} ;

/**
 * A wrapper class for encoding an implicit octet string value.
 */
struct EXTERNBER OSEncStrmImplOctStr : public OSEncStrmOctStr {
   /** A constructor */
   OSEncStrmImplOctStr (ASN1UINT _numocts, const ASN1OCTET* _data) :
      OSEncStrmOctStr (_numocts, _data) { }

   /** A constructor */
   OSEncStrmImplOctStr (ASN1DynOctStr& _os) : 
      OSEncStrmOctStr (_os) { }

} ;

/**
 * A wrapper class for encoding an implicit boolean value.
 */
struct EXTERNBER OSEncStrmImplBool : public OSEncStrmBool {
   /** A constructor */
   OSEncStrmImplBool (ASN1BOOL val) : OSEncStrmBool (val) { }
   /** A constructor */
   OSEncStrmImplBool (const OSEncStrmImplBool& val) : OSEncStrmBool (val) { }
} ;

/**
 * A wrapper class for encoding an implicit character string value.
 */
typedef OSEncStrmCharStr OSEncStrmImplCharStr;

/**
 * A wrapper class for encoding an implicit OBJECT IDENTIFIER value.
 */
struct EXTERNBER OSEncStrmImplObjId : public OSEncStrmObjId {
   /** A constructor */
   OSEncStrmImplObjId (const ASN1OBJID& oid) : OSEncStrmObjId (oid) {}
   /** A constructor */
   OSEncStrmImplObjId (const OSEncStrmObjId& oid) : OSEncStrmObjId (oid) {}
} ;

/**
 * A wrapper class for encoding an implicit RELATIVE-OID value.
 */
struct EXTERNBER OSEncStrmImplRelativeOID : public OSEncStrmObjId {
   /** A constructor */
   OSEncStrmImplRelativeOID (const ASN1OBJID& oid) : OSEncStrmObjId (oid) {}
   /** A constructor */
   OSEncStrmImplRelativeOID (const OSEncStrmObjId& oid) : OSEncStrmObjId (oid) {}
} ;

/**
 * A wrapper class for encoding an implicit NULL value.
 */
struct EXTERNBER OSEncStrmImplNull {};

/**
 * A wrapper class for encoding an implicit BMPString value.
 */
struct EXTERNBER OSEncStrmImplBMPString : public OSEncStrmBMPString {
   /** A constructor */
   OSEncStrmImplBMPString (const Asn116BitCharString& val) :
      OSEncStrmBMPString (val) { }
} ;

/**
 * A wrapper class for encoding an implicit UniversalString value.
 */
struct EXTERNBER OSEncStrmImplUnivString : public OSEncStrmUnivString {
   /** A constructor */
   OSEncStrmImplUnivString (const Asn132BitCharString& val) :
      OSEncStrmUnivString (val) { }
} ;

/** @} */

/**
 * This class is a base class for other ASN.1 BER output stream's classes. It
 * is derived from the ASN1Stream base class. It contains variables and methods
 * specific to streaming encoding of BER messages.
 */
class EXTERNBER ASN1BEROutputStream : public ASN1Stream {
 protected:
   /**
    * A default constructor.
    *
    * @exception OSCStreamException    stream can't be created or initialized.
    */
   ASN1BEROutputStream () { }
 public:
   /**
    * Encodes a tag value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmTag& val); 

   /**
    * Encodes an indefinite length indicator to the stream.
    *
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmIndefLen&); 

   /**
    * Encodes a tag value and indefinite length indicator to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmTagAndIndefLen& val); 

   /**
    * Encodes a tag value and length determinant to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmTagAndLen& val); 

   /**
    * Encodes the end-of-contents octets to the stream.
    *
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmEoc&); 

   /**
    * Encodes an integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmInt& val); 

   /**
    * Encodes an implicit integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplInt& val); 

   /**
    * Encodes an 8-bit integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmInt8& val); 

   /**
    * Encodes an implicit 8-bit integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplInt8& val); 

   /**
    * Encodes a 16-bit integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmInt16& val); 

   /**
    * Encodes an implicit 16-bit integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplInt16& val); 

   /**
    * Encodes a 64-bit integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmInt64& val); 

   /**
    * Encodes an implicit 64-bit integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplInt64& val); 

   /**
    * Encodes an unsigned integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmUInt& val); 

   /**
    * Encodes an implicit unsigned integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplUInt& val); 

   /**
    * Encodes an 8-bit unsigned integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmUInt8& val); 

   /**
    * Encodes an implicit 8-bit unsigned integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplUInt8& val); 

   /**
    * Encodes a 16-bit unsigned integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmUInt16& val); 

   /**
    * Encodes an implicit 16-bit unsigned integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplUInt16& val); 

   /**
    * Encodes a 64-bit unsigned integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmUInt64& val); 

   /**
    * Encodes an implicit 64-bit unsigned integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplUInt64& val); 

   /**
    * Encodes a big integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmBigInt& val); 

   /**
    * Encodes an implicit big integer value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplBigInt& val); 

   /**
    * Encodes an enumerated value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmEnum& val); 

   /**
    * Encodes an implicit enumerated value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplEnum& val); 

   /**
    * Encodes a boolean value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmBool& val); 

   /**
    * Encodes an implicit boolean value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplBool& val); 

   /**
    * Encodes a real value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmReal& val); 

   /**
    * Encodes an implicit real value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplReal& val); 

   /**
    * Encodes a bit string value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmBitStr& val); 

   /**
    * Encodes an implicit bit string value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplBitStr& val); 

   /**
    * Encodes an octet string value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmOctStr& val); 

   /**
    * Encodes an implicit octet string value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplOctStr& val); 

   /**
    * Encodes a character string value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmCharStr& val); 

   /**
    * Encodes an OBJECT IDENTIFIER value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmObjId& val); 

   /**
    * Encodes an implicit OBJECT IDENTIFIER value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplObjId& val); 

   /**
    * Encodes a RELATIVE-OID value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmRelativeOID& val); 

   /**
    * Encodes an implicit RELATIVE-OID value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplRelativeOID& val); 

   /**
    * Encodes a NULL value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmNull& val); 

   /**
    * Encodes an implicit NULL value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplNull& val); 

   /**
    * Encodes a BMPString value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmBMPString& val); 

   /**
    * Encodes an implicit BMPString value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplBMPString& val); 

   /**
    * Encodes an UniversalString value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmUnivString& val); 

   /**
    * Encodes an implicit UniversalString value to the stream.
    *
    * @param val          A reference to a wrapper class with a value to be
    *                       encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (const OSEncStrmImplUnivString& val); 

   /**
    * Encodes an ASN.1 constructed object to the stream.
    *
    * @param val          A reference to an object to be encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   ASN1BEROutputStream& operator << (ASN1CType& val); 



   /**
    * This method encodes a variable of the ASN.1 BMPString type that is based
    * on a 16-bit character sets.
    *
    * @param val                       A reference to a structure representing
    *                                    a 16-bit character string to be
    *                                    encoded. This structure contains a
    *                                    character count element and a pointer
    *                                    to an array of 16-bit character
    *                                    elements represented as 16-bit short
    *                                    integers.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmBMPStr
    */
   void encodeBMPStr (const Asn116BitCharString& val, ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes a variable of the ASN.1 INTEGER type. In this case,
    * the integer is assumed to be of a larger size than can fit in a C or C++
    * long type (normally 32 or 64 bits).
    *
    * @param *pval                     A pointer to a character string
    *                                    containing the value to be encoded.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmBigInt
    */
   void encodeBigInt (const char *pval, ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes a variable of the ASN.1 BIT STRING type.
    *
    * @param pbits                     A pointer to an OCTET string containing
    *                                    the bit data to be encoded. This
    *                                    string contains bytes having the
    *                                    actual bit settings as they are to be
    *                                    encoded in the message.
    * @param numbits                   The number of bits within the bit string
    *                                    to be encoded.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmBitStr
    */
   void encodeBitStr (const ASN1OCTET* pbits, ASN1UINT numbits, 
                      ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes a variable of the ASN.1 BIT STRING type.
    *
    * @param val                       A reference to the ASN1DynBitStr
    *                                    structure containing a bit data and
    *                                    number of bits to be encoded.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmBitStr
    */
   void encodeBitStr (const ASN1DynBitStr& val, ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes a variable of the ASN.1 BOOLEAN type.
    *
    * @param val                       A BOOLEAN value to be encoded. A BOOLEAN
    *                                    is defined as a single OCTET whose
    *                                    value is 0 for FALSE and any other
    *                                    value for TRUE.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmBool
    */
   void encodeBool (ASN1BOOL val, ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes a variable of the ASN.1 character string type.
    *
    * @param pval                      A pointer to a null-terminated C
    *                                    character string to be encoded.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @param tag                       The ASN.1 tag to be encoded in the
    *                                    message. This parameter is passed
    *                                    using the ASN1C internal tag
    *                                    representation. It is passed as an
    *                                    unsigned 32-bit integer.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmCharStr
    */
   void encodeCharStr (const char* pval, ASN1TagType tagging = ASN1EXPL, 
                       ASN1TAG tag = 0);

   /**
    * This method encodes a variable of the ASN.1 ENUMERATED type. The
    * enumerated encoding is identical to that of an integer. The compiler adds
    * additional checks to the generated code to ensure the value is within the
    * given set.
    *
    * @param val                       An integer containing the enumerated
    *                                    value to be encoded.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmEnum
    */
   void encodeEnum (ASN1ENUM val, ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes end-of-contents octets (EOC) into the stream. EOC is
    * two zero octets (it is documented in the X.690 standard). This method
    * must be called when the encoding of the complex type with indefinite
    * length is finishing.
    *
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmEOC,
    *                                    ::berEncStrmTagAndIndefLen,
    */
   void encodeEoc ();

   /**
    * This method is used to encode the indefinite length indicator. This can
    * be used to manually create an indefinite length wrapper around long or
    * constructed records.
    *
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmWriteOctet
    */
   void encodeIndefLen ();

   /**
    * This method encodes a variable of the ASN.1 INTEGER type.
    *
    * @param val                       A 32-bit INTEGER value to be encoded.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmInt
    */
   void encodeInt (ASN1INT val, ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes an 8-bit variable of the ASN.1 INTEGER type.
    *
    * @param val                       An 8-bit INTEGER value to be encoded.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmInt8
    */
   void encodeInt8 (ASN1INT8 val, ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes a 16-bit variable of the ASN.1 INTEGER type.
    *
    * @param val                       A 16-bit INTEGER value to be encoded.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmInt16
    */
   void encodeInt16 (ASN1SINT val, ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes a 64-bit variable of the ASN.1 INTEGER type.
    *
    * @param val                       A 64-bit INTEGER value to be encoded.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmInt64
    */
   void encodeInt64 (ASN1INT64 val, ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes a variable of the ASN.1 NULL type.
    *
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmRelativeOID
    */
   void encodeNull (ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes an ASN.1 constructed object to the stream.
    *
    * @param val          A reference to an object to be encoded.
    * @return             reference to this class to perform sequential
    *                       encoding.
    */
   void encodeObj (ASN1CType& val);

   /**
    * This method encodes a variable of the ASN.1 OBJECT IDENTIFIER type.
    *
    * @param val                       A reference to an object identifier
    *                                    structure. This structure contains an
    *                                    integer to hold the number of
    *                                    subidentifers in the object and an
    *                                    array to hold the subidentifier
    *                                    values.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmObjId
    */
   void encodeObjId (const ASN1OBJID& val, ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes a variable of the ASN.1 OBJECT IDENTIFIER type using
    * 64-bit subidentifiers.
    *
    * @param val                       A reference to a 64-bit object
    *                                    identifier structure. This structure
    *                                    contains an integer to hold the number
    *                                    of subidentifers in the object and an
    *                                    array of 64-bit unsigned integers to
    *                                    hold the subidentifier values.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmObjId64
    */
   void encodeObjId64 (const ASN1OID64& val, ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes a variable of the ASN.1 OCTET STRING type.
    *
    * @param pocts                     A pointer to an OCTET STRING containing
    *                                    the octet data to be encoded.
    * @param numocts                   The number of octets (bytes) within the
    *                                    OCTET STRING to be encoded.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmOctStr
    */
   void encodeOctStr (const ASN1OCTET* pocts, ASN1UINT numocts, 
                      ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes a variable of the ASN.1 OCTET STRING type.
    *
    * @param val                       A reference to the ASN1DynOctStr
    *                                    structure containing an octet data and
    *                                    number of octets to be encoded.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmOctStr
    */
   void encodeOctStr (const ASN1DynOctStr& val, ASN1TagType tagging = ASN1EXPL);
   
   /**
    * This method encodes a variable of the REAL data type. It provides support
    * for the plus-infinity and minus-infinity special real values. Use the
    * ::rtGetPlusInfinity or ::rtGetMinusInfinity functions to get these
    * special values.
    *
    * @param val                       An ASN1REAL data type. This is defined
    *                                    to be the C double type. Special real
    *                                    values plus and minus infinity are
    *                                    encoded by using the
    *                                    ::rtGetPlusInfinity and
    *                                    ::rtGetMinusInfinity functions to set
    *                                    the real value to be encoded.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmReal
    */
   void encodeReal (ASN1REAL val, ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes a variable of the ASN.1 RELATIVE-OID type.
    *
    * @param val                       A reference to an object identifier
    *                                    structure. This structure contains an
    *                                    integer to hold the number of
    *                                    subidentifers in the object and an
    *                                    array to hold the subidentifier
    *                                    values.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmRelativeOID
    */
   void encodeRelativeOID (const ASN1OBJID& val, ASN1TagType tagging = ASN1EXPL);

   /**
    * This method is used to encode the ASN.1 tag field that preface each block
    * of message data. The ASN1C compiler generates calls to this function to
    * handle the encoding of user-defined tags within an ASN.1 specification.
    *
    * @param tag                       The ASN.1 tag to be encoded in the
    *                                    message. This parameter is passed
    *                                    using the ASN1C internal tag
    *                                    representation. It is passed as an
    *                                    unsigned 32-bit integer.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmTag
    */
   void encodeTag (ASN1TAG tag);

   /**
    * This method is used to encode a tag value and an indefinite length. This
    * can be used to manually create an indefinite length wrapper around long
    * or constructed records.
    *
    * @param tag                       The ASN.1 tag to be encoded in the
    *                                    message. This parameter is passed
    *                                    using the ASN1C internal tag
    *                                    representation. It is passed as an
    *                                    unsigned 32-bit integer.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmTagAndIndefLen
    */
   void encodeTagAndIndefLen (ASN1TAG tag);

   /**
    * This method is used to encode the ASN.1 tag and length fields that
    * preface each block of message data.
    *
    * @param tag                       The ASN.1 tag to be encoded in the
    *                                    message. This parameter is passed
    *                                    using the ASN1C internal tag
    *                                    representation. It is passed as an
    *                                    unsigned 32-bit integer.
    * @param len                       The length of the contents field. This
    *                                    parameter can be used to specify the
    *                                    actual length, or the special constant
    *                                    'ASN_K_INDEFLEN' can be used to
    *                                    specify that an indefinite length
    *                                    specification should be encoded.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmTagAndLen
    */
   void encodeTagAndLen (ASN1TAG tag, ASN1INT len);
   
   /**
    * This method encodes an unsigned variable of the ASN.1 INTEGER type.
    *
    * @param val                     An unsigned INTEGER value to be encoded.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmUInt
    */
   void encodeUInt (ASN1UINT val, ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes an 8-bit unsigned variable of the ASN.1 INTEGER type.
    *
    * @param val                     An 8-bit unsigned INTEGER value to be
    *                                    encoded.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmUInt8
    */
   void encodeUInt8 (ASN1UINT8 val, ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes a 16-bit unsigned variable of the ASN.1 INTEGER type.
    *
    * @param val                     A 16-bit unsigned INTEGER value to be
    *                                    encoded.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmUInt16
    */
   void encodeUInt16 (ASN1USINT val, ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes a 64-bit unsigned variable of the ASN.1 INTEGER type.
    *
    * @param val                     A 64-bit unsigned INTEGER value to be
    *                                    encoded.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmUInt64
    */
   void encodeUInt64 (ASN1UINT64 val, ASN1TagType tagging = ASN1EXPL);

   /**
    * This method encodes a variable of the ASN.1 UniversalString type that is
    * based on a 32-bit character sets.
    *
    * @param val                       A reference to a structure representing
    *                                    a 32-bit character string to be
    *                                    encoded. This structure contains a
    *                                    character count element and a pointer
    *                                    to an array of 32-bit character
    *                                    elements represented as 32-bit
    *                                    unsigned integers.
    * @param tagging                   An enumerated type whose value is set to
    *                                    either 'ASN1EXPL' (for explicit
    *                                    tagging) or 'ASN1IMPL' (for implicit).
    *                                    Controls whether the universal tag
    *                                    value for this type is added or not.
    *                                    Users will generally always set this
    *                                    value to 'ASN1EXPL'.
    * @exception OSCStreamException    if error occurred.
    * @see                            ::berEncStrmUnivStr
    */
   void encodeUnivStr (const Asn132BitCharString& val, ASN1TagType tagging = ASN1EXPL);

} ;

/**
 * A file output stream for streaming BER encoding. This class writes data to a
 * file.
 */
class EXTERNBER ASN1BERFileOutputStream : public ASN1BEROutputStream {
 public:
   /**
    * Creates and initializes the file output stream using the name of file.
    *
    * @param pFilename                 Name of file.
    * @exception OSCStreamException    stream can't be created or initialized.
    * @see                            ::rtStreamFileOpen
    */
   ASN1BERFileOutputStream (const char* pFilename);

   /**
    * Initializes the file output stream using the opened FILE structure
    * descriptor.
    *
    * @param file                      Pointer to FILE structure.
    * @exception OSCStreamException    stream can't be created or initialized.
    * @see                            ::rtStreamFileAttach
    */
   ASN1BERFileOutputStream (FILE* file);
} ;

/**
 * A socket output stream for streaming BER encoding. This class writes data
 * directly to a network via TCP/IP socket.
 */
class EXTERNBER ASN1BERSocketOutputStream : public ASN1BEROutputStream {
 protected:
   OSCSocket mSocket; ///< a socket 
 public:
   /**
    * Creates and initializes the socket output stream using the socket's
    * handle.
    *
    * @param socket                    Handle of the socket.
    * @param ownership                 Indicates the ownership of the socket's
    *                                    handle.
    * @exception OSCStreamException    stream can't be created or initialized.
    * @see                            ::rtSocketCreate, ::rtSocketAccept
    * @see                            ::rtStreamSocketAttach
    */
   ASN1BERSocketOutputStream (OSRTSOCKET socket, ASN1BOOL ownership = FALSE);

   /**
    * Initializes the socket output stream using the OSCSocket class' instance.
    *
    * @param socket                    Reference to OSCSocket class' instance.
    * @exception OSCStreamException    stream can't be created or initialized.
    */
   ASN1BERSocketOutputStream (OSCSocket& socket);
} ;

/** @} */
#endif /* _ASN1BEROUTPUTSTREAM_H_ */

