<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkSLCReader.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <ctype.h>

#include "vtkSLCReader.h"

// Constructor for a vtkSLCReader.
vtkSLCReader::vtkSLCReader()
{
  this->FileName = NULL;
}

// Decodes an array of eight bit run-length encoded data.
unsigned char* vtkSLCReader::Decode8BitData( unsigned char *in_ptr,
					       int size )
{
  unsigned char           *curr_ptr;
  unsigned char           *decode_ptr;
  unsigned char           *return_ptr;
  unsigned char           current_value;
  unsigned char           remaining;

  curr_ptr = in_ptr;

  decode_ptr = return_ptr = new unsigned char[size];

  while( 1 )
  {
    current_value = *(curr_ptr++);

    if( !(remaining = (current_value & 0x7f)) )
      {
      break;
      }

    if( current_value & 0x80 )
    {
      while( remaining-- )
	{
        *(decode_ptr++) = *(curr_ptr++);
	}
    }
    else
    {
      current_value = *(curr_ptr++);
      while ( remaining-- )
	{
        *(decode_ptr++) = current_value;
	}
    }

  }

  return return_ptr;
}

// Reads an SLC file and creates a vtkStructuredPoints dataset.
void vtkSLCReader::Execute()
{
  FILE *fp;

  vtkScalars *newScalars;

  int	temp;
  int	data_compression;
  int	plane_size;
  int	volume_size;
  float f[3];
  int	size[3];
  int	magic_num;
  int	z_counter;
  int	icon_width, icon_height;
  int	voxel_count;
  int	compressed_size;
  int	i;

  unsigned char	*icon_ptr = NULL;
  unsigned char	*compressed_ptr = NULL;
  unsigned char	*scan_ptr = NULL;
  unsigned char	*sptr = NULL;

  vtkStructuredPoints *output=(vtkStructuredPoints *)this->Output;

  // Initialize
  if ((fp = fopen(this->FileName, "rb")) == NULL)
  {
    vtkErrorMacro(<< "File " << this->FileName << " not found");
    return;
  }

  fscanf( fp, "%d", &magic_num );
  if( magic_num != 11111 )
  {
    vtkErrorMacro(<< "SLC magic number is not correct");
    return;
  }

  f[0] = f[1] = f[2] = 0.0;
  output->SetOrigin(f);

  fscanf( fp, "%d", size );
  fscanf( fp, "%d", size+1 );
  fscanf( fp, "%d", size+2 );
  output->SetDimensions(size);

  // Skip Over bits_per_voxel Field */
  fscanf( fp, "%d",   &temp );

  fscanf( fp, "%f", f );
  fscanf( fp, "%f", f+1 );
  fscanf( fp, "%f", f+2 );
  output->SetSpacing(f);

  // Skip Over unit_type, data_origin, and data_modification
  fscanf( fp, "%d", &temp );
  fscanf( fp, "%d", &temp );
  fscanf( fp, "%d", &temp );

  fscanf( fp, "%d\n", &data_compression );

  plane_size = size[0] * size[1];
  volume_size = plane_size * size[2];
  newScalars = vtkScalars::New(VTK_UNSIGNED_CHAR,1);
  newScalars->SetNumberOfScalars(volume_size);

  // Skip Over Icon
  fscanf( fp, "%d %d X", &icon_width,  &icon_height );
  icon_ptr = new unsigned char[(icon_width*icon_height)];

  fread( icon_ptr, 1, (icon_width*icon_height), fp );
  fread( icon_ptr, 1, (icon_width*icon_height), fp );
  fread( icon_ptr, 1, (icon_width*icon_height), fp );

  delete [] icon_ptr;

  voxel_count = 0;

  // Read In Data Plane By Plane
  for( z_counter=0; z_counter<size[2]; z_counter++ )
  {
    // Read a single plane into temp memory
    switch( data_compression )
    {
      case 0:

        if( !scan_ptr )
	  {
          scan_ptr = new unsigned char[plane_size];
	  }

        if( fread( scan_ptr, 1, plane_size, fp ) != (unsigned int)plane_size )
	{
          vtkErrorMacro( <<
	    "Unable to read slice " << z_counter << " from SLC File" );
	  newScalars->Delete();
	  return;
	}

        break;

      case 1:

        if( scan_ptr )
	  {
          delete [] scan_ptr;
	  }

        fscanf( fp, "%d X", &compressed_size );

        compressed_ptr = new unsigned char[compressed_size];

        if( fread(compressed_ptr, 1, compressed_size, fp) !=
	    (unsigned int)compressed_size )
	{
          vtkErrorMacro( << "Unable to read compressed slice " <<
	    z_counter << " from SLC File" );
	  newScalars->Delete();
	  return;
	}

	scan_ptr = this->Decode8BitData( compressed_ptr, plane_size );

	delete [] compressed_ptr;

        break;
      default:
        vtkErrorMacro(<< "Unknown SLC compression type: " <<
	  data_compression );
        break;
    }

    sptr = scan_ptr;

    // Copy plane into volume
    for( i=0; i<plane_size; i++ )
    {
    newScalars->SetScalar( (z_counter*plane_size + i), *sptr++ );
    }
  }

  delete scan_ptr;

  vtkDebugMacro(<< "Read " << volume_size << " points");

  if( newScalars )
    {
    output->GetPointData()->SetScalars(newScalars);
    newScalars->Delete();
    }

  fclose( fp );
}

void vtkSLCReader::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkStructuredPointsSource::PrintSelf(os,indent);

  os << indent << "File Name: "
     << (this->FileName ? this->FileName : "(none)") << "\n";
}
<commit_msg>ERR:  delete scan_ptr -> delete [] scan_ptr.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkSLCReader.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <ctype.h>

#include "vtkSLCReader.h"

// Constructor for a vtkSLCReader.
vtkSLCReader::vtkSLCReader()
{
  this->FileName = NULL;
}

// Decodes an array of eight bit run-length encoded data.
unsigned char* vtkSLCReader::Decode8BitData( unsigned char *in_ptr,
					       int size )
{
  unsigned char           *curr_ptr;
  unsigned char           *decode_ptr;
  unsigned char           *return_ptr;
  unsigned char           current_value;
  unsigned char           remaining;

  curr_ptr = in_ptr;

  decode_ptr = return_ptr = new unsigned char[size];

  while( 1 )
  {
    current_value = *(curr_ptr++);

    if( !(remaining = (current_value & 0x7f)) )
      {
      break;
      }

    if( current_value & 0x80 )
    {
      while( remaining-- )
	{
        *(decode_ptr++) = *(curr_ptr++);
	}
    }
    else
    {
      current_value = *(curr_ptr++);
      while ( remaining-- )
	{
        *(decode_ptr++) = current_value;
	}
    }

  }

  return return_ptr;
}

// Reads an SLC file and creates a vtkStructuredPoints dataset.
void vtkSLCReader::Execute()
{
  FILE *fp;

  vtkScalars *newScalars;

  int	temp;
  int	data_compression;
  int	plane_size;
  int	volume_size;
  float f[3];
  int	size[3];
  int	magic_num;
  int	z_counter;
  int	icon_width, icon_height;
  int	voxel_count;
  int	compressed_size;
  int	i;

  unsigned char	*icon_ptr = NULL;
  unsigned char	*compressed_ptr = NULL;
  unsigned char	*scan_ptr = NULL;
  unsigned char	*sptr = NULL;

  vtkStructuredPoints *output=(vtkStructuredPoints *)this->Output;

  // Initialize
  if ((fp = fopen(this->FileName, "rb")) == NULL)
  {
    vtkErrorMacro(<< "File " << this->FileName << " not found");
    return;
  }

  fscanf( fp, "%d", &magic_num );
  if( magic_num != 11111 )
  {
    vtkErrorMacro(<< "SLC magic number is not correct");
    return;
  }

  f[0] = f[1] = f[2] = 0.0;
  output->SetOrigin(f);

  fscanf( fp, "%d", size );
  fscanf( fp, "%d", size+1 );
  fscanf( fp, "%d", size+2 );
  output->SetDimensions(size);

  // Skip Over bits_per_voxel Field */
  fscanf( fp, "%d",   &temp );

  fscanf( fp, "%f", f );
  fscanf( fp, "%f", f+1 );
  fscanf( fp, "%f", f+2 );
  output->SetSpacing(f);

  // Skip Over unit_type, data_origin, and data_modification
  fscanf( fp, "%d", &temp );
  fscanf( fp, "%d", &temp );
  fscanf( fp, "%d", &temp );

  fscanf( fp, "%d\n", &data_compression );

  plane_size = size[0] * size[1];
  volume_size = plane_size * size[2];
  newScalars = vtkScalars::New(VTK_UNSIGNED_CHAR,1);
  newScalars->SetNumberOfScalars(volume_size);

  // Skip Over Icon
  fscanf( fp, "%d %d X", &icon_width,  &icon_height );
  icon_ptr = new unsigned char[(icon_width*icon_height)];

  fread( icon_ptr, 1, (icon_width*icon_height), fp );
  fread( icon_ptr, 1, (icon_width*icon_height), fp );
  fread( icon_ptr, 1, (icon_width*icon_height), fp );

  delete [] icon_ptr;

  voxel_count = 0;

  // Read In Data Plane By Plane
  for( z_counter=0; z_counter<size[2]; z_counter++ )
  {
    // Read a single plane into temp memory
    switch( data_compression )
    {
      case 0:

        if( !scan_ptr )
	  {
          scan_ptr = new unsigned char[plane_size];
	  }

        if( fread( scan_ptr, 1, plane_size, fp ) != (unsigned int)plane_size )
	{
          vtkErrorMacro( <<
	    "Unable to read slice " << z_counter << " from SLC File" );
	  newScalars->Delete();
	  return;
	}

        break;

      case 1:

        if( scan_ptr )
	  {
          delete [] scan_ptr;
	  }

        fscanf( fp, "%d X", &compressed_size );

        compressed_ptr = new unsigned char[compressed_size];

        if( fread(compressed_ptr, 1, compressed_size, fp) !=
	    (unsigned int)compressed_size )
	{
          vtkErrorMacro( << "Unable to read compressed slice " <<
	    z_counter << " from SLC File" );
	  newScalars->Delete();
	  return;
	}

	scan_ptr = this->Decode8BitData( compressed_ptr, plane_size );

	delete [] compressed_ptr;

        break;
      default:
        vtkErrorMacro(<< "Unknown SLC compression type: " <<
	  data_compression );
        break;
    }

    sptr = scan_ptr;

    // Copy plane into volume
    for( i=0; i<plane_size; i++ )
    {
    newScalars->SetScalar( (z_counter*plane_size + i), *sptr++ );
    }
  }

  delete [] scan_ptr;

  vtkDebugMacro(<< "Read " << volume_size << " points");

  if( newScalars )
    {
    output->GetPointData()->SetScalars(newScalars);
    newScalars->Delete();
    }

  fclose( fp );
}

void vtkSLCReader::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkStructuredPointsSource::PrintSelf(os,indent);

  os << indent << "File Name: "
     << (this->FileName ? this->FileName : "(none)") << "\n";
}
<|endoftext|>


