//
// 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_config.h>

#include <cstdlib>

#include "framecpp/Common/FrTOC.hh"

#include "framecpp/FrTOC.hh"
#include "framecppc/FrTOC.h"
#include "framecppc/Stream.h"

#include "FrameCInternal.hh"
#include "StreamInternal.hh"

using FrameC::Set;

namespace FrameC
{
    struct FrTOC : public Handle
    {
        typedef const FrameCPP::Common::FrTOC* data_t;

        data_t m_data;

        FrTOC( );

        virtual ~FrTOC( );
    };

    template <>
    inline pointer_type
    PointerType( FrTOC* Value )
    {
        return POINTER_FR_TOC;
    }

    template <>
    const char*
    Pointers::Name< POINTER_FR_TOC >( )
    {
        return "FrTOC";
    }
} // namespace FrameC

/**
 *  Read a subset of the table of contents information.
 *
 * \note
 *  Currently, this function is currently limited to input streams.
 */
fr_toc_t*
FrameCFrTOCRead( FrameCError** Error, fr_file_t* Stream )
{
    std::unique_ptr< FrameC::FrTOC > retval;

    try
    {
        retval.reset( new FrameC::FrTOC );

        retval->m_data = (FrameC::FrTOC::data_t)NULL;

        FrameC::Handle::Validate( Stream, FrameC::POINTER_STREAM );

        if ( Stream->s_mode == FRAMEC_FILE_MODE_INPUT )
        {
            //-----------------------------------------------------------------
            // input stream
            //-----------------------------------------------------------------

            FrameCPP::IFrameStream* fs( StreamAsInput( Stream ) );

            retval->m_data = fs->GetTOC( );
        }
        else
        {
#if WORKING
            //-----------------------------------------------------------------
            // output stream
            //-----------------------------------------------------------------
            FrameCPP::OFrameStream* fs( Stream->s_stream.output );

            copy_toc( fs->GetTOC( ), retval.get( ) );
#else /* WORKING */
            throw std::runtime_error( "Unable to obtain a table of contents "
                                      "for a frame being written" );
#endif /* WORKING */
        }
        FrameC::Handle::Deposit( retval.get( ) );
    }
    catch ( const std::exception& Exception )
    {
        Set( Error, FRAMEC_ERRNO_FR_TOC_READ_ERROR, Exception.what( ) );
        retval.reset( NULL );
    }
    catch ( ... )
    {
        Set( Error, FRAMEC_ERRNO_FR_TOC_READ_ERROR, FrameC::UnknownError );
        retval.reset( NULL );
    }
    return ( reinterpret_cast< fr_toc_t* >( retval.release( ) ) );
}

/**
 * This function simply recycles resources allocated by FrTOCRead.
 * Once the resource have been recyled, the resource are no longer
 * available to the application for use.
 */
void
FrameCFrTOCFree( FrameCError** Error, fr_toc_t* TOC )
{
    FrameC::Handle::Free(
        Error, TOC, FrameC::POINTER_FR_TOC, FRAMEC_ERRNO_FR_TOC_FREE_ERROR );
}

/**
 * Retrieve information about the FrTOC structure
 * associated with the stream.
 * The Option parameter dictates the number and type of
 * parameters to follow.
 * Multiple pieces of information can be retrieved by having
 * multiple Option/parameter sets.
 * The last value for Option must be FR_TOC_FIELD_LAST to indicate
 * the end of the variable length argument list.
 *
 */
