/*
 * --- GSMP-COPYRIGHT-NOTE-BEGIN ---
 * 
 * This copyright note is auto-generated by ./scripts/Create-CopyPatch.
 * Please add additional copyright information _after_ the line containing
 * the GSMP-COPYRIGHT-NOTE-END tag. Otherwise it might get removed by
 * the ./scripts/Create-CopyPatch script. Do not edit this copyright text!
 * 
 * GSMP: pcm/include/PcmBuffer.hh
 * General Sound Manipulation Program is Copyright (C) 2000 - 2004
 *   Valentin Ziegler and René Rebe
 * 
 * This program 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; version 2. A copy of the GNU General
 * Public License can be found in the file LICENSE.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT-
 * ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 * Public License for more details.
 * 
 * --- GSMP-COPYRIGHT-NOTE-END ---
 */

/* Short Description:
 *   A buffer managing the Pulse Code Modulation data inside a buffer
 *   with bounds checking.
 */

#ifndef LOWLEVEL__PCMBUFFER_HH__
#define LOWLEVEL__PCMBUFFER_HH__

#include "Types.hh"
#include "Logging.hh"

namespace GSMP {

  template<typename T, typename E = HostEndianessTraits>
  class PcmBuffer
  {
  public:

    typedef T pcm_type;
    typedef E endianess_type;

    PcmBuffer(local_index i_size);
    ~PcmBuffer();

    void Resize (local_index n_size);

    template<typename T_SRC, typename E_SRC>
    PcmBuffer<T, E>& operator= (PcmBuffer<T_SRC, E_SRC>& src);

    // read data out of the buffer
    template<typename T_DEST, typename E_DEST>
    void ReadData (local_index index,
		   local_index read_size,
		   PcmBuffer<T_DEST, E_DEST>& destination) const;

    // Valentin hacked this one, because it does what
    // readdata Imho should do....
    template<typename T_DEST, typename E_DEST>
    void CopyData (local_index index,
		   local_index read_size,
		   PcmBuffer<T_DEST, E_DEST>& destination) const
    {
      local_index di = 0;
      for (local_index si=index; si < index + read_size; ++si, ++di)
	destination.data [di] = data [si];
    }
		   


    // pass data into the buffer
    template<typename T_SRC, typename E_SRC>
    void WriteData (local_index write_size,
		    const PcmBuffer<T_SRC, E_SRC>& source);

    // really zero the buffer
    void WriteZero (local_index zero_size);

    // really zero the buffer - but just the trailing garbage
    void WriteZeroUnused ();

    // should only clear the used_size
    void Clear () { m_used_size = 0; };
    // obtain the wohle buffer length
    local_index Size () const { return m_size; }
    // obtain the used size
    local_index UsedSize () const { return m_used_size; };
    // obtain the free size
    local_index FreeSize () const { return m_size - m_used_size; }

    // only for use with direct data access!!
    void SetUsedSize (local_index new_used_size);

    // wrapped so debugging version can do bounds-checking
    T& operator[] (local_index index);
    const T& operator[] (local_index index) const;

    // public for easy and fast access - for normal access
    // the operator[] should be used to obtain bounds-checking
    // debug mode
    T* data;

  private:

    void ZeroImpl (local_index start, local_index size);

    local_index m_size;
    local_index m_used_size;
    
    T m_zero;
  };

} // namespace GSMP

  /* include template implementation */
#define LOWLEVEL__PCMBUFFER_TMPL__
#include "template/PcmBuffer.tcc"
#undef LOWLEVEL__PCMBUFFER_TMPL__

#endif // LOWLEVEL__PCMBUFFER_HH__