<commit_before>/*    Copyright (c) 2010-2014, Delft University of Technology
 *    All rights reserved.
 *
 *    Redistribution and use in source and binary forms, with or without modification, are
 *    permitted provided that the following conditions are met:
 *      - Redistributions of source code must retain the above copyright notice, this list of
 *        conditions and the following disclaimer.
 *      - Redistributions in binary form must reproduce the above copyright notice, this list of
 *        conditions and the following disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *      - Neither the name of the Delft University of Technology nor the names of its contributors
 *        may be used to endorse or promote products derived from this software without specific
 *        prior written permission.
 *
 *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
 *    OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *    COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *    GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *    AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 *    OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *    Changelog
 *      YYMMDD    Author            Comment
 *      120203    B. Tong Minh      Copied RungeKutta4Stepsize unit test.
 *      120207    K. Kumar          Adapted to use modified benchmark functions in Tudat Core.
 *      120213    K. Kumar          Modified getCurrentInterval() to getIndependentVariable();
 *                                  transferred to Boost unit test framework.
 *      120321    K. Kumar          Updated (Burden and Faires, 2011) benchmark function call.
 *      120328    K. Kumar          Removed specific integrator tests; added compiler tests; added
 *                                  test of runtime error when minimm step size is exceeded.
 *      120331    B. Tong Minh      Added typeid check for RungeKuttaVariableStepSizeIntegratorXd
 *                                  typedef; modified minimum step size exceeded unit tests to use
 *                                  custom exception object.
 *      120321    D.Dirkx           Added unit test for getCurrentStateDerivatives function.
 *
 *    References
 *      Burden, R.L., Faires, J.D. Numerical Analysis, 7th Edition, Books/Cole, 2001.
 *
 *    Notes
 *      This file doesn't test any specific Runge-Kutta-type integrators, but rather some general
 *      functionality adopted in the the RungeKuttaVariableStepSizeIntegrator class, applicable to
 *      all Runge-Kutta-type integrators.
 *
 *      It should be noted that the getCurrentStateDerivatives() member function is not tested in a
 *      fully generic manner at the moment; the test is setup specifically based on the
 *      Runge-Kutta-Fehlberg 4(5) (RKF45) integrator. A more comprehensive test should be designed
 *      to ensure that the member function performs as desired regardless of the coefficient set
 *      chosen.
 *
 */

#define BOOST_TEST_MAIN

#include <limits>
#include <string>
#include <typeinfo>

#include <boost/exception/all.hpp>
#include <boost/test/unit_test.hpp>

#include <TudatCore/Basics/testMacros.h>
#include <TudatCore/Mathematics/NumericalIntegrators/UnitTests/numericalIntegratorTestFunctions.h>

#include "Tudat/Mathematics/NumericalIntegrators/rungeKuttaVariableStepSizeIntegrator.h"
#include "Tudat/Mathematics/NumericalIntegrators/rungeKuttaCoefficients.h"