void
FrameCFrTOCQuery( FrameCError** Error, const fr_toc_t* TOC, int Option, ... )
{
    Set( Error );

    const FrameC::FrTOC* ootoc =
        FrameC::HandleCast< const FrameC::FrTOC* >( TOC );
    try
    {
        va_list ap;
        va_start( ap, Option );

        if ( ootoc )
        {
            const FrameCPP::Universal::FrTOC* tocu( NULL );
#if 0
            const FrameCPP::Version_8::FrTOC* toc8( NULL );
            const FrameCPP::Version_7::FrTOC* toc7( NULL );
            const FrameCPP::Version_6::FrTOC* toc6( NULL );
#endif /* 0 */

            //-----------------------------------------------------------------
            // This section is a little tricky as it identifies the version
            // specific type of the Table Of Contents.
            // It does this by doing the assignment inside of the conditional
            // AND uses goto's to cercumvent additional processing.
            //-----------------------------------------------------------------
            if ( ( tocu = ( dynamic_cast< const FrameCPP::Universal::FrTOC* >(
                       ootoc->m_data ) ) ) )
            {
                goto toc_identified;
            }
#if 0
            if ( ( toc8 = ( dynamic_cast< const FrameCPP::Version_8::FrTOC* >(
                       ootoc->m_data ) ) ) )
            {
                goto toc_identified;
            }
            if ( ( toc7 = ( dynamic_cast< const FrameCPP::Version_7::FrTOC* >(
                       ootoc->m_data ) ) ) )
            {
                goto toc_identified;
            }
            if ( ( toc6 = ( dynamic_cast< const FrameCPP::Version_6::FrTOC* >(
                       ootoc->m_data ) ) ) )
            {
                goto toc_identified;
            }
#endif /* 0 */
        toc_identified:

            while ( Option != FR_TOC_FIELD_LAST )
            {
                /**
                 * The following is a description of each value of Option and
                 * the parameters it takes.
                 * <ul>
                 *   <li> <b>FR_TOC_FIELD_LAST</b>
                 *      <p> This is the last option in the list and specifies
                 *          the end of the query.
                 *      </p>
                 *   </li>
                 */
                switch ( Option )
                {
                case FR_TOC_FIELD_ADC_N:
                    /**
                     *   <li> <b>FR_TOC_FIELD_ADC_N</b>
                     *      <p> Retrieve the number of adc channels in the
                     * stream. A single argument should follow this option. The
                     * argument needs to be the address of storage of type
                     * <b>fr_toc_adc_n_t</b>. The number of adc channels in the
                     * stream will be stored here.
                     *      </p>
                     *   </li>
                     */
                    {
                        typedef fr_toc_adc_n_t x_t;
                        x_t*                   x;

                        x = va_arg( ap, x_t* );
                        if ( tocu )
                        {
                            *x = tocu->GetADC( ).size( );
                        }
#if 0
                        if ( toc8 )
                        {
                            *x = toc8->GetADC( ).size( );
                        }
                        else if ( toc7 )
                        {
                            *x = toc7->GetADC( ).size( );
                        }
                        else if ( toc6 )
                        {
                            *x = toc6->GetADC( ).size( );
                        }
                        else
                        {
                            *x = 0;
                        }
#endif /* 0 */
                    }
                    break;
                case FR_TOC_FIELD_ADC_NAMES:
                    /**
                     *   <li> <b>FR_TOC_FIELD_ADC_NAMES</b>
                     *      <p> Retrieve a list of the adc names in the stream.
                     * 	    Two arguments should follow this option.
                     *          The first argument needs to be
                     *          of type <b>fr_toc_adc_names_t</b> and must be
                     *          sufficiently large to hold fr_toc_adc_n_t
                     * elements. The name of each adc will be stored here. The
                     * second argument needs to be of type <b>fr_toc_adc_n_t</b>
                     *          and contains the maximum number of elements
                     *          that can be stored in previous argument.
                     *      </p>
                     *   </li>
                     */
                    {
                        typedef fr_toc_adc_name_t* x_t;
                        typedef fr_toc_adc_n_t     i_t;

                        i_t i, i_max;
                        x_t x;

                        x = va_arg( ap, x_t );
                        i_max = va_arg( ap, i_t );

                        if ( tocu )
                        {
                            typedef FrameCPP::Universal::FrTOC::MapADC_type
                                container_type;

                            const container_type& adcs( tocu->GetADC( ) );

                            i = 0;
                            for ( container_type::const_iterator
                                      cur = adcs.begin( ),
                                      last = adcs.end( );
                                  ( cur != last ) && ( i < i_max );
                                  ++cur, ++i )
                            {
                                x[ i ] = cur->first.c_str( );
                            }
                        }
#if 0
                        if ( toc8 )
                        {
                            typedef FrameCPP::Version_8::FrTOC::MapADC_type
                                container_type;

                            const container_type& adcs( toc8->GetADC( ) );

                            i = 0;
                            for ( container_type::const_iterator
                                      cur = adcs.begin( ),
                                      last = adcs.end( );
                                  ( cur != last ) && ( i < i_max );
                                  ++cur, ++i )
                            {
                                x[ i ] = cur->first.c_str( );
                            }
                        }
                        else if ( toc7 )
                        {
                            typedef FrameCPP::Version_7::FrTOC::MapADC_type
                                container_type;

                            const container_type& adcs( toc7->GetADC( ) );

                            i = 0;
                            for ( container_type::const_iterator
                                      cur = adcs.begin( ),
                                      last = adcs.end( );
                                  ( cur != last ) && ( i < i_max );
                                  ++cur, ++i )
                            {
                                x[ i ] = cur->first.c_str( );
                            }
                        }
                        else if ( toc6 )
                        {
                            typedef FrameCPP::Version_6::FrTOC::MapADC_type
                                container_type;

                            const container_type& adcs( toc6->GetADC( ) );

                            i = 0;
                            for ( container_type::const_iterator
                                      cur = adcs.begin( ),
                                      last = adcs.end( );
                                  ( cur != last ) && ( i < i_max );
                                  ++cur, ++i )
                            {
                                x[ i ] = cur->first.c_str( );
                            }
                        }
#endif /* 0 */
                    }
                    break;
                case FR_TOC_FIELD_DETECTOR_N:
                    /**
                     *   <li> <b>FR_TOC_FIELD_DETECTOR_N</b>
                     *      <p> Retrieve the number of detectors in the stream.
                     * 	    A single argument should follow this option.
                     *          The argument needs to be the address of storage
                     *          of type <b>fr_toc_detector_n_t</b>.
                     *          The number of detectors in the stream
                     *          will be stored here.
                     *      </p>
                     *   </li>
                     */
                    {
                        typedef fr_toc_detector_n_t x_t;
                        x_t*                        x;

                        x = va_arg( ap, x_t* );
                        if ( tocu )
                        {
                            *x = tocu->GetNameDetector( ).size( );
                        }
#if 0
                        if ( toc8 )
                        {
                            *x = toc8->GetNameDetector( ).size( );
                        }
                        else if ( toc7 )
                        {
                            *x = toc7->GetNameDetector( ).size( );
                        }
                        else if ( toc6 )
                        {
                            *x = toc6->GetNameDetector( ).size( );
                        }
                        else
#endif /* 0 */
                        {
                            *x = 0;
                        }
                    }
                    break;
                case FR_TOC_FIELD_DETECTOR_NAMES:
                    /**
                     *   <li> <b>FR_TOC_FIELD_DETECTOR_NAMES</b>
                     *      <p> Retrieve a list of the detector names in the
                     * stream. Two arguments should follow this option. The
                     * first argument needs to be of type
                     * <b>fr_toc_detector_names_t</b> and must be sufficiently
                     * large to hold fr_toc_detector_n_t elements. The name of
                     * each detector will be stored here. The second argument
                     * needs to be of type <b>fr_toc_detector_n_t</b> and
                     * contains the maximum number of elements that can be
                     * stored in previous argument.
                     *      </p>
                     *   </li>
                     */
                    {
                        typedef fr_toc_detector_name_t* x_t;
                        typedef fr_toc_detector_n_t     i_t;

                        i_t i, i_max;
                        x_t x;

                        x = va_arg( ap, x_t );
                        i_max = va_arg( ap, i_t );

                        if ( tocu )
                        {
                            const FrameCPP::Universal::FrTOC::
                                namedetector_container_type& detectors(
                                    tocu->GetNameDetector( ) );

                            i = 0;
                            for ( FrameCPP::Universal::FrTOC::
                                      namedetector_container_type::
                                          const_iterator
                                              cur = detectors.begin( ),
                                              last = detectors.end( );
                                  ( cur != last ) && ( i < i_max );
                                  ++cur, ++i )
                            {
                                x[ i ] = ( *cur ).c_str( );
                            }
                        }
#if 0
                        if ( toc8 )
                        {
                            const FrameCPP::Version_8::FrTOC::
                                namedetector_container_type& detectors(
                                    toc8->GetNameDetector( ) );

                            i = 0;
                            for ( FrameCPP::Version_8::FrTOC::
                                      namedetector_container_type::
                                          const_iterator
                                              cur = detectors.begin( ),
                                              last = detectors.end( );
                                  ( cur != last ) && ( i < i_max );
                                  ++cur, ++i )
                            {
                                x[ i ] = ( *cur ).c_str( );
                            }
                        }
                        else if ( toc7 )
                        {
                            const FrameCPP::Version_7::FrTOC::
                                namedetector_container_type& detectors(
                                    toc7->GetNameDetector( ) );

                            i = 0;
                            for ( FrameCPP::Version_7::FrTOC::
                                      namedetector_container_type::
                                          const_iterator
                                              cur = detectors.begin( ),
                                              last = detectors.end( );
                                  ( cur != last ) && ( i < i_max );
                                  ++cur, ++i )
                            {
                                x[ i ] = ( *cur ).c_str( );
                            }
                        }
                        else if ( toc6 )
                        {
                            const FrameCPP::Version_6::FrTOC::
                                namedetector_container_type& detectors(
                                    toc6->GetNameDetector( ) );

                            i = 0;
                            for ( FrameCPP::Version_6::FrTOC::
                                      namedetector_container_type::
                                          const_iterator
                                              cur = detectors.begin( ),
                                              last = detectors.end( );
                                  ( cur != last ) && ( i < i_max );
                                  ++cur, ++i )
                            {
                                x[ i ] = ( *cur ).c_str( );
                            }
                        }
#endif /* 0 */
                    }
                    break;
                case FR_TOC_FIELD_NFRAME:
                    /**
                     *   <li> <b>FR_TOC_FIELD_NFRAME</b>
                     *      <p> Retrieve the number of frames in the stream.
                     * 	    A single argument should follow this option.
                     *          The argument needs to be the address of storage
                     *          of type <b>fr_toc_nframe_t</b>.
                     *          The number of frames in the stream
                     *          will be stored here.
                     *      </p>
                     *   </li>
                     */
                    {
                        typedef fr_toc_nframe_t x_t;
                        x_t*                    x;

                        x = va_arg( ap, x_t* );
                        *x = ootoc->m_data->nFrame( );
                    }
                    break;
                case FR_TOC_FIELD_DT:
                    /**
                     *   <li> <b>FR_TOC_FIELD_DT</b>
                     *      <p> Retrieve the duration of each frame in the
                     * stream. Two arguments should follow this option. The
                     * first argument needs to be of type <b>fr_toc_dt_t</b> and
                     * must have sufficiently large to hold nFrame elements. The
                     * duration of each frame will be stored here. The second
                     * argument needs to be of type <b>fr_toc_nframe_t</b> and
                     * contains the maximum number of elements that can be
                     * stored in previous argument.
                     *      </p>
                     *   </li>
                     */
                    {
                        typedef fr_toc_dt_t     x_t;
                        typedef fr_toc_nframe_t i_t;
                        i_t                     i;
                        x_t                     x;

                        x = va_arg( ap, x_t );
                        i = va_arg( ap, i_t );

                        const FrameCPP::Common::FrTOC::cmn_dt_container_type&
                            dt = ootoc->m_data->dt( );

                        for ( i_t j = 0; j < i; ++j )
                        {
                            x[ j ] = dt[ j ];
                        }
                    }
                    break;
                case FR_TOC_FIELD_GTIME:
                    /**
                     *   <li> <b>FR_TOC_FIELD_GTIME</b>
                     *      <p> Retrieve the start time of each frame in the
                     * stream. Two arguments should follow this option. The
                     * first argument needs to be of type
                     * <b>fr_toc_t0_array_t</b> and must have sufficiently large
                     * to hold nFrame elements. The start gpstime of each frame
                     * will be stored here. The second argument needs to be of
                     * type <b>fr_toc_nframe_t</b> and contains the maximum
                     * number of elements that can be stored in previous
                     * argument.
                     *      </p>
                     *   </li>
                     */
                    {
                        typedef fr_toc_t0_array_t x_t;
                        typedef fr_toc_nframe_t   i_t;
                        i_t                       i;
                        x_t                       x;

                        x = va_arg( ap, x_t );
                        i = va_arg( ap, i_t );

                        const FrameCPP::Common::FrTOC::
                            cmn_GTimeS_container_type& sec =
                                ootoc->m_data->GTimeS( );
                        const FrameCPP::Common::FrTOC::
                            cmn_GTimeN_container_type& nsec =
                                ootoc->m_data->GTimeN( );

                        for ( i_t j = 0; j < i; ++j )
                        {
                            x[ j ].sec = sec[ j ];
                            x[ j ].nan = nsec[ j ];
                        }
                    }
                    break;
                case FR_TOC_FIELD_PROC_N:
                    /**
                     *   <li> <b>FR_TOC_FIELD_PROC_N</b>
                     *      <p> Retrieve the number of proc channels in the
                     * stream. A single argument should follow this option. The
                     * argument needs to be the address of storage of type
                     * <b>fr_toc_proc_n_t</b>. The number of proc channels in
                     * the stream will be stored here.
                     *      </p>
                     *   </li>
                     */
                    {
                        typedef fr_toc_proc_n_t x_t;
                        x_t*                    x;

                        x = va_arg( ap, x_t* );
                        if ( tocu )
                        {
                            *x = tocu->GetProc( ).size( );
                        }
#if 0
                        if ( toc8 )
                        {
                            *x = toc8->GetProc( ).size( );
                        }
                        else if ( toc7 )
                        {
                            *x = toc7->GetProc( ).size( );
                        }
                        else if ( toc6 )
                        {
                            *x = toc6->GetProc( ).size( );
                        }
#endif /* 0 */
                        else
                        {
                            *x = 0;
                        }
                    }
                    break;
                case FR_TOC_FIELD_PROC_NAMES:
                    /**
                     *   <li> <b>FR_TOC_FIELD_PROC_NAMES</b>
                     *      <p> Retrieve a list of the proc names in the stream.
                     * 	    Two arguments should follow this option.
                     *          The first argument needs to be
                     *          of type <b>fr_toc_proc_names_t</b> and must be
                     *          sufficiently large to hold fr_toc_proc_n_t
                     * elements. The name of each proc will be stored here. The
                     * second argument needs to be of type
                     * <b>fr_toc_proc_n_t</b> and contains the maximum number of
                     * elements that can be stored in previous argument.
                     *      </p>
                     *   </li>
                     */
                    {
                        typedef fr_toc_proc_name_t* x_t;
                        typedef fr_toc_proc_n_t     i_t;

                        i_t i, i_max;
                        x_t x;

                        x = va_arg( ap, x_t );
                        i_max = va_arg( ap, i_t );

                        if ( tocu )
                        {
                            typedef FrameCPP::Universal::FrTOC::MapProc_type
                                vcontainer_type;

                            const vcontainer_type& data( tocu->GetProc( ) );

                            i = 0;
                            for ( vcontainer_type::const_iterator
                                      cur = data.begin( ),
                                      last = data.end( );
                                  ( cur != last ) && ( i < i_max );
                                  ++cur, ++i )
                            {
                                x[ i ] = cur->first.c_str( );
                            }
                        }
#if 0
                        if ( toc8 )
                        {
                            typedef FrameCPP::Version_8::FrTOC::MapProc_type
                                vcontainer_type;

                            const vcontainer_type& data( toc8->GetProc( ) );

                            i = 0;
                            for ( vcontainer_type::const_iterator
                                      cur = data.begin( ),
                                      last = data.end( );
                                  ( cur != last ) && ( i < i_max );
                                  ++cur, ++i )
                            {
                                x[ i ] = cur->first.c_str( );
                            }
                        }
                        else if ( toc7 )
                        {
                            typedef FrameCPP::Version_7::FrTOC::MapProc_type
                                vcontainer_type;

                            const vcontainer_type& data( toc7->GetProc( ) );

                            i = 0;
                            for ( vcontainer_type::const_iterator
                                      cur = data.begin( ),
                                      last = data.end( );
                                  ( cur != last ) && ( i < i_max );
                                  ++cur, ++i )
                            {
                                x[ i ] = cur->first.c_str( );
                            }
                        }
                        else if ( toc6 )
                        {
                            typedef FrameCPP::Version_6::FrTOC::MapProc_type
                                vcontainer_type;

                            const vcontainer_type& data( toc6->GetProc( ) );

                            i = 0;
                            for ( vcontainer_type::const_iterator
                                      cur = data.begin( ),
                                      last = data.end( );
                                  ( cur != last ) && ( i < i_max );
                                  ++cur, ++i )
                            {
                                x[ i ] = cur->first.c_str( );
                            }
                        }
#endif /* 0 */
                    }
                    break;
                case FR_TOC_FIELD_SIM_N:
                    /**
                     *   <li> <b>FR_TOC_FIELD_SIM_N</b>
                     *      <p> Retrieve the number of sim channels in the
                     * stream. A single argument should follow this option. The
                     * argument needs to be the address of storage of type
                     * <b>fr_toc_sim_n_t</b>. The number of sim channels in the
                     * stream will be stored here.
                     *      </p>
                     *   </li>
                     */
                    {
                        typedef fr_toc_sim_n_t x_t;
                        x_t*                   x;

                        x = va_arg( ap, x_t* );
                        if ( tocu )
                        {
                            *x = tocu->GetSim( ).size( );
                        }
#if 0
                        if ( toc8 )
                        {
                            *x = toc8->GetSim( ).size( );
                        }
                        else if ( toc7 )
                        {
                            *x = toc7->GetSim( ).size( );
                        }
                        else if ( toc6 )
                        {
                            *x = toc6->GetSim( ).size( );
                        }
#endif /* 0 */
                        else
                        {
                            *x = 0;
                        }
                    }
                    break;
                case FR_TOC_FIELD_SIM_NAMES:
                    /**
                     *   <li> <b>FR_TOC_FIELD_SIM_NAMES</b>
                     *      <p> Retrieve a list of the sim names in the stream.
                     * 	    Two arguments should follow this option.
                     *          The first argument needs to be
                     *          of type <b>fr_toc_sim_names_t</b> and must be
                     *          sufficiently large to hold fr_toc_sim_n_t
                     * elements. The name of each sim will be stored here. The
                     * second argument needs to be of type <b>fr_toc_sim_n_t</b>
                     *          and contains the maximum number of elements
                     *          that can be stored in previous argument.
                     *      </p>
                     *   </li>
                     */
                    {
                        typedef fr_toc_sim_name_t* x_t;
                        typedef fr_toc_sim_n_t     i_t;

                        i_t i, i_max;
                        x_t x;

                        x = va_arg( ap, x_t );
                        i_max = va_arg( ap, i_t );

                        if ( tocu )
                        {
                            typedef FrameCPP::Universal::FrTOC::MapSim_type
                                container_type;

                            const container_type& data( tocu->GetSim( ) );

                            i = 0;
                            for ( container_type::const_iterator
                                      cur = data.begin( ),
                                      last = data.end( );
                                  ( cur != last ) && ( i < i_max );
                                  ++cur, ++i )
                            {
                                x[ i ] = cur->first.c_str( );
                            }
                        }
#if 0
                        if ( toc8 )
                        {
                            typedef FrameCPP::Version_8::FrTOC::MapSim_type
                                container_type;

                            const container_type& data( toc8->GetSim( ) );

                            i = 0;
                            for ( container_type::const_iterator
                                      cur = data.begin( ),
                                      last = data.end( );
                                  ( cur != last ) && ( i < i_max );
                                  ++cur, ++i )
                            {
                                x[ i ] = cur->first.c_str( );
                            }
                        }
                        else if ( toc7 )
                        {
                            typedef FrameCPP::Version_7::FrTOC::MapSim_type
                                container_type;

                            const container_type& data( toc7->GetSim( ) );

                            i = 0;
                            for ( container_type::const_iterator
                                      cur = data.begin( ),
                                      last = data.end( );
                                  ( cur != last ) && ( i < i_max );
                                  ++cur, ++i )
                            {
                                x[ i ] = cur->first.c_str( );
                            }
                        }
                        else if ( toc6 )
                        {
                            typedef FrameCPP::Version_6::FrTOC::MapSim_type
                                container_type;

                            const container_type& data( toc6->GetSim( ) );

                            i = 0;
                            for ( container_type::const_iterator
                                      cur = data.begin( ),
                                      last = data.end( );
                                  ( cur != last ) && ( i < i_max );
                                  ++cur, ++i )
                            {
                                x[ i ] = cur->first.c_str( );
                            }
                        }
#endif /* 0 */
                    }
                    break;
                default:
                    /**************************************************************
                      An unknown option has been specified. Terminate the
                    request.
                    ***************************************************************/
                    Option = FR_TOC_FIELD_LAST;
                    continue;
                }
                /**
                 * </ul>
                 */
#if 0
	int next_opt = va_arg(ap, int /* fr_vect_fields*/ );
	Option = (fr_toc_fields)next_opt;
#else /* 0 */
                Option = va_arg( ap, int /* fr_vect_fields*/ );
#endif /* 0 */
            }
        }
        else
        {
            Set( Error,
                 FRAMEC_ERRNO_FR_TOC_ACCESSOR_ERROR,
                 "NULL reference to Table of Contents" );
        }
        va_end( ap );
    }
    catch ( const std::exception& Exception )
    {
        Set( Error, FRAMEC_ERRNO_FR_TOC_ACCESSOR_ERROR, Exception.what( ) );
    }
    catch ( ... )
    {
        Set( Error, FRAMEC_ERRNO_FR_TOC_ACCESSOR_ERROR, FrameC::UnknownError );
    }
}

namespace FrameC
{
    FrTOC::FrTOC( ) : Handle( POINTER_FR_TOC ), m_data( (data_t)NULL )
    {
    }

    FrTOC::~FrTOC( )
    {
    }
} // namespace FrameC
