//
// LDASTools frameCPP - A library implementing the LIGO/Virgo frame
// specification
//
// Copyright (C) 2018 California Institute of Technology
//
// LDASTools frameCPP is free software; you may 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 (GPLv2) of the
// License or at your discretion, any later version.
//
// LDASTools frameCPP is distributed in the hope that it will be useful, but
// without any warranty or even the implied warranty of merchantability
// or fitness for a particular purpose. See the GNU General Public
// License (GPLv2) for more details.
//
// Neither the names of the California Institute of Technology (Caltech),
// The Massachusetts Institute of Technology (M.I.T), The Laser
// Interferometer Gravitational-Wave Observatory (LIGO), nor the names
// of its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// You should have received a copy of the licensing terms for this
// software included in the file LICENSE located in the top-level
// directory of this package. If you did not, you can view a copy at
// http://dcc.ligo.org/M1500244/LICENSE
//

#ifndef FrameCPP__COMMON__ContainerBase_HH
#define FrameCPP__COMMON__ContainerBase_HH

namespace FrameCPP
{

    namespace Common
    {
        //-----------------------------------------------------------------------------
        ///
        /// \brief The base class for all containers.
        ///
        /// <p>Most of the LIGO Frame components are containers which contain
        /// other frame components.  For example, the RawData object is a
        /// container for AdcData, SerData, log messages, and other information.
        /// In a frame file, these containers are implemented as linked-lists.
        /// However, in the FrameCPP library these are implemented by a
        /// container class, "Container".  This class standardizes the interface
        /// and maximizes code re-use.
        ///
        /// <p>ContainerBase is the base class for these container objects.  The
        /// container classes themselves are templates, so this class allows the
        /// user to perform queries on the containers which do not require
        /// knowledge of the template type (the template type specifies what
        /// Frame class is stored in the container).
        ///
        /// <p>The methods defined are (they are all pure virtual):
        /// <ul type=disc>
        ///     <li> write - Enable the container to be written to an output
        ///     object.
        ///          This is used by the Frame Object classes when they are
        ///          being written.  It is not meant to be called by the user.
        ///          </li>
        ///     <li> operator[] - Return a pointer to a contained object.  The
        ///     parameter
        ///          to this method is a zero-offset index into the container.
        ///          The object is returned as a pointer to Base (the base class
        ///          for all frame classes) by index. </li>
        ///     <li> size - Returns the number of elements in the container.
        ///     </li>
        /// </ul>
        ///
        /// <p> The destructor is also declared virtual so that the container
        /// can be destructed with only a pointer to the ContainerBase parent.
        ///
        /// \todo
        ///   Implement iterators which dereference to Base*'s.
        ///   This will allow the todo: STL iterator model to be used with
        ///   this class.
        //
        template < class Obj >
        class ContainerBase
        {
        public:
            /// \brief Destructor
            virtual ~ContainerBase( );

            /* Operator Overloads  */
            /// \brief Container indexing.
            /// \exception range_error
            virtual Obj operator[]( unsigned int index ) = 0;
            /// \brief Container indexing.
            /// \exception range_error
            virtual const Obj operator[]( unsigned int index ) const = 0;
            /* Accessors */
            /// \brief Get container size.
            virtual unsigned int size( ) const = 0;

            /* Accessors */
            /// \brief Get container size.
            inline unsigned int
            getSize( ) const
            {
                return size( );
            }
        };

    } // namespace Common
} // namespace FrameCPP

#endif // FrameCPP__COMMON__ContainerBase_HH