namespace tudat
{
namespace unit_tests
{

using tudat::numerical_integrators::RungeKuttaCoefficients;
using tudat::numerical_integrators::RungeKuttaVariableStepSizeIntegrator;
using tudat::numerical_integrators::RungeKuttaVariableStepSizeIntegratorXd;
using numerical_integrator_test_functions::computeZeroStateDerivative;

BOOST_AUTO_TEST_SUITE( test_runge_kutta_variable_step_size_integrator )

//! Test different types of states and state derivatives.
BOOST_AUTO_TEST_CASE( testCompilerErrors )
{
    // Case 1: test the VectorXd typdef. There is no need to explicitly test anything, since we're
    //         looking for compiler errors.
    {
        RungeKuttaVariableStepSizeIntegratorXd integrator(
                    RungeKuttaCoefficients( ),
                    &computeZeroStateDerivative,
                    0.0,
                    Eigen::Vector3d::Zero( ),
                    0.01,
                    std::numeric_limits< double >::infinity( ),
                    10.0 * std::numeric_limits< double >::epsilon( ),
                    10.0 * std::numeric_limits< double >::epsilon( ) );

        // Test integrateTo() function.
        integrator.integrateTo( 10.0, 0.1 );

        // Test performIntegrationStep() function.
        integrator.performIntegrationStep( 0.1 );

        // Test rollbackToPreviousState() function.
        integrator.rollbackToPreviousState( );

        // Check if the default types are correct.
        BOOST_CHECK_EQUAL(
                    std::string( typeid( integrator.getCurrentIndependentVariable( ) ).name( ) ),
                    std::string( typeid( double ).name( ) ) );
        BOOST_CHECK_EQUAL( std::string( typeid( integrator.getCurrentState( ) ).name( ) ),
                           std::string( typeid( Eigen::VectorXd ).name( ) ) );
    }

    // Case 2: test different types of states and state derivatives. There is no need to explicitly
    //         test anything, since we're looking for compiler errors.
    {
        RungeKuttaVariableStepSizeIntegrator < double, Eigen::Vector3d, Eigen::VectorXd >
                integrator( RungeKuttaCoefficients( ),
                            &computeZeroStateDerivative,
                            0.0,
                            Eigen::Vector3d::Zero( ),
                            0.01,
                            std::numeric_limits< double >::infinity( ),
                            10.0 * std::numeric_limits< double >::epsilon( ),
                            10.0 * std::numeric_limits< double >::epsilon( ) );

        // Test integrateTo() function.
        integrator.integrateTo( 10.0, 0.1 );

        // Test performIntegrationStep() function.
        integrator.performIntegrationStep( 0.1 );

        // Test rollbackToPreviousState() function.
        integrator.rollbackToPreviousState( );
    }

    // Case 3: test same types of states and state derivatives (MatrixXd). There is no need to
    //         explicitly test anything, since we're looking for compiler errors.
    {
        RungeKuttaVariableStepSizeIntegrator < double, Eigen::MatrixXd, Eigen::MatrixXd >
                integrator( RungeKuttaCoefficients( ),
                            &computeZeroStateDerivative,
                            0.0,
                            Eigen::Vector3d::Zero( ),
                            0.01,
                            std::numeric_limits< double >::infinity( ),
                            10.0 * std::numeric_limits< double >::epsilon( ),
                            10.0 * std::numeric_limits< double >::epsilon( ) );

        // Test integrateTo() function.
        integrator.integrateTo( 10.0, 0.1 );

        // Test performIntegrationStep() function.
        integrator.performIntegrationStep( 0.1 );

        // Test rollbackToPreviousState() function.
        integrator.rollbackToPreviousState( );
    }
}

//! Test that exceeding minimum step size throws a runtime error.
BOOST_AUTO_TEST_CASE( testMinimumStepSizeRuntimeError )
{
    RungeKuttaVariableStepSizeIntegratorXd integrator(
                RungeKuttaCoefficients( ),
                &computeZeroStateDerivative,
                0.0,
                Eigen::Vector3d::Zero( ),
                100.0,
                std::numeric_limits< double >::infinity( ),
                std::numeric_limits< double >::epsilon( ),
                std::numeric_limits< double >::epsilon( ) );

    // Case 1: test that minimum step size is exceeded when using integrateTo().
    {
        // Declare boolean flag to test if minimum step size is exceed for integrateTo().
        bool isMinimumStepSizeExceededForIntegrateTo = false;

        // Try integrateTo(), which should result in a runtime error.
        try
        {
            // Test integrateTo() function.
            integrator.integrateTo( 10.0, 0.1 );
        }

        // Catch the expected runtime error, and set the boolean flag to true.
        catch ( RungeKuttaVariableStepSizeIntegratorXd::MinimumStepSizeExceededError
                minimumStepSizeExceededError )
        {
            isMinimumStepSizeExceededForIntegrateTo = true;
            BOOST_CHECK_EQUAL( minimumStepSizeExceededError.minimumStepSize, 100.0 );
        }

        // Check that the minimum step size was indeed exceeded.
        BOOST_CHECK( isMinimumStepSizeExceededForIntegrateTo );
    }

    // Case 2: test that minimum step size is exceeded when using performIntegrationStep().
    {
        // Declare boolean flag to test if minimum step size is exceed for
        // performIntegrationStep().
        bool isMinimumStepSizeExceededForPerformIntegrationStep = false;

        // Try performIntegrationStep(), which should result in a runtime error.
        try
        {
            // Test performIntegrationStep() function.
            integrator.performIntegrationStep( 0.1 );
        }

        // Catch the expected runtime error, and set the boolean flag to true.
        catch ( RungeKuttaVariableStepSizeIntegratorXd::MinimumStepSizeExceededError
                minimumStepSizeExceededError )
        {
            isMinimumStepSizeExceededForPerformIntegrationStep = true;
            BOOST_CHECK_EQUAL( minimumStepSizeExceededError.minimumStepSize, 100.0 );
        }

        // Check that the minimum step size was indeed exceeded.
        BOOST_CHECK( isMinimumStepSizeExceededForPerformIntegrationStep );
    }
}

//! Test if the state derivative evaliations are properly returned.
BOOST_AUTO_TEST_CASE( testStateDerivativeRetrievalFunction )
{
    using namespace tudat::numerical_integrators;
    using namespace unit_tests::numerical_integrator_test_functions;

    // This test is based on the Runge-Kutta-Fehlberg 4(5) coefficient set, hence the test does not
    // robustly ensure that the getCurrentStateDerivatives() works correctly for any given
    // coefficient set currently. This test is more of an preliminary check that the function
    // performs as required, with the extrapolation that it is likely to perform consistently in
    // this manner for any Runge-Kutta-type coefficient set.

    // Create test integrator.
    RungeKuttaVariableStepSizeIntegratorXd integrator(
                RungeKuttaCoefficients::get( RungeKuttaCoefficients::rungeKuttaFehlberg45 ),
                &computeVanDerPolStateDerivative,
                0.0,
                ( Eigen::VectorXd( 2 ) << 1.0, 2.0 ).finished( ),
                0.0, 10.0, 1.0E-8, 1.0E-8 );

    // Perform first integration step.
    integrator.performIntegrationStep( 1.0 );

    // Retrieve time and state after first integration step.
    const double previousTime = integrator.getCurrentIndependentVariable( );
    const Eigen::VectorXd previousState = integrator.getCurrentState( );

    // Perform additional integration step to verify that there are no problems with
    // getCurrentStateDerivatives after >1 iterations (i.e not being reset etc.).
    integrator.performIntegrationStep( integrator.getNextStepSize( ) );

    // Get current time and previous time step.
    const double currentTime = integrator.getCurrentIndependentVariable( );
    const double stepSize = currentTime - previousTime;

    // Retrieve state derivative values used in previous time step.
    std::vector< Eigen::VectorXd > stateDerivatives = integrator.getCurrentStateDerivatives( );

    // Check size of state derivative vector. This test is specifically set up to test the for the
    // number of stages in the RKF45 integrator.
    BOOST_CHECK_EQUAL( stateDerivatives.size( ), 6 );

    // Perform manual state derivative evaluations at previous time step using RKF45 method
    RungeKuttaCoefficients rkf45Coefficients = RungeKuttaCoefficients::get(
                RungeKuttaCoefficients::rungeKuttaFehlberg45 );
    std::vector< Eigen::VectorXd > directStateDerivativeValues;

    for ( int stage = 0; stage < rkf45Coefficients.cCoefficients.rows( ); stage++ )
    {
        // Compute the intermediate state to pass to the state derivative for this stage.
        Eigen::VectorXd intermediateState( previousState );

        // Compute the intermediate state.
        for ( int column = 0; column < stage; column++ )
        {
            intermediateState += stepSize * rkf45Coefficients.aCoefficients( stage, column )
                    * directStateDerivativeValues[ column ];
        }

        // Compute state derivative.
        directStateDerivativeValues.push_back(
                    computeVanDerPolStateDerivative(
                        previousTime +
                        rkf45Coefficients.cCoefficients( stage ) * stepSize,
                        intermediateState ) );

        // Check if manual result matched result from NumericalIntegrator.
        TUDAT_CHECK_MATRIX_CLOSE_FRACTION( directStateDerivativeValues.at( stage ),
                                           stateDerivatives.at( stage ),
                                           1.0E-15 );
    }
}

BOOST_AUTO_TEST_SUITE_END( )

} // namespace unit_tests
} // namespace tudat
<commit_msg>Committing bug fix (Issue #667) unit test, pending the upload of the new bundle<commit_after>/*    Copyright (c) 2010-2014, Delft University of Technology
 *    All rights reserved.
 *
 *    Redistribution and use in source and binary forms, with or without modification, are
 *    permitted provided that the following conditions are met:
 *      - Redistributions of source code must retain the above copyright notice, this list of
 *        conditions and the following disclaimer.
 *      - Redistributions in binary form must reproduce the above copyright notice, this list of
 *        conditions and the following disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *      - Neither the name of the Delft University of Technology nor the names of its contributors
 *        may be used to endorse or promote products derived from this software without specific
 *        prior written permission.
 *
 *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
 *    OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *    COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *    GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *    AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 *    OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *    Changelog
 *      YYMMDD    Author            Comment
 *      120203    B. Tong Minh      Copied RungeKutta4Stepsize unit test.
 *      120207    K. Kumar          Adapted to use modified benchmark functions in Tudat Core.
 *      120213    K. Kumar          Modified getCurrentInterval() to getIndependentVariable();
 *                                  transferred to Boost unit test framework.
 *      120321    K. Kumar          Updated (Burden and Faires, 2011) benchmark function call.
 *      120328    K. Kumar          Removed specific integrator tests; added compiler tests; added
 *                                  test of runtime error when minimm step size is exceeded.
 *      120331    B. Tong Minh      Added typeid check for RungeKuttaVariableStepSizeIntegratorXd
 *                                  typedef; modified minimum step size exceeded unit tests to use
 *                                  custom exception object.
 *      120321    D.Dirkx           Added unit test for getCurrentStateDerivatives function.
 *
 *    References
 *      Burden, R.L., Faires, J.D. Numerical Analysis, 7th Edition, Books/Cole, 2001.
 *
 *    Notes
 *      This file doesn't test any specific Runge-Kutta-type integrators, but rather some general
 *      functionality adopted in the the RungeKuttaVariableStepSizeIntegrator class, applicable to
 *      all Runge-Kutta-type integrators.
 *
 *      It should be noted that the getCurrentStateDerivatives() member function is not tested in a
 *      fully generic manner at the moment; the test is setup specifically based on the
 *      Runge-Kutta-Fehlberg 4(5) (RKF45) integrator. A more comprehensive test should be designed
 *      to ensure that the member function performs as desired regardless of the coefficient set
 *      chosen.
 *
 */

#define BOOST_TEST_MAIN

#include <limits>
#include <string>
#include <typeinfo>

#include <boost/exception/all.hpp>
#include <boost/test/unit_test.hpp>

#include <TudatCore/Basics/testMacros.h>
#include <TudatCore/Mathematics/NumericalIntegrators/UnitTests/numericalIntegratorTestFunctions.h>
#include <TudatCore/Mathematics/NumericalIntegrators/rungeKutta4Integrator.h>

#include "Tudat/Mathematics/NumericalIntegrators/rungeKuttaVariableStepSizeIntegrator.h"
#include "Tudat/Mathematics/NumericalIntegrators/rungeKuttaCoefficients.h"

namespace tudat
{
namespace unit_tests
{

using tudat::numerical_integrators::RungeKuttaCoefficients;
using tudat::numerical_integrators::RungeKuttaVariableStepSizeIntegrator;
using tudat::numerical_integrators::RungeKuttaVariableStepSizeIntegratorXd;
using numerical_integrator_test_functions::computeZeroStateDerivative;

BOOST_AUTO_TEST_SUITE( test_runge_kutta_variable_step_size_integrator )

//! Test different types of states and state derivatives.
BOOST_AUTO_TEST_CASE( testCompilerErrors )
{
    // Case 1: test the VectorXd typdef. There is no need to explicitly test anything, since we're
    //         looking for compiler errors.
    {
        RungeKuttaVariableStepSizeIntegratorXd integrator(
                    RungeKuttaCoefficients( ),
                    &computeZeroStateDerivative,
                    0.0,
                    Eigen::Vector3d::Zero( ),
                    0.01,
                    std::numeric_limits< double >::infinity( ),
                    10.0 * std::numeric_limits< double >::epsilon( ),
                    10.0 * std::numeric_limits< double >::epsilon( ) );

        // Test integrateTo() function.
        integrator.integrateTo( 10.0, 0.1 );

        // Test performIntegrationStep() function.
        integrator.performIntegrationStep( 0.1 );

        // Test rollbackToPreviousState() function.
        integrator.rollbackToPreviousState( );

        // Check if the default types are correct.
        BOOST_CHECK_EQUAL(
                    std::string( typeid( integrator.getCurrentIndependentVariable( ) ).name( ) ),
                    std::string( typeid( double ).name( ) ) );
        BOOST_CHECK_EQUAL( std::string( typeid( integrator.getCurrentState( ) ).name( ) ),
                           std::string( typeid( Eigen::VectorXd ).name( ) ) );
    }

    // Case 2: test different types of states and state derivatives. There is no need to explicitly
    //         test anything, since we're looking for compiler errors.
    {
        RungeKuttaVariableStepSizeIntegrator < double, Eigen::Vector3d, Eigen::VectorXd >
                integrator( RungeKuttaCoefficients( ),
                            &computeZeroStateDerivative,
                            0.0,
                            Eigen::Vector3d::Zero( ),
                            0.01,
                            std::numeric_limits< double >::infinity( ),
                            10.0 * std::numeric_limits< double >::epsilon( ),
                            10.0 * std::numeric_limits< double >::epsilon( ) );

        // Test integrateTo() function.
        integrator.integrateTo( 10.0, 0.1 );

        // Test performIntegrationStep() function.
        integrator.performIntegrationStep( 0.1 );

        // Test rollbackToPreviousState() function.
        integrator.rollbackToPreviousState( );
    }

    // Case 3: test same types of states and state derivatives (MatrixXd). There is no need to
    //         explicitly test anything, since we're looking for compiler errors.
    {
        RungeKuttaVariableStepSizeIntegrator < double, Eigen::MatrixXd, Eigen::MatrixXd >
                integrator( RungeKuttaCoefficients( ),
                            &computeZeroStateDerivative,
                            0.0,
                            Eigen::Vector3d::Zero( ),
                            0.01,
                            std::numeric_limits< double >::infinity( ),
                            10.0 * std::numeric_limits< double >::epsilon( ),
                            10.0 * std::numeric_limits< double >::epsilon( ) );

        // Test integrateTo() function.
        integrator.integrateTo( 10.0, 0.1 );

        // Test performIntegrationStep() function.
        integrator.performIntegrationStep( 0.1 );

        // Test rollbackToPreviousState() function.
        integrator.rollbackToPreviousState( );
    }
}

//! Test that exceeding minimum step size throws a runtime error.
BOOST_AUTO_TEST_CASE( testMinimumStepSizeRuntimeError )
{
    RungeKuttaVariableStepSizeIntegratorXd integrator(
                RungeKuttaCoefficients( ),
                &computeZeroStateDerivative,
                0.0,
                Eigen::Vector3d::Zero( ),
                100.0,
                std::numeric_limits< double >::infinity( ),
                std::numeric_limits< double >::epsilon( ),
                std::numeric_limits< double >::epsilon( ) );

    // Case 1: test that minimum step size is exceeded when using integrateTo().
    {
        // Declare boolean flag to test if minimum step size is exceed for integrateTo().
        bool isMinimumStepSizeExceededForIntegrateTo = false;

        // Try integrateTo(), which should result in a runtime error.
        try
        {
            // Test integrateTo() function.
            integrator.integrateTo( 10.0, 0.1 );
        }

        // Catch the expected runtime error, and set the boolean flag to true.
        catch ( RungeKuttaVariableStepSizeIntegratorXd::MinimumStepSizeExceededError
                minimumStepSizeExceededError )
        {
            isMinimumStepSizeExceededForIntegrateTo = true;
            BOOST_CHECK_EQUAL( minimumStepSizeExceededError.minimumStepSize, 100.0 );
        }

        // Check that the minimum step size was indeed exceeded.
        BOOST_CHECK( isMinimumStepSizeExceededForIntegrateTo );
    }

    // Case 2: test that minimum step size is exceeded when using performIntegrationStep().
    {
        // Declare boolean flag to test if minimum step size is exceed for
        // performIntegrationStep().
        bool isMinimumStepSizeExceededForPerformIntegrationStep = false;

        // Try performIntegrationStep(), which should result in a runtime error.
        try
        {
            // Test performIntegrationStep() function.
            integrator.performIntegrationStep( 0.1 );
        }

        // Catch the expected runtime error, and set the boolean flag to true.
        catch ( RungeKuttaVariableStepSizeIntegratorXd::MinimumStepSizeExceededError
                minimumStepSizeExceededError )
        {
            isMinimumStepSizeExceededForPerformIntegrationStep = true;
            BOOST_CHECK_EQUAL( minimumStepSizeExceededError.minimumStepSize, 100.0 );
        }

        // Check that the minimum step size was indeed exceeded.
        BOOST_CHECK( isMinimumStepSizeExceededForPerformIntegrationStep );
    }
}

//! Test if the state derivative evaliations are properly returned.
BOOST_AUTO_TEST_CASE( testStateDerivativeRetrievalFunction )
{
    using namespace tudat::numerical_integrators;
    using namespace unit_tests::numerical_integrator_test_functions;

    // This test is based on the Runge-Kutta-Fehlberg 4(5) coefficient set, hence the test does not
    // robustly ensure that the getCurrentStateDerivatives() works correctly for any given
    // coefficient set currently. This test is more of an preliminary check that the function
    // performs as required, with the extrapolation that it is likely to perform consistently in
    // this manner for any Runge-Kutta-type coefficient set.

    // Create test integrator.
    RungeKuttaVariableStepSizeIntegratorXd integrator(
                RungeKuttaCoefficients::get( RungeKuttaCoefficients::rungeKuttaFehlberg45 ),
                &computeVanDerPolStateDerivative,
                0.0,
                ( Eigen::VectorXd( 2 ) << 1.0, 2.0 ).finished( ),
                0.0, 10.0, 1.0E-8, 1.0E-8 );

    // Perform first integration step.
    integrator.performIntegrationStep( 1.0 );

    // Retrieve time and state after first integration step.
    const double previousTime = integrator.getCurrentIndependentVariable( );
    const Eigen::VectorXd previousState = integrator.getCurrentState( );

    // Perform additional integration step to verify that there are no problems with
    // getCurrentStateDerivatives after >1 iterations (i.e not being reset etc.).
    integrator.performIntegrationStep( integrator.getNextStepSize( ) );

    // Get current time and previous time step.
    const double currentTime = integrator.getCurrentIndependentVariable( );
    const double stepSize = currentTime - previousTime;

    // Retrieve state derivative values used in previous time step.
    std::vector< Eigen::VectorXd > stateDerivatives = integrator.getCurrentStateDerivatives( );

    // Check size of state derivative vector. This test is specifically set up to test the for the
    // number of stages in the RKF45 integrator.
    BOOST_CHECK_EQUAL( stateDerivatives.size( ), 6 );

    // Perform manual state derivative evaluations at previous time step using RKF45 method
    RungeKuttaCoefficients rkf45Coefficients = RungeKuttaCoefficients::get(
                RungeKuttaCoefficients::rungeKuttaFehlberg45 );
    std::vector< Eigen::VectorXd > directStateDerivativeValues;

    for ( int stage = 0; stage < rkf45Coefficients.cCoefficients.rows( ); stage++ )
    {
        // Compute the intermediate state to pass to the state derivative for this stage.
        Eigen::VectorXd intermediateState( previousState );

        // Compute the intermediate state.
        for ( int column = 0; column < stage; column++ )
        {
            intermediateState += stepSize * rkf45Coefficients.aCoefficients( stage, column )
                    * directStateDerivativeValues[ column ];
        }

        // Compute state derivative.
        directStateDerivativeValues.push_back(
                    computeVanDerPolStateDerivative(
                        previousTime +
                        rkf45Coefficients.cCoefficients( stage ) * stepSize,
                        intermediateState ) );

        // Check if manual result matched result from NumericalIntegrator.
        TUDAT_CHECK_MATRIX_CLOSE_FRACTION( directStateDerivativeValues.at( stage ),
                                           stateDerivatives.at( stage ),
                                           1.0E-15 );
    }
}

//! Test if integtrateTo function works for variable step size where last step is modified.
BOOST_AUTO_TEST_CASE( testVariableStepIntegrateToFunction )
{
    using namespace tudat::numerical_integrators;
    using namespace unit_tests::numerical_integrator_test_functions;

    // In this test, the integrateTo function is used with variable step size integrator, where the
    // step size is modified by the last step size, to ensure the correct operation of the
    // integrator in this case.

    // Create variable step size integrator.
    RungeKuttaVariableStepSizeIntegratorXd integrator(
                RungeKuttaCoefficients::get( RungeKuttaCoefficients::rungeKuttaFehlberg45 ),
                &computeSecondNonAutonomousModelStateDerivative,
                0.0,
                ( Eigen::VectorXd( 1 ) << 1.0 ).finished( ),
                0.0, 10.0, 1.0E-10, 1.0E-10 );

    // Use integrateTo function
    Eigen::VectorXd integratedValue = integrator.integrateTo( 0.5, 1.0 );
    double currentTime = integrator.getCurrentIndependentVariable( );

    // Check if current time is correct.
    BOOST_CHECK_CLOSE_FRACTION( currentTime, 0.5, std::numeric_limits< double >::epsilon( ) );

    // Create integrator to see if performing a single step with the given settings will indeed
    // result in the step size being adapted.
    RungeKuttaVariableStepSizeIntegratorXd verificationIntegrator(
                RungeKuttaCoefficients::get( RungeKuttaCoefficients::rungeKuttaFehlberg45 ),
                &computeSecondNonAutonomousModelStateDerivative,
                0.0,
                ( Eigen::VectorXd( 1 ) << 1.0 ).finished( ),
                0.0, 10.0, 1.0E-10, 1.0E-10 );

    // Check if single step size of 0.5 will be adapted.
    verificationIntegrator.performIntegrationStep( 0.5 );
    BOOST_CHECK_EQUAL( ( verificationIntegrator.getCurrentIndependentVariable( ) < 0.5 *
                         ( 1.0 - 10.0 * std::numeric_limits< double >::epsilon( ) ) ), true );

    // Use a fixed step size integrator to check the original result of integrateTo
    RungeKutta4IntegratorXd fixedStepSizeIntegrator(
                &computeSecondNonAutonomousModelStateDerivative,0.0,
                ( Eigen::VectorXd( 1 ) << 1.0 ).finished( ) );
    Eigen::VectorXd fixedStepIntegratedValue = integrator.integrateTo( 0.5, 0.01 );
    BOOST_CHECK_CLOSE_FRACTION( fixedStepIntegratedValue.x( ), integratedValue.x( ), 1.0E-10 );
}

BOOST_AUTO_TEST_SUITE_END( )

} // namespace unit_tests
} // namespace tudat
<|endoftext|>


<commit_before><commit_msg>[ASSERT] Applies technique in action.cpp<commit_after><|endoftext|>


<commit_before>#include <ellis/ellis_map_node.hpp>

#include <ellis/ellis_node.hpp>
#include <ellis/private/using.hpp>

namespace ellis {

ellis_map_node::~ellis_map_node()
{
  /* Do nothing; destruction is handled by ellis_node. */
}

ellis_node & ellis_map_node::operator[](const std::string &key)
{
  auto it = m_node.m_blk->m_map.find(key);
  return it->second;
}

void ellis_map_node::insert(const std::string &key, const ellis_node &val)
{
  m_node.m_blk->m_map.emplace(key, val);
}

void ellis_map_node::insert(const std::string &key, ellis_node &&val)
{
  m_node.m_blk->m_map.emplace(key, std::move(val));
}

}  /* namespace ellis */
<commit_msg>fix miss behavior<commit_after>#include <ellis/ellis_map_node.hpp>

#include <ellis/ellis_node.hpp>
#include <ellis/private/using.hpp>

namespace ellis {

ellis_map_node::~ellis_map_node()
{
  /* Do nothing; destruction is handled by ellis_node. */
}

ellis_node & ellis_map_node::operator[](const std::string &key)
{
  return const_cast<ellis_node&>(
      (*(static_cast<const ellis_map_node*>(this)))[key]);
}

const ellis_node & ellis_map_node::operator[](const std::string &key) const
{
  const auto it = m_node.m_blk->m_map.find(key);
  if (it == m_node.m_blk->m_map.end()) {
    auto added = m_node.m_blk->m_map.emplace(key, ellis_node(ellis_type::NIL));
    assert(added.second == true);
    return added.first->second;
  }
  return it->second;
}

void ellis_map_node::insert(const std::string &key, const ellis_node &val)
{
  m_node.m_blk->m_map.emplace(key, val);
}

void ellis_map_node::insert(const std::string &key, ellis_node &&val)
{
  m_node.m_blk->m_map.emplace(key, std::move(val));
}

}  /* namespace ellis */
<|endoftext|>


<commit_before><commit_msg>export assert_fail<commit_after><|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkOclResourceServiceImpl_p.h"

OclResourceService::~OclResourceService()
{
}

OclResourceServiceImpl::OclResourceServiceImpl()
: m_ContextCollection(NULL),
  m_ProgramStorage(),
  m_CurrentPlatformNum(0),
  m_CurrentDeviceNum(0),
  m_ContextInitialized(false)
{
  m_ProgramStorageMutex = itk::FastMutexLock::New();
}

OclResourceServiceImpl::~OclResourceServiceImpl()
{
  // if map non-empty, release all remaining
  if( m_ProgramStorage.size() )
  {
    ProgramMapType::iterator it = m_ProgramStorage.begin();
    while(it != m_ProgramStorage.end() )
    {
      clReleaseProgram( it->second.program );
      m_ProgramStorage.erase( it++ );
    }
  }

  if( m_ContextCollection )
    delete m_ContextCollection;
}

bool OclResourceServiceImpl::InitContext()
{
  if (m_ContextInitialized)
    return true;

  m_ContextCollection = new OclContextCollection();
  m_ContextCollection->GetPreferredPlatformAndDeviceNum(m_CurrentPlatformNum, m_CurrentDeviceNum);

  m_ContextInitialized = true;
}

void OclResourceServiceImpl::SpecifyPlatformAndDevice(cl_uint platformNum, cl_uint deviceNum, bool sharedCLGL)
{
  if (!m_ContextInitialized)
    InitContext();

  oclPrintFullCLInfo();

  m_CurrentPlatformNum = platformNum;
  m_CurrentDeviceNum   = deviceNum;

  bool supported = false;

  // Check if the sharing extension is supported by the device
  if (sharedCLGL)
    supported = IsCLExtensionSupported(CL_GL_SHARING_EXT, GetCurrentDevice());

  if( m_ContextCollection == NULL )
    m_ContextCollection = new OclContextCollection();

  if (sharedCLGL && supported)
    m_ContextCollection->EnableCLGLContextSharing(true);
  else
    m_ContextCollection->EnableCLGLContextSharing(false);
}

cl_context OclResourceServiceImpl::GetContext()
{
  if (!m_ContextInitialized)
    InitContext();

  return m_ContextCollection->GetContext(m_CurrentPlatformNum, m_CurrentDeviceNum);
}

cl_command_queue OclResourceServiceImpl::GetCommandQueue()
{
  // check if queue valid
  cl_context clQueueContext;

  // check if there is a context available
  // if not create one
  if (!m_ContextInitialized)
    InitContext();

  cl_int clErr = clGetCommandQueueInfo( m_ContextCollection->GetCommandQueue(m_CurrentPlatformNum, m_CurrentDeviceNum), CL_QUEUE_CONTEXT, sizeof(clQueueContext), &clQueueContext, NULL );
  if( clErr != CL_SUCCESS || clQueueContext != m_ContextCollection->GetContext(m_CurrentPlatformNum, m_CurrentDeviceNum))
  {
    MITK_WARN << "Have no valid command queue. Query returned : " << GetOclErrorAsString( clErr );
    return NULL;
  }

  return m_ContextCollection->GetCommandQueue(m_CurrentPlatformNum, m_CurrentDeviceNum);
}

cl_device_id OclResourceServiceImpl::GetCurrentDevice()
{
  if (!m_ContextInitialized)
    InitContext();

  return m_ContextCollection->GetDeviceID(m_CurrentPlatformNum, m_CurrentDeviceNum);
}

cl_platform_id OclResourceServiceImpl::GetCurrentPlatform()
{
  if (!m_ContextInitialized)
    InitContext();
  return m_ContextCollection->GetPlatformID(m_CurrentPlatformNum);
}

bool OclResourceServiceImpl::GetIsFormatSupported(cl_image_format *fmt)
{
  if (!m_ContextInitialized)
    InitContext();

  cl_image_format temp;
  temp.image_channel_data_type = fmt->image_channel_data_type;
  temp.image_channel_order = fmt->image_channel_order;

  return (this->m_ContextCollection->GetImageFormat(m_CurrentPlatformNum, m_CurrentDeviceNum)->GetNearestSupported(&temp, fmt));
}

void OclResourceServiceImpl::PrintContextInfo()
{
  if (!m_ContextInitialized)
    InitContext();

  // context and devices available
  if( m_ContextCollection->CanProvideContext() )
  {
    this->m_ContextCollection->PrintContextInfo(m_CurrentPlatformNum, m_CurrentDeviceNum);
  }
}

void OclResourceServiceImpl::InsertProgram(cl_program _program_in, std::string name, bool forceOverride)
{
  typedef std::pair < std::string, ProgramData > MapElemPair;
  std::pair< ProgramMapType::iterator, bool> retValue;

  ProgramData data;
  data.counter = 1;
  data.program = _program_in;
  data.mutex = itk::FastMutexLock::New();

  // program is not stored, insert first instance (count = 1)
  m_ProgramStorageMutex->Lock();
  retValue = m_ProgramStorage.insert( MapElemPair(name, data) );
  m_ProgramStorageMutex->Unlock();

  // insertion failed, i.e. a program with same name exists
  if( !retValue.second )
  {
    std::string overrideMsg("");
    if( forceOverride )
    {
      // overwrite old instance
      m_ProgramStorage[name].program = _program_in;
      overrideMsg +=" The old program was overwritten!";
    }

    MITK_WARN("OpenCL.ResourceService") << "The program " << name << " already exists." << overrideMsg;
  }
}

cl_program OclResourceServiceImpl::GetProgram(const std::string &name)
{
  ProgramMapType::iterator it = m_ProgramStorage.find(name);

  if( it != m_ProgramStorage.end() )
  {
    it->second.mutex->Lock();
    // first check if the program was deleted
    // while waiting on the mutex
    if ( it->second.counter == 0 )
      mitkThrow() << "Requested OpenCL Program (" << name <<") not found."
                  << "(deleted while waiting on the mutex)";
    // increase the reference counter
    // by one if the program is requestet
    it->second.counter += 1;
    it->second.mutex->Unlock();

    // return the cl_program
    return it->second.program;
  }

  mitkThrow() << "Requested OpenCL Program (" << name <<") not found.";
}

void OclResourceServiceImpl::RemoveProgram(const std::string& name)
{
  ProgramMapType::iterator it = m_ProgramStorage.find(name);
  cl_int status = 0;
  cl_program program = NULL;

  if( it != m_ProgramStorage.end() )
  {
    it->second.mutex->Lock();
    // decrease reference by one
    it->second.counter -= 1;
    it->second.mutex->Unlock();

    // remove from the storage
    if( it->second.counter == 0 )
    {
      program = it->second.program;

      m_ProgramStorageMutex->Lock();
      m_ProgramStorage.erase(it);
      m_ProgramStorageMutex->Unlock();
    }

    // delete the program
    if( program )
    {
      status = clReleaseProgram(program);
      CHECK_OCL_ERR(status);
    }
  }
  else
  {
    MITK_WARN("OpenCL.ResourceService") << "Program name [" <<name <<"] passed for deletion not found.";
  }
}

void OclResourceServiceImpl::InvalidateStorage()
{
  // do nothing if no context present, there is also no storage
  if( !m_ContextCollection->CanProvideContext() )
    return;

  // query the map
  ProgramMapType::iterator it = m_ProgramStorage.begin();

  while(it != m_ProgramStorage.end() )
  {
    // query the program build status
    cl_build_status status;
    unsigned int query = clGetProgramBuildInfo( it->second.program, m_ContextCollection->GetDeviceID(m_CurrentPlatformNum, m_CurrentDeviceNum), CL_PROGRAM_BUILD_STATUS, sizeof(cl_int), &status, NULL );
    CHECK_OCL_ERR( query )

    MITK_DEBUG << "Quering status for " << it->first << std::endl;

    // remove program if no succesfull build
    // we need to pay attention to the increment of the iterator when erasing current element
    if( status != CL_BUILD_SUCCESS )
    {
      MITK_DEBUG << " +-- Build failed " << std::endl;
      m_ProgramStorage.erase( it++ );
    }
    else
    {
      ++it;
    }
  }
}

unsigned int OclResourceServiceImpl::GetMaximumImageSize(unsigned int dimension, cl_mem_object_type _imagetype)
{
  if( ! m_ContextCollection->CanProvideContext() )
    return 0;

  size_t retValue = 0;

  switch(dimension)
  {
  case 0:
    if ( _imagetype == CL_MEM_OBJECT_IMAGE2D)
      clGetDeviceInfo( m_ContextCollection->GetDeviceID(m_CurrentPlatformNum, m_CurrentDeviceNum), CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( cl_uint ), &retValue, NULL );
    else
      clGetDeviceInfo( m_ContextCollection->GetDeviceID(m_CurrentPlatformNum, m_CurrentDeviceNum), CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( cl_uint ), &retValue, NULL );

    break;
  case 1:
    if ( _imagetype == CL_MEM_OBJECT_IMAGE2D)
      clGetDeviceInfo( m_ContextCollection->GetDeviceID(m_CurrentPlatformNum, m_CurrentDeviceNum), CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( cl_uint ), &retValue, NULL );
    else
      clGetDeviceInfo( m_ContextCollection->GetDeviceID(m_CurrentPlatformNum, m_CurrentDeviceNum), CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( cl_uint ), &retValue, NULL );
    break;
  case 2:
    if ( _imagetype == CL_MEM_OBJECT_IMAGE3D)
      clGetDeviceInfo( m_ContextCollection->GetDeviceID(m_CurrentPlatformNum, m_CurrentDeviceNum), CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( cl_uint ), &retValue, NULL);
    break;
  default:
    MITK_WARN << "Could not recieve info. Desired dimension or object type does not exist. ";
    break;
  }

  return retValue;
}
<commit_msg>Bug #4210: Disabled the extensive printouts<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkOclResourceServiceImpl_p.h"

OclResourceService::~OclResourceService()
{
}

OclResourceServiceImpl::OclResourceServiceImpl()
: m_ContextCollection(NULL),
  m_ProgramStorage(),
  m_CurrentPlatformNum(0),
  m_CurrentDeviceNum(0),
  m_ContextInitialized(false)
{
  m_ProgramStorageMutex = itk::FastMutexLock::New();
}

OclResourceServiceImpl::~OclResourceServiceImpl()
{
  // if map non-empty, release all remaining
  if( m_ProgramStorage.size() )
  {
    ProgramMapType::iterator it = m_ProgramStorage.begin();
    while(it != m_ProgramStorage.end() )
    {
      clReleaseProgram( it->second.program );
      m_ProgramStorage.erase( it++ );
    }
  }

  if( m_ContextCollection )
    delete m_ContextCollection;
}

bool OclResourceServiceImpl::InitContext()
{
  if (m_ContextInitialized)
    return true;

  m_ContextCollection = new OclContextCollection();
  m_ContextCollection->GetPreferredPlatformAndDeviceNum(m_CurrentPlatformNum, m_CurrentDeviceNum);

  m_ContextInitialized = true;
}

void OclResourceServiceImpl::SpecifyPlatformAndDevice(cl_uint platformNum, cl_uint deviceNum, bool sharedCLGL)
{
  if (!m_ContextInitialized)
    InitContext();

  //oclPrintFullCLInfo();

  m_CurrentPlatformNum = platformNum;
  m_CurrentDeviceNum   = deviceNum;

  bool supported = false;

  // Check if the sharing extension is supported by the device
  if (sharedCLGL)
    supported = IsCLExtensionSupported(CL_GL_SHARING_EXT, GetCurrentDevice());

  if( m_ContextCollection == NULL )
    m_ContextCollection = new OclContextCollection();

  if (sharedCLGL && supported)
    m_ContextCollection->EnableCLGLContextSharing(true);
  else
    m_ContextCollection->EnableCLGLContextSharing(false);
}

cl_context OclResourceServiceImpl::GetContext()
{
  if (!m_ContextInitialized)
    InitContext();

  return m_ContextCollection->GetContext(m_CurrentPlatformNum, m_CurrentDeviceNum);
}

cl_command_queue OclResourceServiceImpl::GetCommandQueue()
{
  // check if queue valid
  cl_context clQueueContext;

  // check if there is a context available
  // if not create one
  if (!m_ContextInitialized)
    InitContext();

  cl_int clErr = clGetCommandQueueInfo( m_ContextCollection->GetCommandQueue(m_CurrentPlatformNum, m_CurrentDeviceNum), CL_QUEUE_CONTEXT, sizeof(clQueueContext), &clQueueContext, NULL );
  if( clErr != CL_SUCCESS || clQueueContext != m_ContextCollection->GetContext(m_CurrentPlatformNum, m_CurrentDeviceNum))
  {
    MITK_WARN << "Have no valid command queue. Query returned : " << GetOclErrorAsString( clErr );
    return NULL;
  }

  return m_ContextCollection->GetCommandQueue(m_CurrentPlatformNum, m_CurrentDeviceNum);
}

cl_device_id OclResourceServiceImpl::GetCurrentDevice()
{
  if (!m_ContextInitialized)
    InitContext();

  return m_ContextCollection->GetDeviceID(m_CurrentPlatformNum, m_CurrentDeviceNum);
}

cl_platform_id OclResourceServiceImpl::GetCurrentPlatform()
{
  if (!m_ContextInitialized)
    InitContext();
  return m_ContextCollection->GetPlatformID(m_CurrentPlatformNum);
}

bool OclResourceServiceImpl::GetIsFormatSupported(cl_image_format *fmt)
{
  if (!m_ContextInitialized)
    InitContext();

  cl_image_format temp;
  temp.image_channel_data_type = fmt->image_channel_data_type;
  temp.image_channel_order = fmt->image_channel_order;

  return (this->m_ContextCollection->GetImageFormat(m_CurrentPlatformNum, m_CurrentDeviceNum)->GetNearestSupported(&temp, fmt));
}

void OclResourceServiceImpl::PrintContextInfo()
{
  if (!m_ContextInitialized)
    InitContext();

  // context and devices available
  if( m_ContextCollection->CanProvideContext() )
  {
    this->m_ContextCollection->PrintContextInfo(m_CurrentPlatformNum, m_CurrentDeviceNum);
  }
}

void OclResourceServiceImpl::InsertProgram(cl_program _program_in, std::string name, bool forceOverride)
{
  typedef std::pair < std::string, ProgramData > MapElemPair;
  std::pair< ProgramMapType::iterator, bool> retValue;

  ProgramData data;
  data.counter = 1;
  data.program = _program_in;
  data.mutex = itk::FastMutexLock::New();

  // program is not stored, insert first instance (count = 1)
  m_ProgramStorageMutex->Lock();
  retValue = m_ProgramStorage.insert( MapElemPair(name, data) );
  m_ProgramStorageMutex->Unlock();

  // insertion failed, i.e. a program with same name exists
  if( !retValue.second )
  {
    std::string overrideMsg("");
    if( forceOverride )
    {
      // overwrite old instance
      m_ProgramStorage[name].program = _program_in;
      overrideMsg +=" The old program was overwritten!";
    }

    MITK_WARN("OpenCL.ResourceService") << "The program " << name << " already exists." << overrideMsg;
  }
}

cl_program OclResourceServiceImpl::GetProgram(const std::string &name)
{
  ProgramMapType::iterator it = m_ProgramStorage.find(name);

  if( it != m_ProgramStorage.end() )
  {
    it->second.mutex->Lock();
    // first check if the program was deleted
    // while waiting on the mutex
    if ( it->second.counter == 0 )
      mitkThrow() << "Requested OpenCL Program (" << name <<") not found."
                  << "(deleted while waiting on the mutex)";
    // increase the reference counter
    // by one if the program is requestet
    it->second.counter += 1;
    it->second.mutex->Unlock();

    // return the cl_program
    return it->second.program;
  }

  mitkThrow() << "Requested OpenCL Program (" << name <<") not found.";
}

void OclResourceServiceImpl::RemoveProgram(const std::string& name)
{
  ProgramMapType::iterator it = m_ProgramStorage.find(name);
  cl_int status = 0;
  cl_program program = NULL;

  if( it != m_ProgramStorage.end() )
  {
    it->second.mutex->Lock();
    // decrease reference by one
    it->second.counter -= 1;
    it->second.mutex->Unlock();

    // remove from the storage
    if( it->second.counter == 0 )
    {
      program = it->second.program;

      m_ProgramStorageMutex->Lock();
      m_ProgramStorage.erase(it);
      m_ProgramStorageMutex->Unlock();
    }

    // delete the program
    if( program )
    {
      status = clReleaseProgram(program);
      CHECK_OCL_ERR(status);
    }
  }
  else
  {
    MITK_WARN("OpenCL.ResourceService") << "Program name [" <<name <<"] passed for deletion not found.";
  }
}

void OclResourceServiceImpl::InvalidateStorage()
{
  // do nothing if no context present, there is also no storage
  if( !m_ContextCollection->CanProvideContext() )
    return;

  // query the map
  ProgramMapType::iterator it = m_ProgramStorage.begin();

  while(it != m_ProgramStorage.end() )
  {
    // query the program build status
    cl_build_status status;
    unsigned int query = clGetProgramBuildInfo( it->second.program, m_ContextCollection->GetDeviceID(m_CurrentPlatformNum, m_CurrentDeviceNum), CL_PROGRAM_BUILD_STATUS, sizeof(cl_int), &status, NULL );
    CHECK_OCL_ERR( query )

    MITK_DEBUG << "Quering status for " << it->first << std::endl;

    // remove program if no succesfull build
    // we need to pay attention to the increment of the iterator when erasing current element
    if( status != CL_BUILD_SUCCESS )
    {
      MITK_DEBUG << " +-- Build failed " << std::endl;
      m_ProgramStorage.erase( it++ );
    }
    else
    {
      ++it;
    }
  }
}

unsigned int OclResourceServiceImpl::GetMaximumImageSize(unsigned int dimension, cl_mem_object_type _imagetype)
{
  if( ! m_ContextCollection->CanProvideContext() )
    return 0;

  size_t retValue = 0;

  switch(dimension)
  {
  case 0:
    if ( _imagetype == CL_MEM_OBJECT_IMAGE2D)
      clGetDeviceInfo( m_ContextCollection->GetDeviceID(m_CurrentPlatformNum, m_CurrentDeviceNum), CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( cl_uint ), &retValue, NULL );
    else
      clGetDeviceInfo( m_ContextCollection->GetDeviceID(m_CurrentPlatformNum, m_CurrentDeviceNum), CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( cl_uint ), &retValue, NULL );

    break;
  case 1:
    if ( _imagetype == CL_MEM_OBJECT_IMAGE2D)
      clGetDeviceInfo( m_ContextCollection->GetDeviceID(m_CurrentPlatformNum, m_CurrentDeviceNum), CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( cl_uint ), &retValue, NULL );
    else
      clGetDeviceInfo( m_ContextCollection->GetDeviceID(m_CurrentPlatformNum, m_CurrentDeviceNum), CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( cl_uint ), &retValue, NULL );
    break;
  case 2:
    if ( _imagetype == CL_MEM_OBJECT_IMAGE3D)
      clGetDeviceInfo( m_ContextCollection->GetDeviceID(m_CurrentPlatformNum, m_CurrentDeviceNum), CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( cl_uint ), &retValue, NULL);
    break;
  default:
    MITK_WARN << "Could not recieve info. Desired dimension or object type does not exist. ";
    break;
  }

  return retValue;
}
<|endoftext|>


<commit_before>#pragma once

#include "fly/fly.hpp"
#include "fly/logger/detail/styler_proxy.hpp"
#include "fly/traits/traits.hpp"
#include "fly/types/numeric/literals.hpp"

#include <cstdint>
#include <memory>
#include <ostream>
#include <stack>
#include <type_traits>
#include <utility>

namespace fly::logger {

/**
 * Constants to modify the style of a std::ostream.
 *
 * Note: Windows only supports Bold and Underline, and Bold can more accurately be interpreted as
 * higher intensity color.
 */
enum class Style : std::uint8_t
{
    Default,
    Blink,
    Bold,
    Dim,
    Italic,
    Strike,
    Underline,
};

/**
 * Struct to modify the foreground or background color of a std::ostream.
 */
struct Color
{
    /**
     * Constants for standard colors.
     *
     * On Linux and macOS, a color may be any value in the range [0, 255]. While only the 8 standard
     * colors are listed here, any 8-bit integer value may be cast to a color. The color values
     * correspond to the ANSI 256-color lookup table:
     *
     *     https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit.
     *
     * On Windows, the color may only be one of the 8 standard colors listed here.
     */
    enum StandardColor
    {
        Black,
        Red,
        Green,
        Yellow,
        Blue,
        Magenta,
        Cyan,
        White,
    };

    /**
     * Constants for the plane that should be modified.
     */
    enum Plane
    {
        Foreground,
        Background,
    };

    /**
     * Construct a Color as either a foreground or background color.
     *
     * @param color The 256-color value to apply.
     * @param plane The plane (default foreground) that should be modified.
     */
    explicit constexpr Color(std::uint8_t color, Plane plane = Foreground) noexcept :
        m_color(color),
        m_plane(plane)
    {
    }

    const std::uint8_t m_color;
    const Plane m_plane;
};

/**
 * Struct to modify the cursor position within a std::ostream.
 */
struct Cursor
{
    /**
     * Constants for the direction that the cursor should move.
     */
    enum Direction
    {
        Up,
        Down,
        Forward,
        Backward,
    };

    /**
     * Construct a Cursor instance with a direction and distance.
     *
     * @param direction The direction to move the cursor.
     * @param distance The distance to move the cursor.
     */
    constexpr Cursor(Direction direction, std::uint8_t distance = 1) noexcept :
        m_direction(direction),
        m_distance(distance > 0 ? distance : 1)
    {
    }

    const Direction m_direction;
    const std::uint8_t m_distance;
};

/**
 * IO manipulator to stylize a std::ostream with style and color. This manipulator allows for
 * applying any number of styles (e.g. bold, italic), a foreground color, and background color to
 * the std::ostream. It also allows for modifying the cursor position within the stream.
 *
 * Upon destruction, the styles and colors applied by this manipulator are reverted. Manipulations
 * of the cursor position are not reverted.
 *
 * Only standard output and error streams are supported. Any other streams will remain
 * unmanipulated.
 *
 * Not all styles and colors are supported on all platforms. Unsupported styles and colors will be
 * silently ignored.
 *
 * Callers may invoke and stream a Styler instance inline, or hold onto a Styler instance for as
 * long as desired (in which case, it will not take effect until streamed onto the std::ostream).
 *
 * Stream inline:
 *
 *     std::cout << fly::Styler(fly::Style::Bold, fly::Color::Red) << "This is bold and red\n";
 *     std::cout << "This is neither bold nor red\n";
 *
 * Scoped instance:
 *
 *     {
 *         fly::Styler styler(fly::Style::Bold, fly::Color::Red);
 *         std::cout << "This is neither bold nor red\n";
 *         std::cout << styler << "This is bold and red\n";
 *         std::cout << "This is also bold and red\n";
 *     }
 *     std::cout << "This is neither bold nor red\n";
 *
 * @author Timothy Flynn (trflynn89@pm.me)
 * @version July 11, 2020
 */
class Styler
{
public:
    /**
     * Construct a Styler with a single modifier. The template modifier type must be one of [Style,
     * Color, Color::StandardColor, Cursor, Cursor::Direction]. The enumeration [Style are coverted
     * to their parent structure types.
     *
     * @tparam Modifier The type of the modifier to apply to the std::ostream.
     *
     * @param modifier The modifier to apply to the std::ostream.
     */
    template <typename Modifier>
    explicit Styler(Modifier &&modifier) noexcept
    {
        set_modifier(modifier);
    }

    /**
     * Construct a Styler with multiple modifiers. The template modifier types must be one of
     * [Style, Color, Color::StandardColor, Cursor, Cursor::Direction]. The enumeration types are
     * coverted to their parent structure types.
     *
     * Any number of Style and Cursor instances may be used and will be combined in the Styler. Only
     * one foreground and one background Color instance may be used; if more than one of each is
     * provided, only the last instance provided will take effect.
     *
     * @tparam Modifier The type of the modifier to apply to the std::ostream.
     * @tparam Modifiers Variadic types of the remaining modifiers to apply to the std::ostream.
     *
     * @param modifier The modifier to apply to the std::ostream.
     * @param modifiers The remaining modifiers to apply to the std::ostream.
     */
    template <typename Modifier, typename... Modifiers>
    Styler(Modifier &&modifier, Modifiers &&...modifiers) noexcept :
        Styler(std::forward<Modifiers>(modifiers)...)
    {
        set_modifier(modifier);
    }

    /**
     * Stream a Styler onto a std::ostream. The Styler creates a StylerProxy instance responsible
     * for performing the underlying stream manipulations. That instance is active until the
     * streamed Styler goes out of scope.
     *
     * @param stream The stream to manipulate.
     * @param styler The Styler holding the manipulation to apply to the stream.
     *
     * @return A reference to the created StylerProxy instance.
     */
    friend detail::StylerProxy &operator<<(std::ostream &stream, const Styler &styler);

private:
    /**
     * Store a modifier as either a style, color, or position. The template modifier type must
     * be one of [Style, Color, Color::StandardColor, Cursor, Cursor::Direction]. The enumeration
     * types are coverted to their parent structure types.
     *
     * @tparam Modifier The type of the modifier to apply to the std::ostream.
     *
     * @param modifier The modifier to apply to the std::ostream.
     */
    template <typename Modifier>
    void set_modifier(Modifier &&modifier)
    {
        using DecayedModifier = std::decay_t<Modifier>;

        static_assert(
            any_same_v<
                DecayedModifier,
                Style,
                Color,
                Color::StandardColor,
                Cursor,
                Cursor::Direction>,
            "Styler can only be constructed with a valid modifier type");

        if constexpr (std::is_same_v<DecayedModifier, Style>)
        {
            m_styles.emplace(std::move(modifier));
        }
        else if constexpr (any_same_v<DecayedModifier, Color, Color::StandardColor>)
        {
            m_colors.emplace(std::move(modifier));
        }
        else if constexpr (any_same_v<DecayedModifier, Cursor, Cursor::Direction>)
        {
            m_cursors.emplace(std::move(modifier));
        }
    }

    // Store modifier instances in a stack because the variadic constructor processes parameters
    // from right-to-left (due to the delegating constructor invocation).
    std::stack<Style> m_styles;
    std::stack<Color> m_colors;
    std::stack<Cursor> m_cursors;

    std::unique_ptr<detail::StylerProxy> m_proxy;
};

} // namespace fly::logger

namespace fly {
inline namespace literals {
    inline namespace styler_literals {

        /**
         * Type-safe integer literal suffix to construct a Color as a foreground color. The integer
         * literal must be in the range [0, 255].
         *
         * @tparam Literals The numeric literals from which to construct a 256-color value.
         *
         * @return The constructed Color.
         */
        template <char... Literals>
        FLY_CONSTEVAL inline fly::logger::Color operator"" _c()
        {
            // Convert to std::uint8_t via numeric literal to ensure the provided color is valid.
            const std::uint8_t validated_color = operator"" _u8<Literals...>();
            return fly::logger::Color(validated_color);
        }

    } // namespace styler_literals
} // namespace literals
} // namespace fly
<commit_msg>Use a C++20 concepts in the fly::logger::Styler IO manipulator<commit_after>#pragma once

#include "fly/fly.hpp"
#include "fly/logger/detail/styler_proxy.hpp"
#include "fly/traits/concepts.hpp"
#include "fly/types/numeric/literals.hpp"

#include <cstdint>
#include <memory>
#include <ostream>
#include <stack>
#include <utility>

namespace fly::logger {

/**
 * Constants to modify the style of a std::ostream.
 *
 * Note: Windows only supports Bold and Underline, and Bold can more accurately be interpreted as
 * higher intensity color.
 */
enum class Style : std::uint8_t
{
    Default,
    Blink,
    Bold,
    Dim,
    Italic,
    Strike,
    Underline,
};

/**
 * Struct to modify the foreground or background color of a std::ostream.
 */
struct Color
{
    /**
     * Constants for standard colors.
     *
     * On Linux and macOS, a color may be any value in the range [0, 255]. While only the 8 standard
     * colors are listed here, any 8-bit integer value may be cast to a color. The color values
     * correspond to the ANSI 256-color lookup table:
     *
     *     https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit.
     *
     * On Windows, the color may only be one of the 8 standard colors listed here.
     */
    enum StandardColor
    {
        Black,
        Red,
        Green,
        Yellow,
        Blue,
        Magenta,
        Cyan,
        White,
    };

    /**
     * Constants for the plane that should be modified.
     */
    enum Plane
    {
        Foreground,
        Background,
    };

    /**
     * Construct a Color as either a foreground or background color.
     *
     * @param color The 256-color value to apply.
     * @param plane The plane (default foreground) that should be modified.
     */
    explicit constexpr Color(std::uint8_t color, Plane plane = Foreground) noexcept :
        m_color(color),
        m_plane(plane)
    {
    }

    const std::uint8_t m_color;
    const Plane m_plane;
};

/**
 * Struct to modify the cursor position within a std::ostream.
 */
struct Cursor
{
    /**
     * Constants for the direction that the cursor should move.
     */
    enum Direction
    {
        Up,
        Down,
        Forward,
        Backward,
    };

    /**
     * Construct a Cursor instance with a direction and distance.
     *
     * @param direction The direction to move the cursor.
     * @param distance The distance to move the cursor.
     */
    constexpr Cursor(Direction direction, std::uint8_t distance = 1) noexcept :
        m_direction(direction),
        m_distance(distance > 0 ? distance : 1)
    {
    }

    const Direction m_direction;
    const std::uint8_t m_distance;
};

/**
 * Concept that is satisfied if the provided type is a valid stream modifier.
 */
template <typename T>
concept Modifier = fly::SameAsAny<T, Style, Color, Color::StandardColor, Cursor, Cursor::Direction>;

/**
 * IO manipulator to stylize a std::ostream with style and color. This manipulator allows for
 * applying any number of styles (e.g. bold, italic), a foreground color, and background color to
 * the std::ostream. It also allows for modifying the cursor position within the stream.
 *
 * Upon destruction, the styles and colors applied by this manipulator are reverted. Manipulations
 * of the cursor position are not reverted.
 *
 * Only standard output and error streams are supported. Any other streams will remain
 * unmanipulated.
 *
 * Not all styles and colors are supported on all platforms. Unsupported styles and colors will be
 * silently ignored.
 *
 * Callers may invoke and stream a Styler instance inline, or hold onto a Styler instance for as
 * long as desired (in which case, it will not take effect until streamed onto the std::ostream).
 *
 * Stream inline:
 *
 *     std::cout << fly::Styler(fly::Style::Bold, fly::Color::Red) << "This is bold and red\n";
 *     std::cout << "This is neither bold nor red\n";
 *
 * Scoped instance:
 *
 *     {
 *         fly::Styler styler(fly::Style::Bold, fly::Color::Red);
 *         std::cout << "This is neither bold nor red\n";
 *         std::cout << styler << "This is bold and red\n";
 *         std::cout << "This is also bold and red\n";
 *     }
 *     std::cout << "This is neither bold nor red\n";
 *
 * @author Timothy Flynn (trflynn89@pm.me)
 * @version July 11, 2020
 */
class Styler
{
public:
    /**
     * Construct a Styler with a single modifier. The template modifier type must be one of [Style,
     * Color, Color::StandardColor, Cursor, Cursor::Direction]. The enumeration [Style are coverted
     * to their parent structure types.
     *
     * @tparam ModifierType The type of the modifier to apply to the std::ostream.
     *
     * @param modifier The modifier to apply to the std::ostream.
     */
    template <Modifier ModifierType>
    explicit Styler(ModifierType &&modifier) noexcept
    {
        set_modifier(modifier);
    }

    /**
     * Construct a Styler with multiple modifiers. The template modifier types must be one of
     * [Style, Color, Color::StandardColor, Cursor, Cursor::Direction]. The enumeration types are
     * coverted to their parent structure types.
     *
     * Any number of Style and Cursor instances may be used and will be combined in the Styler. Only
     * one foreground and one background Color instance may be used; if more than one of each is
     * provided, only the last instance provided will take effect.
     *
     * @tparam ModifierType The type of the modifier to apply to the std::ostream.
     * @tparam ModifierTypes Variadic types of the remaining modifiers to apply to the std::ostream.
     *
     * @param modifier The modifier to apply to the std::ostream.
     * @param modifiers The remaining modifiers to apply to the std::ostream.
     */
    template <Modifier ModifierType, Modifier... ModifierTypes>
    Styler(ModifierType &&modifier, ModifierTypes &&...modifiers) noexcept :
        Styler(std::forward<ModifierTypes>(modifiers)...)
    {
        set_modifier(modifier);
    }

    /**
     * Stream a Styler onto a std::ostream. The Styler creates a StylerProxy instance responsible
     * for performing the underlying stream manipulations. That instance is active until the
     * streamed Styler goes out of scope.
     *
     * @param stream The stream to manipulate.
     * @param styler The Styler holding the manipulation to apply to the stream.
     *
     * @return A reference to the created StylerProxy instance.
     */
    friend detail::StylerProxy &operator<<(std::ostream &stream, const Styler &styler);

private:
    /**
     * Store a modifier as either a style, color, or position. The template modifier type must
     * be one of [Style, Color, Color::StandardColor, Cursor, Cursor::Direction]. The enumeration
     * types are coverted to their parent structure types.
     *
     * @tparam ModifierType The type of the modifier to apply to the std::ostream.
     *
     * @param modifier The modifier to apply to the std::ostream.
     */
    template <Modifier ModifierType>
    void set_modifier(ModifierType &&modifier)
    {
        if constexpr (fly::SameAs<ModifierType, Style>)
        {
            m_styles.emplace(std::move(modifier));
        }
        else if constexpr (fly::SameAsAny<ModifierType, Color, Color::StandardColor>)
        {
            m_colors.emplace(std::move(modifier));
        }
        else if constexpr (fly::SameAsAny<ModifierType, Cursor, Cursor::Direction>)
        {
            m_cursors.emplace(std::move(modifier));
        }
    }

    // Store modifier instances in a stack because the variadic constructor processes parameters
    // from right-to-left (due to the delegating constructor invocation).
    std::stack<Style> m_styles;
    std::stack<Color> m_colors;
    std::stack<Cursor> m_cursors;

    std::unique_ptr<detail::StylerProxy> m_proxy;
};

} // namespace fly::logger

namespace fly {
inline namespace literals {
    inline namespace styler_literals {

        /**
         * Type-safe integer literal suffix to construct a Color as a foreground color. The integer
         * literal must be in the range [0, 255].
         *
         * @tparam Literals The numeric literals from which to construct a 256-color value.
         *
         * @return The constructed Color.
         */
        template <char... Literals>
        FLY_CONSTEVAL inline fly::logger::Color operator"" _c()
        {
            // Convert to std::uint8_t via numeric literal to ensure the provided color is valid.
            const std::uint8_t validated_color = operator"" _u8<Literals...>();
            return fly::logger::Color(validated_color);
        }

    } // namespace styler_literals
} // namespace literals
} // namespace fly
<|endoftext|>


<commit_before><commit_msg>fixes bug resulting in degenerate segments<commit_after><|endoftext|>


<commit_before>/*
  * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License").
  * You may not use this file except in compliance with the License.
  * A copy of the License is located at
  *
  *  http://aws.amazon.com/apache2.0
  *
  * or in the "license" file accompanying this file. This file is distributed
  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  * express or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */

#include <aws/external/gtest.h>
#include <aws/testing/MemoryTesting.h>
#include <aws/identity-management/auth/PersistentCognitoIdentityProvider.h>
#include <aws/core/utils/FileSystemUtils.h>
#include <aws/core/utils/json/JsonSerializer.h>
#include <fstream>

//since MAC isn't posix compliant, it likes to complain about std::tmpnam. Also, it the std:: function is supposed
//to be different than the posix defined function.
//turn it off because we need it for this test and this isn't production code
//anyways.
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif

#ifdef _MSC_VER
#pragma warning(disable: 4996) // _CRT_SECURE_NO_WARNINGS
#endif

using namespace Aws::Auth;
using namespace Aws::Utils;
using namespace Aws::Utils::Json;

#ifdef _WIN32
Aws::String ComputeIdentityFilePath()
{
    static bool s_initialized = false;
    static Aws::String s_tempName;

    if(s_tempName.empty())
    {
        char tempName[L_tmpnam_s];
        memset(tempName, 0x00, L_tmpnam_s);

        tmpnam_s(tempName, L_tmpnam_s);

        // tmpnam_s() may return a file name that starts with a \ or an absolut path ...
        if ((strlen(tempName) > 0) && (tempName[0] == '\\'))
        {
            s_tempName = '.';
            s_tempName += tempName;
        }
        else
        {
            s_tempName = tempName;
        }
    }

    return Aws::String(s_tempName);
}
#else
Aws::String ComputeIdentityFilePath()
{
    static Aws::String tempFile(std::tmpnam(nullptr));
    return tempFile;
}
#endif

TEST(PersistentCognitoIdentityProvider_JsonImpl_Test, TestConstructorWhenNoFileIsAvailable)
{
    PersistentCognitoIdentityProvider_JsonFileImpl identityProvider("identityPoolId", "accountId", ComputeIdentityFilePath().c_str());
    ASSERT_FALSE(identityProvider.HasIdentityId());
    ASSERT_FALSE(identityProvider.HasLogins());
    ASSERT_EQ("identityPoolId", identityProvider.GetIdentityPoolId());
    ASSERT_EQ("accountId", identityProvider.GetAccountId());

    Aws::String filePath = ComputeIdentityFilePath();
    std::ifstream shouldNotExist(filePath.c_str());
    ASSERT_FALSE(shouldNotExist.good());
}

TEST(PersistentCognitoIdentityProvider_JsonImpl_Test, TestConstructorWhenFileIsAvaiable)
{
    JsonValue theIdentityPoolWeWant;
    theIdentityPoolWeWant.WithString("IdentityId", "TheIdentityWeWant");

    //this should test the legacy case.
    //the next test case will cover the current spec in detail.
    JsonValue logins;
    logins.WithString("TestLoginName", "TestLoginValue");
    theIdentityPoolWeWant.WithObject("Logins", logins);

    JsonValue someOtherIdentityPool;
    someOtherIdentityPool.WithString("IdentityId", "SomeOtherIdentity");

    JsonValue identityDoc;
    identityDoc.WithObject("IdentityPoolWeWant", theIdentityPoolWeWant);
    identityDoc.WithObject("SomeOtherIdentityPool", someOtherIdentityPool);

    Aws::String filePath = ComputeIdentityFilePath();
    std::ofstream identityFile(filePath.c_str());
    identityFile << identityDoc.WriteReadable();
    identityFile.flush();
    identityFile.close();

    PersistentCognitoIdentityProvider_JsonFileImpl identityProvider("IdentityPoolWeWant", "accountId", filePath.c_str());
    FileSystemUtils::RemoveFileIfExists(filePath.c_str());

    ASSERT_TRUE(identityProvider.HasIdentityId());
    ASSERT_EQ(theIdentityPoolWeWant.GetString("IdentityId"), identityProvider.GetIdentityId());
    ASSERT_TRUE(identityProvider.HasLogins());
    ASSERT_EQ(1u, identityProvider.GetLogins().size());
    ASSERT_EQ("TestLoginName", identityProvider.GetLogins().begin()->first);
    ASSERT_EQ("TestLoginValue", identityProvider.GetLogins().begin()->second.accessToken);
}

TEST(PersistentCognitoIdentityProvider_JsonImpl_Test, TestPersistance)
{
    JsonValue someOtherIdentityPool;
    someOtherIdentityPool.WithString("IdentityId", "SomeOtherIdentity");

    JsonValue identityDoc;
    identityDoc.WithObject("SomeOtherIdentityPool", someOtherIdentityPool);

    Aws::String filePath = ComputeIdentityFilePath();
    FileSystemUtils::RemoveFileIfExists(filePath.c_str());
    std::ofstream identityFile(filePath.c_str());
    identityFile << identityDoc.WriteReadable();
    identityFile.close();

    Aws::Map<Aws::String, LoginAccessTokens> loginsMap;
    LoginAccessTokens loginAccessTokens;
    loginAccessTokens.accessToken = "LoginValue";
    loginAccessTokens.longTermTokenExpiry = 1001;
    loginAccessTokens.longTermToken = "LongTermToken";
    loginsMap["LoginName"] = loginAccessTokens;

    //scope it to kill the cache and force it to reload from file.
    {
        PersistentCognitoIdentityProvider_JsonFileImpl identityProvider("IdentityPoolWeWant", "accountId", filePath.c_str());

        EXPECT_FALSE(identityProvider.HasIdentityId());
        EXPECT_FALSE(identityProvider.HasLogins());

        identityProvider.PersistIdentityId("IdentityWeWant");
        identityProvider.PersistLogins(loginsMap);
    }

    PersistentCognitoIdentityProvider_JsonFileImpl identityProvider("IdentityPoolWeWant", "accountId", filePath.c_str());

    EXPECT_EQ("IdentityWeWant", identityProvider.GetIdentityId());
    EXPECT_EQ("LoginName", identityProvider.GetLogins().begin()->first);
    EXPECT_EQ(loginAccessTokens.accessToken, identityProvider.GetLogins().begin()->second.accessToken);
    EXPECT_EQ(loginAccessTokens.longTermToken, identityProvider.GetLogins().begin()->second.longTermToken);
    EXPECT_EQ(loginAccessTokens.longTermTokenExpiry, identityProvider.GetLogins().begin()->second.longTermTokenExpiry);

    std::ifstream identityFileInput(filePath.c_str());
    JsonValue finalIdentityDoc(identityFileInput);
    identityFileInput.close();
    FileSystemUtils::RemoveFileIfExists(filePath.c_str());

    ASSERT_TRUE(finalIdentityDoc.ValueExists("SomeOtherIdentityPool"));
    ASSERT_TRUE(finalIdentityDoc.ValueExists("IdentityPoolWeWant"));
    JsonValue ourIdentityPool = finalIdentityDoc.GetObject("IdentityPoolWeWant");
    ASSERT_EQ("IdentityWeWant", ourIdentityPool.GetString("IdentityId"));
    ASSERT_EQ("LoginName", ourIdentityPool.GetObject("Logins").GetAllObjects().begin()->first);
    ASSERT_EQ(loginAccessTokens.accessToken, ourIdentityPool.GetObject("Logins").GetAllObjects().begin()->second.GetString("AccessToken"));
    ASSERT_EQ(loginAccessTokens.longTermToken, ourIdentityPool.GetObject("Logins").GetAllObjects().begin()->second.GetString("LongTermToken"));
    ASSERT_EQ(loginAccessTokens.longTermTokenExpiry, ourIdentityPool.GetObject("Logins").GetAllObjects().begin()->second.GetInt64("Expiry"));
}

#ifdef __clang__
#pragma clang diagnostic pop
#endif

<commit_msg>Revert "changed/fixed ComputeIdentityFilePath() again for MSVC 2013 (apparently tmpnam_s() may return a file name that starts with a \ or an absolut path ...)"<commit_after>/*
  * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License").
  * You may not use this file except in compliance with the License.
  * A copy of the License is located at
  *
  *  http://aws.amazon.com/apache2.0
  *
  * or in the "license" file accompanying this file. This file is distributed
  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  * express or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */

#include <aws/external/gtest.h>
#include <aws/testing/MemoryTesting.h>
#include <aws/identity-management/auth/PersistentCognitoIdentityProvider.h>
#include <aws/core/utils/FileSystemUtils.h>
#include <aws/core/utils/json/JsonSerializer.h>
#include <fstream>

//since MAC isn't posix compliant, it likes to complain about std::tmpnam. Also, it the std:: function is supposed
//to be different than the posix defined function.
//turn it off because we need it for this test and this isn't production code
//anyways.
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif

#ifdef _MSC_VER
#pragma warning(disable: 4996) // _CRT_SECURE_NO_WARNINGS
#endif

using namespace Aws::Auth;
using namespace Aws::Utils;
using namespace Aws::Utils::Json;

#ifdef _WIN32
Aws::String ComputeIdentityFilePath()
{
    static bool s_initialized = false;
    static char s_tempName[L_tmpnam];

    if(!s_initialized)
    {
        tmpnam_s(s_tempName, L_tmpnam);
        s_initialized = true;
    }

    return Aws::String(s_tempName);
}
#else
Aws::String ComputeIdentityFilePath()
{
    static Aws::String tempFile(std::tmpnam(nullptr));
    return tempFile;
}
#endif

TEST(PersistentCognitoIdentityProvider_JsonImpl_Test, TestConstructorWhenNoFileIsAvailable)
{
    PersistentCognitoIdentityProvider_JsonFileImpl identityProvider("identityPoolId", "accountId", ComputeIdentityFilePath().c_str());
    ASSERT_FALSE(identityProvider.HasIdentityId());
    ASSERT_FALSE(identityProvider.HasLogins());
    ASSERT_EQ("identityPoolId", identityProvider.GetIdentityPoolId());
    ASSERT_EQ("accountId", identityProvider.GetAccountId());

    Aws::String filePath = ComputeIdentityFilePath();
    std::ifstream shouldNotExist(filePath.c_str());
    ASSERT_FALSE(shouldNotExist.good());
}

TEST(PersistentCognitoIdentityProvider_JsonImpl_Test, TestConstructorWhenFileIsAvaiable)
{
    JsonValue theIdentityPoolWeWant;
    theIdentityPoolWeWant.WithString("IdentityId", "TheIdentityWeWant");

    //this should test the legacy case.
    //the next test case will cover the current spec in detail.
    JsonValue logins;
    logins.WithString("TestLoginName", "TestLoginValue");
    theIdentityPoolWeWant.WithObject("Logins", logins);

    JsonValue someOtherIdentityPool;
    someOtherIdentityPool.WithString("IdentityId", "SomeOtherIdentity");

    JsonValue identityDoc;
    identityDoc.WithObject("IdentityPoolWeWant", theIdentityPoolWeWant);
    identityDoc.WithObject("SomeOtherIdentityPool", someOtherIdentityPool);

    Aws::String filePath = ComputeIdentityFilePath();
    std::ofstream identityFile(filePath.c_str());
    identityFile << identityDoc.WriteReadable();
    identityFile.flush();
    identityFile.close();

    PersistentCognitoIdentityProvider_JsonFileImpl identityProvider("IdentityPoolWeWant", "accountId", filePath.c_str());
    FileSystemUtils::RemoveFileIfExists(filePath.c_str());

    ASSERT_TRUE(identityProvider.HasIdentityId());
    ASSERT_EQ(theIdentityPoolWeWant.GetString("IdentityId"), identityProvider.GetIdentityId());
    ASSERT_TRUE(identityProvider.HasLogins());
    ASSERT_EQ(1u, identityProvider.GetLogins().size());
    ASSERT_EQ("TestLoginName", identityProvider.GetLogins().begin()->first);
    ASSERT_EQ("TestLoginValue", identityProvider.GetLogins().begin()->second.accessToken);
}

TEST(PersistentCognitoIdentityProvider_JsonImpl_Test, TestPersistance)
{
    JsonValue someOtherIdentityPool;
    someOtherIdentityPool.WithString("IdentityId", "SomeOtherIdentity");

    JsonValue identityDoc;
    identityDoc.WithObject("SomeOtherIdentityPool", someOtherIdentityPool);

    Aws::String filePath = ComputeIdentityFilePath();
    FileSystemUtils::RemoveFileIfExists(filePath.c_str());
    std::ofstream identityFile(filePath.c_str());
    identityFile << identityDoc.WriteReadable();
    identityFile.close();

    Aws::Map<Aws::String, LoginAccessTokens> loginsMap;
    LoginAccessTokens loginAccessTokens;
    loginAccessTokens.accessToken = "LoginValue";
    loginAccessTokens.longTermTokenExpiry = 1001;
    loginAccessTokens.longTermToken = "LongTermToken";
    loginsMap["LoginName"] = loginAccessTokens;

    //scope it to kill the cache and force it to reload from file.
    {
        PersistentCognitoIdentityProvider_JsonFileImpl identityProvider("IdentityPoolWeWant", "accountId", filePath.c_str());

        EXPECT_FALSE(identityProvider.HasIdentityId());
        EXPECT_FALSE(identityProvider.HasLogins());

        identityProvider.PersistIdentityId("IdentityWeWant");
        identityProvider.PersistLogins(loginsMap);
    }

    PersistentCognitoIdentityProvider_JsonFileImpl identityProvider("IdentityPoolWeWant", "accountId", filePath.c_str());

    EXPECT_EQ("IdentityWeWant", identityProvider.GetIdentityId());
    EXPECT_EQ("LoginName", identityProvider.GetLogins().begin()->first);
    EXPECT_EQ(loginAccessTokens.accessToken, identityProvider.GetLogins().begin()->second.accessToken);
    EXPECT_EQ(loginAccessTokens.longTermToken, identityProvider.GetLogins().begin()->second.longTermToken);
    EXPECT_EQ(loginAccessTokens.longTermTokenExpiry, identityProvider.GetLogins().begin()->second.longTermTokenExpiry);

    std::ifstream identityFileInput(filePath.c_str());
    JsonValue finalIdentityDoc(identityFileInput);
    identityFileInput.close();
    FileSystemUtils::RemoveFileIfExists(filePath.c_str());

    ASSERT_TRUE(finalIdentityDoc.ValueExists("SomeOtherIdentityPool"));
    ASSERT_TRUE(finalIdentityDoc.ValueExists("IdentityPoolWeWant"));
    JsonValue ourIdentityPool = finalIdentityDoc.GetObject("IdentityPoolWeWant");
    ASSERT_EQ("IdentityWeWant", ourIdentityPool.GetString("IdentityId"));
    ASSERT_EQ("LoginName", ourIdentityPool.GetObject("Logins").GetAllObjects().begin()->first);
    ASSERT_EQ(loginAccessTokens.accessToken, ourIdentityPool.GetObject("Logins").GetAllObjects().begin()->second.GetString("AccessToken"));
    ASSERT_EQ(loginAccessTokens.longTermToken, ourIdentityPool.GetObject("Logins").GetAllObjects().begin()->second.GetString("LongTermToken"));
    ASSERT_EQ(loginAccessTokens.longTermTokenExpiry, ourIdentityPool.GetObject("Logins").GetAllObjects().begin()->second.GetInt64("Expiry"));
}

#ifdef __clang__
#pragma clang diagnostic pop
#endif

<|endoftext|>