/*!
  @file           SAPDBFields_FieldList.hpp
  @author         StefanB,TillL,UweH
  @ingroup        Field
  @brief          Declarations for class SAPDBFields_FieldList.

\if EMIT_LICENCE
    ========== licence begin  GPL
    Copyright (c) 2000-2005 SAP AG

    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; either version 2
    of the License, or (at your option) any later version.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end

\endif
*/
#ifndef SAPDBFields_FieldList_HPP
#define SAPDBFields_FieldList_HPP

#include "SAPDBCommon/Fields/SAPDBFields_IFieldSequences.hpp"
/*!
@class SAPDBFields_FieldList
@brief A handler to a contiguous memory block of certain size and with certain structure.

The structure consists of a list of offsets followed by a list of fields.
Each offset gives the position of the corresponding field.
The last offset points behind the last field.
*/
class SAPDBFields_FieldList : public SAPDBFields_Field, 
                              public SAPDBFields_IFieldSequence
{
private:
    /// Type for the offsets stored at the beginning of the field list.
    typedef SAPDB_UInt2 OffsetType;

public:
    /*!
    @brief Type definition of type IndexType.

	Both base classes provide a type IndexType.
    The following type definition forces this class to use the 
    type IndexType from base class 'SADBFields_IFieldSequence'.
    */
    typedef SAPDBFields_IFieldSequence::IndexType IndexType;

public:
    /*!
    @brief          Returns the length in bytes needed to create a field list.
    @param          Seq [in] The field sequence for which the length shoud be determined.
    @return         SizeType* The adress of the n-th offset
    */
    static SizeType GetFieldListLength(const SAPDBFields_IFieldSequence& Seq)
    {
        return (Seq.GetTotalLength() + GetOffsetLength(Seq));
    }
	/// Constructs sequence that is not assigned.
    SAPDBFields_FieldList () {}
    /*!
    @brief          Constructs a field list pointing to &lt;Src> with length &lt;Len>.
    @param          Src [in]  The address of the memory block
    @param          Len [in]  The length of the memory block
    */
    SAPDBFields_FieldList (void *Src, SizeType Len)
        : SAPDBFields_Field(Src, Len) {}
	/// Destructs the field list
    ~SAPDBFields_FieldList () {}

    virtual IndexType GetFieldCount() const
    { 
        SAPDBERR_ASSERT_STATE(IsAssigned());
        return *(GetOffsetAddress(0))/2 - 1;
    }
    virtual SAPDBFields_Field& GetField(IndexType N, SAPDBFields_Field& Field) const;
    virtual SAPDBFields_Field::SizeType GetFieldLength(IndexType N) const
    {
        SAPDBERR_ASSERT_ARGUMENT(N < GetFieldCount());
        return (*GetOffsetAddress(N+1) - *GetOffsetAddress(N));
    }
    virtual SAPDBFields_Field::SizeType GetTotalLength() const
    {
        return (GetLength() - GetOffsetLength(*this));
    }
    virtual SAPDBFields_Field::SizeType Write(SAPDBFields_Field            &Destination, 
                                              SAPDBFields_Field::IndexType  Offset,
                                              IndexType                     Begin, 
                                              IndexType                     End) const;
    /*!
    @brief Creates a new field list from an arbitrary field sequence &lt;Seq>
           at a given address &lt;Destination>.
    @param          Seq [in] Sequence of fields to be written.
    @param          Destination [in] The destination buffer.
    @return         SizeType
  
    The length of the new written field list.
    The user is responsible for sufficient memory at &lt;Destination>.
    After writing the field list the handler manages the new memory block at &lt;Destination>.
    */
    SizeType Create(SAPDBFields_Field &Destination, SAPDBFields_IFieldSequence& Seq);

    /*!
    @brief Outputs the content of a field list and returns the modified output stream.
    @param os [in] The output stream
    @param List [in] The field list to be printed.
    @return SAPDB_OStream&

    Because the class inherits two operators << from both 
    class SAPDBFields_Field and class SAPDBFields_IFieldSequence
    the operator is needed to resolve the ambiguity.
    */
    friend SAPDB_OStream& operator <<(SAPDB_OStream& os, const SAPDBFields_FieldList& List)
    {
        return operator <<(os, static_cast<const SAPDBFields_IFieldSequence&>(List));
    }

protected:
    virtual void Print(SAPDB_OStream& os) const;

private:
    /*!
    @brief Returns the adress of the n-th offset.
    @param   N [in] Index of the offset
    @return OffsetType*   The adress of the n-th offset
    */
    const OffsetType* GetOffsetAddress(IndexType N) const
    {
        return reinterpret_cast<const OffsetType*>(GetDataPtr()) + N;
    }

	/// Returns the size of an offset.
    static SizeType GetOffsetSize()
        { return sizeof(OffsetType); }

    /// Returns the length of the whole offset area for a given field sequence <Seq>.
    static SizeType GetOffsetLength(const SAPDBFields_IFieldSequence& Seq)
        { return (Seq.GetFieldCount()+1) * GetOffsetSize(); }
};
#endif // SAPDBFields_FieldList_HPP

