text: /*
   *
   *  Copyright (C) 1994-2010, OFFIS e.V.
   *  All rights reserved.  See COPYRIGHT file for details.
   *
   *  This software and supporting documentation were developed by
   *
   *    OFFIS e.V.
   *    R&D Division Health
   *    Escherweg 2
   *    D-26121 Oldenburg, Germany
   *
   *
   *  Module:  dcmdata
   *
   *  Author:  Marco Eichelberg
   *
   *  Purpose: base classes for input streams
   *
   *  Last Update:      $Author: joergr $
   *  Update Date:      $Date: 2010-10-14 13:15:41 $
   *  CVS/RCS Revision: $Revision: 1.5 $
   *  Status:           $State: Exp $
   *
   *  CVS/RCS Log at end of file
   *
   */
  
  #ifndef DCISTRMA_H
  #define DCISTRMA_H
  
  #include "dcmtk/config/osconfig.h"
  #include "dcmtk/ofstd/oftypes.h"  /* for OFBool */
  #include "dcmtk/ofstd/ofcond.h"   /* for OFCondition */
  #include "dcmtk/ofstd/offile.h"   /* for offile_off_t */
  #include "dcmtk/dcmdata/dcxfer.h"   /* for E_StreamCompression */
  
  class DcmInputStream;
  
  /** pure virtual abstract base class for producers, i.e. the initial node 
   *  of a filter chain in an input stream.
   */
  class DcmProducer
  {
  public:
  
    /// destructor
    virtual ~DcmProducer()
    {
    }
  
    /** returns the status of the producer. Unless the status is good,
     *  the producer will not permit any operation.
     *  @return status, true if good
     */
    virtual OFBool good() const = 0;
  
    /** returns the status of the producer as an OFCondition object.
     *  Unless the status is good, the producer will not permit any operation.
     *  @return status, EC_Normal if good
     */
    virtual OFCondition status() const = 0;
  
    /** returns true if the producer is at the end of stream.
     *  @return true if end of stream, false otherwise
     */
    virtual OFBool eos() = 0;
  
    /** returns the minimum number of bytes that can be read with the
     *  next call to read(). The DcmObject read methods rely on avail
     *  to return a value > 0 if there is no I/O suspension since certain
     *  data such as tag and length are only read "en bloc", i.e. all
     *  or nothing.
     *  @return minimum of data available in producer
     */
    virtual offile_off_t avail() = 0;
  
    /** reads as many bytes as possible into the given block.
     *  @param buf pointer to memory block, must not be NULL
     *  @param buflen length of memory block
     *  @return number of bytes actually read. 
     */
    virtual offile_off_t read(void *buf, offile_off_t buflen) = 0;
  
    /** skips over the given number of bytes (or less)
     *  @param skiplen number of bytes to skip
     *  @return number of bytes actually skipped. 
     */
    virtual offile_off_t skip(offile_off_t skiplen) = 0;
  
    /** resets the stream to the position by the given number of bytes.
     *  @param num number of bytes to putback. If the putback operation
     *    fails, the producer status becomes bad. 
     */
    virtual void putback(offile_off_t num) = 0;
  
  };
  
  
  /** pure virtual abstract base class for input filters, i.e. 
   *  intermediate nodes of a filter chain in an input stream.
   */
  class DcmInputFilter: public DcmProducer
  {
  public:
  
    /// destructor
    virtual ~DcmInputFilter()
    {
    }
  
    /** determines the producer from which the filter is supposed
     *  to read it's input. Once a producer for the input filter has 
     *  been defined, it cannot be changed anymore during the lifetime
     *  of the object.
     *  @param producer reference to producer, must not be circular chain
     */
    virtual void append(DcmProducer& producer) = 0;
  };
  
  
  /** pure virtual abstract base class for input stream factories,
   *  i.e. objects that can create a new input stream
   */
  class DcmInputStreamFactory
  {
  public:
  
    /// destructor
    virtual ~DcmInputStreamFactory()
    {
    }
  
    /** create a new input stream object
     *  @return pointer to new input stream object
     */
    virtual DcmInputStream *create() const = 0;
  
    /** returns a pointer to a copy of this object
     */
    virtual DcmInputStreamFactory *clone() const = 0;
  };
  
  
  /** abstract base class for input streams.
   */
  class DcmInputStream
  {
  public:
  
    /// destructor
    virtual ~DcmInputStream();
  
    /** returns the status of the stream. Unless the status is good,
     *  the stream will not permit any operation.
     *  @return status, true if good
     */
    virtual OFBool good() const;
  
    /** returns the status of the stream as an OFCondition object.
     *  Unless the status is good, the stream will not permit any operation.
     *  @return status, EC_Normal if good
     */
    virtual OFCondition status() const;
  
    /** returns true if the producer is at the end of stream.
     *  @return true if end of stream, false otherwise
     */
    virtual OFBool eos();
  
    /** returns the minimum number of bytes that can be read with the
     *  next call to read(). The DcmObject read methods rely on avail
     *  to return a value > 0 if there is no I/O suspension since certain
     *  data such as tag and length are only read "en bloc", i.e. all
     *  or nothing.
     *  @return minimum of data available in producer
     */
    virtual offile_off_t avail();
  
    /** reads as many bytes as possible into the given block.
     *  @param buf pointer to memory block, must not be NULL
     *  @param buflen length of memory block
     *  @return number of bytes actually read. 
     */
    virtual offile_off_t read(void *buf, offile_off_t buflen);
  
    /** skips over the given number of bytes (or less)
     *  @param skiplen number of bytes to skip
     *  @return number of bytes actually skipped. 
     */
    virtual offile_off_t skip(offile_off_t skiplen);
  
    /** returns the total number of bytes read from the stream so far
     *  @return total number of bytes read from the stream
     */
    virtual offile_off_t tell() const;
  
    /** installs a compression filter for the given stream compression type,
     *  which should be neither ESC_none nor ESC_unsupported. Once a compression
     *  filter is active, it cannot be deactivated or replaced during the
     *  lifetime of the stream.
     *  @param filterType type of compression filter
     *  @return EC_Normal if successful, an error code otherwise
     */
    virtual OFCondition installCompressionFilter(E_StreamCompression filterType);
  
    /** creates a new factory object for the current stream
     *  and stream position.  When activated, the factory will be
     *  able to create new DcmInputStream delivering the same
     *  data as the current stream.  Used to defer loading of
     *  value fields until accessed.
     *  If no factory object can be created (e.g. because the
     *  stream is not seekable), returns NULL.
     *  @return pointer to new factory object if successful, NULL otherwise.
     */
    virtual DcmInputStreamFactory *newFactory() const = 0;
  
    /** marks the current stream position for a later putback operation,
     *  overwriting a possibly existing prior putback mark.
     *  The DcmObject read methods rely on the possibility to putback
     *  up to 132 bytes for transfer syntax detection, parse error recovery etc.
     *  Implementations of this class should guarantee a putback capability
     *  of at least 1 kbyte.
     */
    virtual void mark();
  
    /** resets the stream to the position previously marked with
     *  setPutbackMark(). If the putback operation fails (no putback mark 
     *  set or putback buffer exceeded), status of the producer switches to bad.
     */
    virtual void putback();
  
  protected:
  
    /** protected constructor, to be called from derived class constructor
     *  @param initial initial pointer to first node in filter chain
     *     The pointer is not dereferenced in the constructor, so the
     *     object pointed to may be initialized later in the subclass
     *     constructor.
     */
    DcmInputStream(DcmProducer *initial);
  
    /** returns pointer to current producer object
     */
    const DcmProducer *currentProducer() const;
  
  private:
  
    /// private unimplemented copy constructor
    DcmInputStream(const DcmInputStream&);
  
    /// private unimplemented copy assignment operator
    DcmInputStream& operator=(const DcmInputStream&);
  
    /// pointer to first node in filter chain
    DcmProducer *current_;
  
    /// pointer to compression filter, NULL if no compression
    DcmInputFilter *compressionFilter_;
  
    /// counter for number of bytes read so far
    offile_off_t tell_;
  
    /// putback marker
    offile_off_t mark_;
  };
  
  
  
  #endif
  
  /*
   * CVS/RCS Log:
   * $Log: dcistrma.h,v $
   * Revision 1.5  2010-10-14 13:15:41  joergr
   * Updated copyright header. Added reference to COPYRIGHT file.
   *
   * Revision 1.4  2009-11-04 09:58:07  uli
   * Switched to logging mechanism provided by the "new" oflog module
   *
   * Revision 1.3  2007-02-19 15:45:41  meichel
   * Class DcmInputStream and related classes are now safe for use with
   *   large files (2 GBytes or more) if supported by compiler and operating system.
   *
   * Revision 1.2  2005/12/08 16:28:15  meichel
   * Changed include path schema for all DCMTK header files
   *
   * Revision 1.1  2002/08/27 16:55:32  meichel
   * Initial release of new DICOM I/O stream classes that add support for stream
   *   compression (deflated little endian explicit VR transfer syntax)
   *
   *
   */
  
  