/* Network-Integrated Multimedia Middleware (NMM)
 * http://www.motama.com/nmm.html
 *  
 * Copyright (C) 2006-2007
 * Motama GmbH, Saarbruecken, Germany
 * http://www.motama.com
 *  
 * This file is part of NMM. 
 * 
 * NMM is free software; you can redistribute it and/or modify it    
 * under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; only version 2 of the License.      
 * 
 * NMM 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 General Public 
 * License for more details.  
 * 
 * You should have received a copy of the GNU General Public License 
 * along with NMM; if not, write to the Free Software Foundation,    
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#ifndef NMM_I_STREAM_HPP
#define NMM_I_STREAM_HPP NMM_I_STREAM_HPP

#include "nmm/nmm_prefix.hpp"

#include "SerializedValue.hpp"
#include "visibility.hpp"

#include "nmm/nmm_types.hpp"

#include <string>

using namespace std;

namespace NMM {

  template<typename T> class TValue;

  /** An input stream.
   * A stream defines defines a serialization method for all serializable types.
   * Input streams are used for reading data into variables being serialized.
   * This is the base class of all input stream classes.
   *
   * An input stream defines a serialization operator '>>' for every basic serializable type.
   * For other types, free serialization operators can be defined.
   *
   * Streams can have partner streams for layered serialization.
   * This allows the creation of serialization stacks.
   * This class provides an interface for setting and managing partner streams.
   *
   * @see OStream
   */
  class DLLEXPORT IStream
    : public SerializedValue
  {
  public:
    /** @name Constructor & Destructor
     */
    //@{
    /** Copy constructor.
     *
     * @param stream Stream object to copy from
     */
    IStream(const IStream& stream);

    /** Virtual copy constructor.
     *
     * @return A copy of this object which has the same type
     */
    IStream* copy() const = 0;

    /** Assignment operator.
     *
     * @param stream Stream object to assign from
     * @return *this
     */
    IStream& operator=(const IStream& stream);

    /** Virtual destructor.
     */
    virtual ~IStream();
    //@}

    /** @name Serialization Operator
     */
    //@{
    /** Input serialization operator.
     * This is the abstract input serialization operator for a basic type.
     * It must be implemented by subclasses.
     * Subclass implementations must have covariant return types.
     *
     * @param value Reference to variable to be serialized
     * @return *this 
     */
    virtual  IStream& operator>>(nmm_uint16& value)       = 0;

    /** Input serialization operator.
     * This is the abstract input serialization operator for a basic type.
     * It must be implemented by subclasses.
     * Subclass implementations must have covariant return types.
     *
     * @param value Reference to variable to be serialized
     * @return *this 
     */
    virtual  IStream& operator>>(nmm_int16& value)         = 0;

    /** Input serialization operator.
     * This is the abstract input serialization operator for a basic type.
     * It must be implemented by subclasses.
     * Subclass implementations must have covariant return types.
     *
     * @param value Reference to variable to be serialized
     * @return *this 
     */
    virtual  IStream& operator>>(nmm_uint32& value)     = 0;

    /** Input serialization operator.
     * This is the abstract input serialization operator for a basic type.
     * It must be implemented by subclasses.
     * Subclass implementations must have covariant return types.
     *
     * @param value Reference to variable to be serialized
     * @return *this 
     */
    virtual  IStream& operator>>(nmm_int32& value)       = 0;

    /** Input serialization operator.
     * This is the abstract input serialization operator for a basic type.
     * It must be implemented by subclasses.
     * Subclass implementations must have covariant return types.
     *
     * @param value Reference to variable to be serialized
     * @return *this 
     */
    virtual  IStream& operator>>(nmm_uint64& value)     = 0;

    /** Input serialization operator.
     * This is the abstract input serialization operator for a basic type.
     * It must be implemented by subclasses.
     * Subclass implementations must have covariant return types.
     *
     * @param value Reference to variable to be serialized
     * @return *this
     */
    virtual  IStream& operator>>(nmm_int64& value)       = 0;

    /** Input serialization operator.
     * This is the abstract input serialization operator for a basic type.
     * It must be implemented by subclasses.
     * Subclass implementations must have covariant return types.
     *
     * @param value Reference to variable to be serialized
     * @return *this 
     */
    virtual  IStream& operator>>(nmm_bool& value)          = 0;

    /** Input serialization operator.
     * This is the abstract input serialization operator for a basic type.
     * It must be implemented by subclasses.
     * Subclass implementations must have covariant return types.
     *
     * @param value Reference to variable to be serialized
     * @return *this 
     */
    virtual  IStream& operator>>(nmm_double& value)         = 0;

    /** Input serialization operator.
     * This is the abstract input serialization operator for a basic type.
     * It must be implemented by subclasses.
     * Subclass implementations must have covariant return types.
     *
     * @param value Reference to variable to be serialized
     * @return *this 
     */
    virtual  IStream& operator>>(nmm_float& value)          = 0;

    /** Input serialization operator.
     * This is the abstract input serialization operator for a basic type.
     * It must be implemented by subclasses.
     * Subclass implementations must have covariant return types.
     *
     * @param value Reference to variable to be serialized
     * @return *this
     */
    virtual  IStream& operator>>(nmm_char& value)           = 0;

    /** Input serialization operator.
     * This is the abstract input serialization operator for a basic type.
     * It must be implemented by subclasses.
     * Subclass implementations must have covariant return types.
     *
     * @param value Reference to variable to be serialized
     * @return *this
     */
    virtual  IStream& operator>>(nmm_uchar& value)   = 0;

    /** Input serialization operator.
     * This is the abstract input serialization operator for a basic type.
     * It must be implemented by subclasses.
     * Subclass implementations must have covariant return types.
     *
     * @param value Reference to variable to be serialized
     * @return *this
     */
    virtual  IStream& operator>>(string& value)          = 0;

    /** Read data for serialization.
     * This method must be called before using the serialization operators.
     * It fetches data internally.
     */
    virtual void readData() {}
    //@}

    /** @name Buffer Reading
     */
    //@{
    /** Read a line of text from this stream.
     * This method reads characters from the stream and stores them in a string
     * until it encounters an end-of-line character.
     *
     * @param value Returns the string containing the read characters
     * @param end_of_line End-of-line character
     */
    virtual void readLine(string& value, char end_of_line);

    /** Read raw data from this stream.
     * This method reads exactly the given number of raw bytes from the stream
     * and stores the read data in a buffer.
     *
     * @param buffer Pointer to buffer that stores the read data
     * @param size Number of bytes to read
     */
    virtual void readBuffer(char* buffer, nmm_uint32 size)        = 0   ;

    /** Read raw data from this stream.
     * This method reads exactly the given number of raw bytes from the stream
     * and stores the read data in a buffer.
     *
     * @param buffer Pointer to buffer that stores the read data
     * @param size Number of bytes to read
     */
    virtual void readBuffer(unsigned char* buffer, nmm_uint32 size) = 0;
    //@}

    /** @name Partner Streams
     */
    //@{
    /** Set the input partner stream.
     * This method sets the input partner stream of this stream.
     * This stream only stores a reference to the given partner stream (shallow copy).
     * The partner stream is not destroyed if this stream is destroyed.
     * It must not be destroyed while it is set as partner stream of this stream.
     *
     * @param partner_stream Pointer to the partner stream
     */
    void setIPartnerStream(IStream* partner_stream);

    /** Set the input partner stream.
     * This method sets the input partner stream of this stream.
     * This stream stores a deep copy of given partner stream as partner stream.
     * The copy is destroyed when this stream is destroyed.
     * The stream object passed to this method is only used as a source object for copying.
     *
     * @param partner_stream Pointer to a partner stream template
     */
    void setIPartnerStreamDeepCopy(const IStream* partner_stream);

    /** Get the input partner stream.
     * This method gets the input partner stream of this stream.
     * This method only returns a reference to the stream. The caller must not delete it.
     *
     * @return Pointer to input partner stream
     */
    IStream* getIPartnerStream();

    /** Get the input partner stream.
     * This method gets the input partner stream of this stream.
     * This method only returns a reference to the stream. The caller must not delete it.
     *
     * @return Pointer to input partner stream
     */
    const IStream* getIPartnerStream() const;

    /** Check if this stream is empty.
     * This method checks if this stream contains no data to read.
     * If this method returns @c true, serialization operations will fail.
     *
     * @return @c true if this stream is empty, @c false otherwise
     */
    virtual bool isEmpty()    const = 0;
    //@}
  protected:
    /** Subclass constructor.
     * This constructor must be used by subclasses when initializing the base class.
     * Every subclass must also define this subclass constructor as a protected constructor.
     *
     * @param ti Type information for this object
     */
    IStream(const TypeInfo& ti);
  
    /** Assignment.
     * This method implements the assignment operator.
     * It is used by the assignment operator and the copy constructor.
     */
    void assign(const IStream& stream);

    /** Register attributes for serialization.
     */
    void registerAttributes();

  private:
    bool     __own_partner_stream;          ///< Partner stream is a deep copy
    TValue<IStream*>* __partner_stream;     ///< Input partner stream
  };

}

#include "nmm/nmm_suffix.hpp"

#endif
