//
// 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
//

#include "framecpp/Common/ROMemoryBuffer.hh"

namespace FrameCPP
{
    namespace Common
    {
        //===================================================================
        //===================================================================
        //-------------------------------------------------------------------
        /// The default constructor manages a zero length buffer.
        //-------------------------------------------------------------------
        ROMemoryStreamBuf::ROMemoryStreamBuf( )
        {
            //----------------------------------------------------------------
            // By default, have it be a zero length buffer. Use of this
            // is to ensure valid memory address. Having all three values
            // being identical, ensures zero length.
            //----------------------------------------------------------------
            setg( reinterpret_cast< char_type* >( this ),
                  reinterpret_cast< char_type* >( this ),
                  reinterpret_cast< char_type* >( this ) );
        }

        ROMemoryStreamBuf::pos_type
        ROMemoryStreamBuf::ROMemoryStreamBuf::position( )
        {
            return ( gptr( ) - eback( ) );
        }

        ROMemoryStreamBuf::pos_type
        ROMemoryStreamBuf::seekpos( pos_type                Pos,
                                    std::ios_base::openmode Which )
        {
            if ( Which == std::ios_base::out )
            {
                return pos_type( -1 );
            }
            if ( Pos > ( egptr( ) - eback( ) ) )
            {
                return pos_type( -1 );
            }
            setg( eback( ), eback( ) + Pos, egptr( ) );
            return position( );
        }

        ROMemoryStreamBuf::pos_type
        ROMemoryStreamBuf::seekoff( off_type                Off,
                                    std::ios_base::seekdir  Way,
                                    std::ios_base::openmode Which )
        {
            if ( Which == std::ios_base::out )
            {
                return pos_type( -1 );
            }
            char_type* beg = eback( );
            char_type* cur = gptr( );
            char_type* end = egptr( );

            if ( Way == std::ios_base::beg )
            {
                if ( ( Off < 0 ) || ( ( beg + Off ) > end ) )
                {
                    return pos_type( -1 );
                }
                cur = beg + Off;
            }
            else if ( Way == std::ios_base::cur )
            {
                if ( ( ( cur + Off ) < beg ) || ( ( cur + Off ) > end ) )
                {
                    return pos_type( -1 );
                }
                cur += Off;
            }
            else if ( Way == std::ios_base::end )
            {
                if ( ( Off > 0 ) || ( ( end + Off ) < beg ) )
                {
                    return pos_type( -1 );
                }
                cur = end + Off;
            }
            setg( beg, cur, end );
            return position( );
        }

        ROMemoryStreamBuf::buffer_type*
        ROMemoryStreamBuf::setbuf( char_type* S, std::streamsize N )
        {
            setg( S, S, S + N );
            return this;
        }

        //-------------------------------------------------------------------
        //===================================================================
        //===================================================================
        //-------------------------------------------------------------------
        /// The default constructor will initialize all the parts used
        /// in the general case.
        //-------------------------------------------------------------------
        template < typename BT >
        BaseMemoryBufferT< BT >::BaseMemoryBufferT( )
        {
        }

        //-------------------------------------------------------------------
        /// Be careful to release all the resources that were created
        /// for this object.
        //-------------------------------------------------------------------
        template < typename BT >
        BaseMemoryBufferT< BT >::~BaseMemoryBufferT( )
        {
        }

        //-------------------------------------------------------------------
        /// Filtering currently is not optimized at the this layer so
        /// this method will always return false.
        //-------------------------------------------------------------------
        template < typename BT >
        bool
        BaseMemoryBufferT< BT >::FilterInternally( ) const
        {
            return false;
        }

        template < typename BT >
        void
        BaseMemoryBufferT< BT >::buffer( )
        {
        }

        //-------------------------------------------------------------------
        /// \brief Perform filtering operations on the stream
        //-------------------------------------------------------------------
        template < typename BT >
        void
        BaseMemoryBufferT< BT >::filter( const char_type* Begin,
                                         const char_type* End )
        {
        }

        template class BaseMemoryBufferT< ROMemoryStreamBuf >;

    } // namespace Common

} // namespace FrameCPP
