<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License 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.
 *
 *=========================================================================*/
#ifndef itkSpectra1DImageFilter_hxx
#define itkSpectra1DImageFilter_hxx

#include "itkSpectra1DImageFilter.h"

#include "itkImageLinearConstIteratorWithIndex.h"
#include "itkImageLinearIteratorWithIndex.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageScanlineIterator.h"
#include "itkImageScanlineConstIterator.h"
#include "itkMetaDataObject.h"

#include "itkSpectra1DSupportWindowImageFilter.h"

namespace itk
{

template< typename TInputImage, typename TSupportWindowImage, typename TOutputImage >
Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >
::Spectra1DImageFilter()
{
  this->AddRequiredInputName( "SupportWindowImage" );
}

template< typename TInputImage, typename TSupportWindowImage, typename TOutputImage >
void
Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >
::GenerateOutputInformation()
{
  Superclass::GenerateOutputInformation();
  OutputImageType * output = this->GetOutput();
  const SupportWindowImageType * supportWindowImage = this->GetSupportWindowImage();

  output->SetSpacing( supportWindowImage->GetSpacing() );
  output->SetLargestPossibleRegion( supportWindowImage->GetLargestPossibleRegion() );

  const MetaDataDictionary & dict = supportWindowImage->GetMetaDataDictionary();
  FFT1DSizeType fft1DSize = 32;
  ExposeMetaData< FFT1DSizeType >( dict, "FFT1DSize", fft1DSize );
  // Divide by two for Hermitian symmetry. Divide by two for Welch's method
  // with 50% overlap
  const FFT1DSizeType spectraComponents = fft1DSize / 2 / 2 - 1;

  output->SetVectorLength( spectraComponents );
}

template< typename TInputImage, typename TSupportWindowImage, typename TOutputImage >
void
Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >
::BeforeThreadedGenerateData()
{
  const SupportWindowImageType * supportWindowImage = this->GetSupportWindowImage();
  const MetaDataDictionary & dict = supportWindowImage->GetMetaDataDictionary();
  FFT1DSizeType fft1DSize = 32;
  ExposeMetaData< FFT1DSizeType >( dict, "FFT1DSize", fft1DSize );
  const FFT1DSizeType spectraComponents = fft1DSize / 2 / 2 - 1;

  const ThreadIdType numberOfThreads = this->GetNumberOfThreads();
  this->m_PerThreadDataContainer.resize( numberOfThreads );
  for( ThreadIdType threadId = 0; threadId < numberOfThreads; ++threadId )
    {
    PerThreadData & perThreadData = this->m_PerThreadDataContainer[threadId];
    perThreadData.ComplexVector.set_size( fft1DSize / 2 );
    perThreadData.SpectraVector.resize( spectraComponents );
    perThreadData.LineImageRegionSize.Fill( 1 );
    perThreadData.LineImageRegionSize[0] = fft1DSize;
    }
}

template< typename TInputImage, typename TSupportWindowImage, typename TOutputImage >
void
Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >
::VerifyInputInformation()
{
}

template< typename TInputImage, typename TSupportWindowImage, typename TOutputImage >
void
Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >
::AddLineWindow( FFT1DSizeType length, LineWindowMapType & lineWindowMap )
{
  if( lineWindowMap.count( length ) == 1 )
    {
    return;
    }
  // Currently using a Hamming Window
  SpectraVectorType window( length );
  ScalarType sum = NumericTraits< ScalarType >::ZeroValue();
  for( FFT1DSizeType sample = 0; sample < length; ++sample )
    {
    window[sample] = 0.54 + 0.46 * std::cos( (Math::twopi * sample) / (length - 1) );
    sum += window[sample];
    }
  for( FFT1DSizeType sample = 0; sample < length; ++sample )
    {
    window[sample] /= sum;
    }
  lineWindowMap[length] = window;
}

template< typename TInputImage, typename TSupportWindowImage, typename TOutputImage >
void
Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >
::ComputeSpectra( const IndexType & lineIndex, ThreadIdType threadId, SpectraLineType & spectraLine )
{
  const InputImageType * input = this->GetInput();
  PerThreadData & perThreadData = this->m_PerThreadDataContainer[threadId];

  const FFT1DSizeType fftSize = static_cast< FFT1DSizeType >( perThreadData.ComplexVector.size() );

  const typename InputImageType::RegionType lineRegion( lineIndex, perThreadData.LineImageRegionSize );
  InputImageIteratorType inputIt( input, lineRegion );
  inputIt.GoToBegin();
  perThreadData.ComplexVector.fill( 0 );
  typename ComplexVectorType::iterator complexVectorIt = perThreadData.ComplexVector.begin();
  const typename ComplexVectorType::iterator complexVectorEnd = perThreadData.ComplexVector.end();
  typename SpectraVectorType::const_iterator windowIt = perThreadData.LineWindowMap[fftSize].begin();
  typename ComplexVectorType::const_iterator complexVectorConstIt = perThreadData.ComplexVector.begin();
  typename SpectraVectorType::iterator spectraVectorIt = perThreadData.SpectraVector.begin();
  const size_t highFreq = perThreadData.SpectraVector.size();
  for( size_t freq = 0; freq < highFreq; ++freq )
    {
    spectraVectorIt[freq] = 0.0f;
    }
  const double overlap = 0.5;
  IndexType segmentIndex( lineIndex );
  const double spectralScale = 1.0 / (fftSize * fftSize);
  for( unsigned int segment = 0; segment < 3; ++segment )
    {
    segmentIndex[0] = static_cast< IndexValueType >( lineIndex[0] + segment * perThreadData.LineImageRegionSize[0] * overlap / 3.0 );
    inputIt.SetIndex( segmentIndex );
    complexVectorIt = perThreadData.ComplexVector.begin();
    windowIt = perThreadData.LineWindowMap[fftSize].begin();
    while( complexVectorIt != complexVectorEnd )
      {
      *complexVectorIt = inputIt.Value() * *windowIt;
      ++inputIt;
      ++complexVectorIt;
      ++windowIt;
      }
    FFT1DType fft1D( fftSize );
    fft1D.bwd_transform( perThreadData.ComplexVector );
    complexVectorConstIt = perThreadData.ComplexVector.begin();
    spectraVectorIt = perThreadData.SpectraVector.begin();
    // drop DC component
    ++complexVectorConstIt;
    for( size_t freq = 0; freq < highFreq; ++freq )
      {
      spectraVectorIt[freq] += std::real(*complexVectorConstIt * std::conj(*complexVectorConstIt)) / 3.0 * spectralScale;
      ++complexVectorConstIt;
      }
    }

  spectraLine.first = lineIndex;
  spectraLine.second = perThreadData.SpectraVector;
}

template< typename TInputImage, typename TSupportWindowImage, typename TOutputImage >
void
Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >
::ThreadedGenerateData( const OutputImageRegionType & outputRegionForThread, ThreadIdType threadId )
{
  OutputImageType * output = this->GetOutput();
  const SupportWindowImageType * supportWindowImage = this->GetSupportWindowImage();

  typedef ImageLinearIteratorWithIndex< OutputImageType > OutputIteratorType;
  OutputIteratorType outputIt( output, outputRegionForThread );
  outputIt.SetDirection( 1 );

  const MetaDataDictionary & dict = supportWindowImage->GetMetaDataDictionary();
  PerThreadData & perThreadData = this->m_PerThreadDataContainer[threadId];
  this->AddLineWindow( perThreadData.ComplexVector.size(), perThreadData.LineWindowMap );

  SpectraLinesContainerType spectraLines;

  typedef ImageLinearConstIteratorWithIndex< SupportWindowImageType > SupportWindowIteratorType;
  SupportWindowIteratorType supportWindowIt( supportWindowImage, outputRegionForThread );
  supportWindowIt.SetDirection( 1 );

  SpectraLineType spectraLine;
  for( outputIt.GoToBegin(), supportWindowIt.GoToBegin();
       !outputIt.IsAtEnd();
       outputIt.NextLine(), supportWindowIt.NextLine() )
    {
    spectraLines.clear();
    while( ! outputIt.IsAtEndOfLine() )
      {
      // Compute the per line spectra.
      const SupportWindowType & supportWindow = supportWindowIt.Value();
      if( spectraLines.size() == 0 ) // first window in this lateral direction
        {
        const typename SupportWindowType::const_iterator windowLineEnd = supportWindow.end();
        for( typename SupportWindowType::const_iterator windowLine = supportWindow.begin();
             windowLine != windowLineEnd;
             ++windowLine )
          {
          const IndexType & lineIndex = *windowLine;
          this->ComputeSpectra( lineIndex, threadId, spectraLine );
          spectraLines.push_back( spectraLine );
          }
        }
      else // subsequent window along a line
        {
        const IndexValueType desiredFirstLine = supportWindow.front()[1];
        while( spectraLines.front().first[1] < desiredFirstLine )
          {
          spectraLines.pop_front();
          }
        const typename SupportWindowType::const_iterator windowLineEnd = supportWindow.end();
        typename SpectraLinesContainerType::iterator spectraLinesIt = spectraLines.begin();
        const typename SpectraLinesContainerType::iterator spectraLinesEnd = spectraLines.end();
        for( typename SupportWindowType::const_iterator windowLine = supportWindow.begin();
             windowLine != windowLineEnd;
             ++windowLine )
          {
          const IndexType & lineIndex = *windowLine;
          if( spectraLinesIt == spectraLinesEnd ) // past the end of the previously processed lines
            {
            this->ComputeSpectra( lineIndex, threadId, spectraLine );
            spectraLines.push_back( spectraLine );
            }
          else if( lineIndex[1] == (spectraLinesIt->first)[1] ) // one of the same lines that was previously computed
            {
            if( lineIndex[0] != (spectraLinesIt->first)[0] )
              {
              this->ComputeSpectra( lineIndex, threadId, spectraLine );
              *spectraLinesIt = spectraLine;
              }
            ++spectraLinesIt;
            }
          else
            {
            itkExceptionMacro( "Unexpected line" );
            }
          }
        }

      // lateral window and sum
      const size_t spectraLinesCount = spectraLines.size();
      this->AddLineWindow( spectraLinesCount, perThreadData.LineWindowMap );
      typename OutputImageType::PixelType outputPixel;
      const FFT1DSizeType spectralComponents = perThreadData.SpectraVector.size();
      outputPixel.SetSize( spectralComponents );
      outputPixel.Fill( NumericTraits< ScalarType >::ZeroValue() );
      typename SpectraVectorType::const_iterator windowIt = perThreadData.LineWindowMap[spectraLinesCount].begin();
      SpectraLinesContainerType::iterator linesIt = spectraLines.begin();
      for( size_t line = 0; line < spectraLinesCount; ++line )
        {
        typename SpectraVectorType::const_iterator spectraIt = linesIt->second.begin();
        for( FFT1DSizeType sample = 0; sample < spectralComponents; ++sample )
          {
          outputPixel[sample] += *windowIt * *spectraIt;
          ++spectraIt;
          }
        ++windowIt;
        ++linesIt;
        }
      outputIt.Set( outputPixel );

      ++outputIt;
      ++supportWindowIt;
      }
    }

  const OutputImageType * referenceSpectra = this->GetReferenceSpectraImage();
  if( referenceSpectra != ITK_NULLPTR )
    {
    typedef ImageScanlineConstIterator< OutputImageType > ReferenceSpectraIteratorType;
    ReferenceSpectraIteratorType referenceSpectraIt( referenceSpectra, outputRegionForThread );

    typedef ImageScanlineIterator< OutputImageType >      PopulatedOutputIteratorType;
    PopulatedOutputIteratorType populatedOutputIt( output, outputRegionForThread );

    const unsigned int numberOfComponents = referenceSpectra->GetNumberOfComponentsPerPixel();
    if( numberOfComponents != output->GetNumberOfComponentsPerPixel() )
      {
      itkExceptionMacro( "ReferenceSpectraImage has " << numberOfComponents << " while the output image has " << output->GetNumberOfComponentsPerPixel() << " components" );
      }

    for( referenceSpectraIt.GoToBegin(), populatedOutputIt.GoToBegin(); !populatedOutputIt.IsAtEnd();)
      {
      while( !populatedOutputIt.IsAtEndOfLine() )
        {
        typedef typename OutputImageType::PixelType PixelType;
        PixelType outputPixel = populatedOutputIt.Get();
        const PixelType referencePixel = referenceSpectraIt.Get();
        for( unsigned int component = 0; component < numberOfComponents; ++component )
          {
          if( Math::FloatAlmostEqual( referencePixel[component], NumericTraits< typename PixelType::ValueType >::Zero ) )
            {
            outputPixel[component] = NumericTraits< typename PixelType::ValueType >::Zero;
            }
          else
            {
            outputPixel[component] /= referencePixel[component];
            }
          }
        populatedOutputIt.Set( outputPixel );

        ++populatedOutputIt;
        ++referenceSpectraIt;
        }
      populatedOutputIt.NextLine();
      referenceSpectraIt.NextLine();
      }
    }
}

} // end namespace itk

#endif
<commit_msg>BUG: Missing typename for compliance on Linux.<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License 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.
 *
 *=========================================================================*/
#ifndef itkSpectra1DImageFilter_hxx
#define itkSpectra1DImageFilter_hxx

#include "itkSpectra1DImageFilter.h"

#include "itkImageLinearConstIteratorWithIndex.h"
#include "itkImageLinearIteratorWithIndex.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageScanlineIterator.h"
#include "itkImageScanlineConstIterator.h"
#include "itkMetaDataObject.h"

#include "itkSpectra1DSupportWindowImageFilter.h"

namespace itk
{

template< typename TInputImage, typename TSupportWindowImage, typename TOutputImage >
Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >
::Spectra1DImageFilter()
{
  this->AddRequiredInputName( "SupportWindowImage" );
}

template< typename TInputImage, typename TSupportWindowImage, typename TOutputImage >
void
Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >
::GenerateOutputInformation()
{
  Superclass::GenerateOutputInformation();
  OutputImageType * output = this->GetOutput();
  const SupportWindowImageType * supportWindowImage = this->GetSupportWindowImage();

  output->SetSpacing( supportWindowImage->GetSpacing() );
  output->SetLargestPossibleRegion( supportWindowImage->GetLargestPossibleRegion() );

  const MetaDataDictionary & dict = supportWindowImage->GetMetaDataDictionary();
  FFT1DSizeType fft1DSize = 32;
  ExposeMetaData< FFT1DSizeType >( dict, "FFT1DSize", fft1DSize );
  // Divide by two for Hermitian symmetry. Divide by two for Welch's method
  // with 50% overlap
  const FFT1DSizeType spectraComponents = fft1DSize / 2 / 2 - 1;

  output->SetVectorLength( spectraComponents );
}

template< typename TInputImage, typename TSupportWindowImage, typename TOutputImage >
void
Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >
::BeforeThreadedGenerateData()
{
  const SupportWindowImageType * supportWindowImage = this->GetSupportWindowImage();
  const MetaDataDictionary & dict = supportWindowImage->GetMetaDataDictionary();
  FFT1DSizeType fft1DSize = 32;
  ExposeMetaData< FFT1DSizeType >( dict, "FFT1DSize", fft1DSize );
  const FFT1DSizeType spectraComponents = fft1DSize / 2 / 2 - 1;

  const ThreadIdType numberOfThreads = this->GetNumberOfThreads();
  this->m_PerThreadDataContainer.resize( numberOfThreads );
  for( ThreadIdType threadId = 0; threadId < numberOfThreads; ++threadId )
    {
    PerThreadData & perThreadData = this->m_PerThreadDataContainer[threadId];
    perThreadData.ComplexVector.set_size( fft1DSize / 2 );
    perThreadData.SpectraVector.resize( spectraComponents );
    perThreadData.LineImageRegionSize.Fill( 1 );
    perThreadData.LineImageRegionSize[0] = fft1DSize;
    }
}

template< typename TInputImage, typename TSupportWindowImage, typename TOutputImage >
void
Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >
::VerifyInputInformation()
{
}

template< typename TInputImage, typename TSupportWindowImage, typename TOutputImage >
void
Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >
::AddLineWindow( FFT1DSizeType length, LineWindowMapType & lineWindowMap )
{
  if( lineWindowMap.count( length ) == 1 )
    {
    return;
    }
  // Currently using a Hamming Window
  SpectraVectorType window( length );
  ScalarType sum = NumericTraits< ScalarType >::ZeroValue();
  for( FFT1DSizeType sample = 0; sample < length; ++sample )
    {
    window[sample] = 0.54 + 0.46 * std::cos( (Math::twopi * sample) / (length - 1) );
    sum += window[sample];
    }
  for( FFT1DSizeType sample = 0; sample < length; ++sample )
    {
    window[sample] /= sum;
    }
  lineWindowMap[length] = window;
}

template< typename TInputImage, typename TSupportWindowImage, typename TOutputImage >
void
Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >
::ComputeSpectra( const IndexType & lineIndex, ThreadIdType threadId, SpectraLineType & spectraLine )
{
  const InputImageType * input = this->GetInput();
  PerThreadData & perThreadData = this->m_PerThreadDataContainer[threadId];

  const FFT1DSizeType fftSize = static_cast< FFT1DSizeType >( perThreadData.ComplexVector.size() );

  const typename InputImageType::RegionType lineRegion( lineIndex, perThreadData.LineImageRegionSize );
  InputImageIteratorType inputIt( input, lineRegion );
  inputIt.GoToBegin();
  perThreadData.ComplexVector.fill( 0 );
  typename ComplexVectorType::iterator complexVectorIt = perThreadData.ComplexVector.begin();
  const typename ComplexVectorType::iterator complexVectorEnd = perThreadData.ComplexVector.end();
  typename SpectraVectorType::const_iterator windowIt = perThreadData.LineWindowMap[fftSize].begin();
  typename ComplexVectorType::const_iterator complexVectorConstIt = perThreadData.ComplexVector.begin();
  typename SpectraVectorType::iterator spectraVectorIt = perThreadData.SpectraVector.begin();
  const size_t highFreq = perThreadData.SpectraVector.size();
  for( size_t freq = 0; freq < highFreq; ++freq )
    {
    spectraVectorIt[freq] = 0.0f;
    }
  const double overlap = 0.5;
  IndexType segmentIndex( lineIndex );
  const double spectralScale = 1.0 / (fftSize * fftSize);
  for( unsigned int segment = 0; segment < 3; ++segment )
    {
    segmentIndex[0] = static_cast< IndexValueType >( lineIndex[0] + segment * perThreadData.LineImageRegionSize[0] * overlap / 3.0 );
    inputIt.SetIndex( segmentIndex );
    complexVectorIt = perThreadData.ComplexVector.begin();
    windowIt = perThreadData.LineWindowMap[fftSize].begin();
    while( complexVectorIt != complexVectorEnd )
      {
      *complexVectorIt = inputIt.Value() * *windowIt;
      ++inputIt;
      ++complexVectorIt;
      ++windowIt;
      }
    FFT1DType fft1D( fftSize );
    fft1D.bwd_transform( perThreadData.ComplexVector );
    complexVectorConstIt = perThreadData.ComplexVector.begin();
    spectraVectorIt = perThreadData.SpectraVector.begin();
    // drop DC component
    ++complexVectorConstIt;
    for( size_t freq = 0; freq < highFreq; ++freq )
      {
      spectraVectorIt[freq] += std::real(*complexVectorConstIt * std::conj(*complexVectorConstIt)) / 3.0 * spectralScale;
      ++complexVectorConstIt;
      }
    }

  spectraLine.first = lineIndex;
  spectraLine.second = perThreadData.SpectraVector;
}

template< typename TInputImage, typename TSupportWindowImage, typename TOutputImage >
void
Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >
::ThreadedGenerateData( const OutputImageRegionType & outputRegionForThread, ThreadIdType threadId )
{
  OutputImageType * output = this->GetOutput();
  const SupportWindowImageType * supportWindowImage = this->GetSupportWindowImage();

  typedef ImageLinearIteratorWithIndex< OutputImageType > OutputIteratorType;
  OutputIteratorType outputIt( output, outputRegionForThread );
  outputIt.SetDirection( 1 );

  const MetaDataDictionary & dict = supportWindowImage->GetMetaDataDictionary();
  PerThreadData & perThreadData = this->m_PerThreadDataContainer[threadId];
  this->AddLineWindow( perThreadData.ComplexVector.size(), perThreadData.LineWindowMap );

  SpectraLinesContainerType spectraLines;

  typedef ImageLinearConstIteratorWithIndex< SupportWindowImageType > SupportWindowIteratorType;
  SupportWindowIteratorType supportWindowIt( supportWindowImage, outputRegionForThread );
  supportWindowIt.SetDirection( 1 );

  SpectraLineType spectraLine;
  for( outputIt.GoToBegin(), supportWindowIt.GoToBegin();
       !outputIt.IsAtEnd();
       outputIt.NextLine(), supportWindowIt.NextLine() )
    {
    spectraLines.clear();
    while( ! outputIt.IsAtEndOfLine() )
      {
      // Compute the per line spectra.
      const SupportWindowType & supportWindow = supportWindowIt.Value();
      if( spectraLines.size() == 0 ) // first window in this lateral direction
        {
        const typename SupportWindowType::const_iterator windowLineEnd = supportWindow.end();
        for( typename SupportWindowType::const_iterator windowLine = supportWindow.begin();
             windowLine != windowLineEnd;
             ++windowLine )
          {
          const IndexType & lineIndex = *windowLine;
          this->ComputeSpectra( lineIndex, threadId, spectraLine );
          spectraLines.push_back( spectraLine );
          }
        }
      else // subsequent window along a line
        {
        const IndexValueType desiredFirstLine = supportWindow.front()[1];
        while( spectraLines.front().first[1] < desiredFirstLine )
          {
          spectraLines.pop_front();
          }
        const typename SupportWindowType::const_iterator windowLineEnd = supportWindow.end();
        typename SpectraLinesContainerType::iterator spectraLinesIt = spectraLines.begin();
        const typename SpectraLinesContainerType::iterator spectraLinesEnd = spectraLines.end();
        for( typename SupportWindowType::const_iterator windowLine = supportWindow.begin();
             windowLine != windowLineEnd;
             ++windowLine )
          {
          const IndexType & lineIndex = *windowLine;
          if( spectraLinesIt == spectraLinesEnd ) // past the end of the previously processed lines
            {
            this->ComputeSpectra( lineIndex, threadId, spectraLine );
            spectraLines.push_back( spectraLine );
            }
          else if( lineIndex[1] == (spectraLinesIt->first)[1] ) // one of the same lines that was previously computed
            {
            if( lineIndex[0] != (spectraLinesIt->first)[0] )
              {
              this->ComputeSpectra( lineIndex, threadId, spectraLine );
              *spectraLinesIt = spectraLine;
              }
            ++spectraLinesIt;
            }
          else
            {
            itkExceptionMacro( "Unexpected line" );
            }
          }
        }

      // lateral window and sum
      const size_t spectraLinesCount = spectraLines.size();
      this->AddLineWindow( spectraLinesCount, perThreadData.LineWindowMap );
      typename OutputImageType::PixelType outputPixel;
      const FFT1DSizeType spectralComponents = perThreadData.SpectraVector.size();
      outputPixel.SetSize( spectralComponents );
      outputPixel.Fill( NumericTraits< ScalarType >::ZeroValue() );
      typename SpectraVectorType::const_iterator windowIt = perThreadData.LineWindowMap[spectraLinesCount].begin();
      typename SpectraLinesContainerType::iterator linesIt = spectraLines.begin();
      for( size_t line = 0; line < spectraLinesCount; ++line )
        {
        typename SpectraVectorType::const_iterator spectraIt = linesIt->second.begin();
        for( FFT1DSizeType sample = 0; sample < spectralComponents; ++sample )
          {
          outputPixel[sample] += *windowIt * *spectraIt;
          ++spectraIt;
          }
        ++windowIt;
        ++linesIt;
        }
      outputIt.Set( outputPixel );

      ++outputIt;
      ++supportWindowIt;
      }
    }

  const OutputImageType * referenceSpectra = this->GetReferenceSpectraImage();
  if( referenceSpectra != ITK_NULLPTR )
    {
    typedef ImageScanlineConstIterator< OutputImageType > ReferenceSpectraIteratorType;
    ReferenceSpectraIteratorType referenceSpectraIt( referenceSpectra, outputRegionForThread );

    typedef ImageScanlineIterator< OutputImageType >      PopulatedOutputIteratorType;
    PopulatedOutputIteratorType populatedOutputIt( output, outputRegionForThread );

    const unsigned int numberOfComponents = referenceSpectra->GetNumberOfComponentsPerPixel();
    if( numberOfComponents != output->GetNumberOfComponentsPerPixel() )
      {
      itkExceptionMacro( "ReferenceSpectraImage has " << numberOfComponents << " while the output image has " << output->GetNumberOfComponentsPerPixel() << " components" );
      }

    for( referenceSpectraIt.GoToBegin(), populatedOutputIt.GoToBegin(); !populatedOutputIt.IsAtEnd();)
      {
      while( !populatedOutputIt.IsAtEndOfLine() )
        {
        typedef typename OutputImageType::PixelType PixelType;
        PixelType outputPixel = populatedOutputIt.Get();
        const PixelType referencePixel = referenceSpectraIt.Get();
        for( unsigned int component = 0; component < numberOfComponents; ++component )
          {
          if( Math::FloatAlmostEqual( referencePixel[component], NumericTraits< typename PixelType::ValueType >::Zero ) )
            {
            outputPixel[component] = NumericTraits< typename PixelType::ValueType >::Zero;
            }
          else
            {
            outputPixel[component] /= referencePixel[component];
            }
          }
        populatedOutputIt.Set( outputPixel );

        ++populatedOutputIt;
        ++referenceSpectraIt;
        }
      populatedOutputIt.NextLine();
      referenceSpectraIt.NextLine();
      }
    }
}

} // end namespace itk

#endif
<|endoftext|>


<commit_before>template <typename T1, std::size_t N, template <class, std::size_t> class T2, typename T3>
optimise_result<T1, N> optimise(
    const T2<T1, N>& problem,
    const T3& optimiser,
    std::vector<std::array<T1, N>> initial_parameters);

//
// Implementation
//

template <typename T1, std::size_t N, template <class, std::size_t> class T2, typename T3>
optimise_result<T1, N> optimise(
    const T2<T1, N>& problem,
    const T3& optimiser,
    std::vector<std::array<T1, N>> initial_parameters) {
  static_assert(std::is_floating_point<T1>::value, "");
  static_assert(N > 0, "");
  static_assert(std::is_base_of<mant::problem<T1, N>, T2<T1, N>>::value, "");
  // static_assert(std::is_base_of<mant::optimiser<T1, N, T2>, T3<T1, N, T2<T1, N>>>::value, "");

  assert(initial_parameters.size() > 0);

  // Maps the parameter's bounds from [*problem.lower_bounds*, *problem.upper_bounds*] to [0, 1] and places all active
  // dimensions (in-order) upfront.
  for (auto& parameter : initial_parameters) {
    for (std::size_t n = 0; n < optimiser.active_dimensions.size(); ++n) {
      parameter.at(n) = (
          parameter.at(optimiser.active_dimensions.at(n)) -
          problem.lower_bounds.at(n)
        ) / (problem.upper_bounds.at(n) - problem.lower_bounds.at(n));
    }
  }

  mant::problem<T1, N> mapped_problem;
  mapped_problem.objective_function = [&problem, &optimiser](const auto& parameter) {
    std::array<T1, N> mapped_parameter = problem.lower_bounds;
    for (std::size_t n = optimiser.active_dimensions.size(); n > 0; --n) {
      mapped_parameter.at(optimiser.active_dimensions.at(n - 1)) =
        problem.lower_bounds.at(n - 1) +
        parameter.at(n - 1) * (
          problem.upper_bounds.at(n - 1) - problem.lower_bounds.at(n - 1)
        );
    }

    return problem.objective_function(mapped_parameter);
  };

  auto&& result = optimiser.optimisation_function(mapped_problem, initial_parameters);

  // Maps the parameter's bounds back from [0, 1] to [*lower_bounds*, *upper_bounds*], permutes the parameter to match
  // the active dimensions.
  for (std::size_t n = optimiser.active_dimensions.size(); n > 0; --n) {
    result.best_parameter.at(optimiser.active_dimensions.at(n - 1)) =
      problem.lower_bounds.at(n - 1) +
      result.best_parameter.at(n - 1) * (
        problem.upper_bounds.at(n - 1) - problem.lower_bounds.at(n - 1)
      );
  }

  return result;
}

//
// Unit tests
//

#if defined(MANTELLA_BUILD_TESTS)
TEST_CASE("optimise", "[optimise]") {
  mant::sphere_function<double, 2> problem;
  problem.lower_bounds = {-5.0, -5.0};
  problem.upper_bounds = {5.0, 5.0};

  mant::hooke_jeeves_algorithm<double, 2, mant::problem> optimiser;
  optimiser.acceptable_objective_value = 1e-12;

  const auto&& result = mant::optimise(problem, optimiser, {{-3.2, 4.1}});
  CHECK((result.best_parameter == std::array<double, 2>({5.245208729576234e-07, 3.3378601038691613e-07})));
  CHECK(result.best_objective_value == Approx(5.57065506021764692e-13));
  CHECK(result.number_of_evaluations == 40);
}
#endif
<commit_msg>feature: Added optimise overloads (#267)<commit_after>template <typename T1, std::size_t N, template <class, std::size_t> class T2, typename T3>
optimise_result<T1, N> optimise(
    const T2<T1, N>& problem,
    const T3& optimiser,
    std::vector<std::array<T1, N>> initial_parameters);

template <typename T1, std::size_t N, template <class, std::size_t> class T2, typename T3>
optimise_result<T1, N> optimise(
    const T2<T1, N>& problem,
    const T3& optimiser);

template <typename T1, std::size_t N, template <class, std::size_t> class T2, typename T3>
optimise_result<T1, N> optimise(
    const T2<T1, N>& problem);
//
// Implementation
//

template <typename T1, std::size_t N, template <class, std::size_t> class T2, typename T3>
optimise_result<T1, N> optimise(
    const T2<T1, N>& problem,
    const T3& optimiser,
    std::vector<std::array<T1, N>> initial_parameters) {
  static_assert(std::is_floating_point<T1>::value, "");
  static_assert(N > 0, "");
  static_assert(std::is_base_of<mant::problem<T1, N>, T2<T1, N>>::value, "");
  // static_assert(std::is_base_of<mant::optimiser<T1, N, T2>, T3<T1, N, T2<T1, N>>>::value, "");

  assert(initial_parameters.size() > 0);

  // Maps the parameter's bounds from [*problem.lower_bounds*, *problem.upper_bounds*] to [0, 1] and places all active
  // dimensions (in-order) upfront.
  for (auto& parameter : initial_parameters) {
    for (std::size_t n = 0; n < optimiser.active_dimensions.size(); ++n) {
      parameter.at(n) = (
          parameter.at(optimiser.active_dimensions.at(n)) -
          problem.lower_bounds.at(n)
        ) / (problem.upper_bounds.at(n) - problem.lower_bounds.at(n));
    }
  }

  mant::problem<T1, N> mapped_problem;
  mapped_problem.objective_function = [&problem, &optimiser](const auto& parameter) {
    std::array<T1, N> mapped_parameter = problem.lower_bounds;
    for (std::size_t n = optimiser.active_dimensions.size(); n > 0; --n) {
      mapped_parameter.at(optimiser.active_dimensions.at(n - 1)) =
        problem.lower_bounds.at(n - 1) +
        parameter.at(n - 1) * (
          problem.upper_bounds.at(n - 1) - problem.lower_bounds.at(n - 1)
        );
    }

    return problem.objective_function(mapped_parameter);
  };

  auto&& result = optimiser.optimisation_function(mapped_problem, initial_parameters);

  // Maps the parameter's bounds back from [0, 1] to [*lower_bounds*, *upper_bounds*], permutes the parameter to match
  // the active dimensions.
  for (std::size_t n = optimiser.active_dimensions.size(); n > 0; --n) {
    result.best_parameter.at(optimiser.active_dimensions.at(n - 1)) =
      problem.lower_bounds.at(n - 1) +
      result.best_parameter.at(n - 1) * (
        problem.upper_bounds.at(n - 1) - problem.lower_bounds.at(n - 1)
      );
  }

  return result;
}

template <typename T1, std::size_t N, template <class, std::size_t> class T2, typename T3>
optimise_result<T1, N> optimise(
    const T2<T1, N>& problem,
    const T3& optimiser) {
  std::vector<std::array<T1, N>> initial_parameters(40);
  for (auto& parameter : initial_parameters) {
    std::generate(
      parameter.begin(), std::next(parameter.begin(), optimiser.active_dimensions.size()),
      std::bind(
        std::uniform_real_distribution<T1>(0.0, 1.0),
        std::ref(random_number_generator())));
  }

  return optimise(problem, optimiser, initial_parameters);
}

template <typename T1, std::size_t N, template <class, std::size_t> class T2>
optimise_result<T1, N> optimise(
    const T2<T1, N>& problem) {
  return optimise(problem, hooke_jeeves_algorithm<T1, N, mant::problem>());
}

//
// Unit tests
//

#if defined(MANTELLA_BUILD_TESTS)
TEST_CASE("optimise", "[optimise]") {
  mant::sphere_function<double, 2> problem;
  problem.lower_bounds = {-5.0, -5.0};
  problem.upper_bounds = {5.0, 5.0};

  mant::hooke_jeeves_algorithm<double, 2, mant::problem> optimiser;
  optimiser.acceptable_objective_value = 1e-12;

  const auto&& result = mant::optimise(problem, optimiser, {{-3.2, 4.1}});
  CHECK((result.best_parameter == std::array<double, 2>({5.245208729576234e-07, 3.3378601038691613e-07})));
  CHECK(result.best_objective_value == Approx(5.57065506021764692e-13));
  CHECK(result.number_of_evaluations == 40);

  CHECK_NOTHROW(mant::optimise(problem, optimiser));
  CHECK_NOTHROW(mant::optimise(problem));
}
#endif
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_GEOMETRY_TO_PATH_HPP
#define MAPNIK_GEOMETRY_TO_PATH_HPP

#include <mapnik/geometry.hpp>
#include <mapnik/path.hpp>

namespace mapnik { namespace geometry { namespace detail {

//template <typename Transformer>
struct geometry_to_path
{
    geometry_to_path(path_type & p)
        : p_(p) {}

    template <typename T>
    void operator() (geometry<T> const& geom) const
    {
        mapnik::util::apply_visitor(*this, geom);
    }

    void operator() (geometry_empty const&) const
    {
        // no-op
    }
    // point
    template <typename T>
    void operator() (point<T> const& pt) const
    {
        //point pt_new;
        //Transformer::apply(pt, pt_new);
        p_.move_to(pt.x, pt.y);
    }

    // line_string
    template <typename T>
    void operator() (line_string<T> const& line) const
    {
        bool first = true;
        for (auto const& pt : line)
        {
            //point pt_new;
            //Transformer::apply(pt, pt_new);
            if (first) { p_.move_to(pt.x, pt.y); first=false;}
            else p_.line_to(pt.x, pt.y);
        }
    }

    // polygon
    template <typename T>
    void operator() (polygon<T> const& poly) const
    {
        // exterior
        bool first = true;
        for (auto const& pt : poly.exterior_ring)
        {
            //point pt_new;
            //Transformer::apply(pt, pt_new);
            if (first) { p_.move_to(pt.x, pt.y); first=false;}
            else p_.line_to(pt.x, pt.y);
        }
        // interior
        for (auto const& ring : poly.interior_rings)
        {
            first = true;
            for (auto const& pt : ring)
            {
                //point pt_new;
                //Transformer::apply(pt, pt_new);
                if (first) { p_.move_to(pt.x, pt.y); first=false;}
                else p_.line_to(pt.x, pt.y);
            }
        }
    }

    // multi point
    template <typename T>
    void operator() (multi_point<T> const& multi_pt) const
    {
        for (auto const& pt : multi_pt)
        {
            (*this)(pt);
        }
    }
    // multi_line_string
    template <typename T>
    void operator() (multi_line_string<T> const& multi_line) const
    {
        for (auto const& line : multi_line)
        {
            (*this)(line);
        }
    }

    // multi_polygon
    template <typename T>
    void operator() (multi_polygon<T> const& multi_poly) const
    {
        for (auto const& poly : multi_poly)
        {
            (*this)(poly);
        }
    }

    template <typename T>
    void operator() (geometry_collection<T> const& collection) const
    {
        for (auto const& geom :  collection)
        {
            (*this)(geom);
        }
    }

    path_type & p_;

};
} // ns detail

template <typename T>
void to_path(T const& geom, path_type & p)
{
    detail::geometry_to_path func(p);
    func(geom);
}

}}

#endif // MAPNIK_GEOMETRY_TO_PATH_HPP
<commit_msg>close polygon paths<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_GEOMETRY_TO_PATH_HPP
#define MAPNIK_GEOMETRY_TO_PATH_HPP

#include <mapnik/geometry.hpp>
#include <mapnik/path.hpp>

namespace mapnik { namespace geometry { namespace detail {

//template <typename Transformer>
struct geometry_to_path
{
    geometry_to_path(path_type & p)
        : p_(p) {}

    template <typename T>
    void operator() (geometry<T> const& geom) const
    {
        mapnik::util::apply_visitor(*this, geom);
    }

    void operator() (geometry_empty const&) const
    {
        // no-op
    }
    // point
    template <typename T>
    void operator() (point<T> const& pt) const
    {
        //point pt_new;
        //Transformer::apply(pt, pt_new);
        p_.move_to(pt.x, pt.y);
    }

    // line_string
    template <typename T>
    void operator() (line_string<T> const& line) const
    {
        bool first = true;
        for (auto const& pt : line)
        {
            //point pt_new;
            //Transformer::apply(pt, pt_new);
            if (first) { p_.move_to(pt.x, pt.y); first=false;}
            else p_.line_to(pt.x, pt.y);
        }
    }

    // polygon
    template <typename T>
    void operator() (polygon<T> const& poly) const
    {
        // exterior
        bool first = true;
        for (auto const& pt : poly.exterior_ring)
        {
            //point pt_new;
            //Transformer::apply(pt, pt_new);
            if (first) { p_.move_to(pt.x, pt.y); first=false;}
            else p_.line_to(pt.x, pt.y);
        }
        p_.close_path();
        // interior
        for (auto const& ring : poly.interior_rings)
        {
            first = true;
            for (auto const& pt : ring)
            {
                //point pt_new;
                //Transformer::apply(pt, pt_new);
                if (first) { p_.move_to(pt.x, pt.y); first=false;}
                else p_.line_to(pt.x, pt.y);
            }
            p_.close_path();
        }
    }

    // multi point
    template <typename T>
    void operator() (multi_point<T> const& multi_pt) const
    {
        for (auto const& pt : multi_pt)
        {
            (*this)(pt);
        }
    }
    // multi_line_string
    template <typename T>
    void operator() (multi_line_string<T> const& multi_line) const
    {
        for (auto const& line : multi_line)
        {
            (*this)(line);
        }
    }

    // multi_polygon
    template <typename T>
    void operator() (multi_polygon<T> const& multi_poly) const
    {
        for (auto const& poly : multi_poly)
        {
            (*this)(poly);
        }
    }

    template <typename T>
    void operator() (geometry_collection<T> const& collection) const
    {
        for (auto const& geom :  collection)
        {
            (*this)(geom);
        }
    }

    path_type & p_;

};
} // ns detail

template <typename T>
void to_path(T const& geom, path_type & p)
{
    detail::geometry_to_path func(p);
    func(geom);
}

}}

#endif // MAPNIK_GEOMETRY_TO_PATH_HPP
<|endoftext|>


<commit_before>#ifndef PICOLIB_SOCKET_IMPL_H_
#define PICOLIB_SOCKET_IMPL_H_

#include <sys/un.h>

namespace Pico {

    namespace Network {

        template <AddressType>
        struct Address;

        template <>
        struct Address<AddressType::UNIX_ABSTRACT>
        {
            char *path;
        };

        using UnixAbstractAddress   = Address<AddressType::UNIX_ABSTRACT>;

        // From glibc 2.19, sysdeps/unix/sysv/linux/cmsg_nxthdr.c
        FUNCTION
        struct cmsghdr *cmsg_nxthdr (struct msghdr *mhdr, struct cmsghdr *cmsg)
        {
            if ((size_t) cmsg->cmsg_len < sizeof (struct cmsghdr))
            /* The kernel header does this so there may be a reason.  */
                return NULL;

            cmsg = (struct cmsghdr *) ((unsigned char *) cmsg
                    + CMSG_ALIGN (cmsg->cmsg_len));

            if ((unsigned char *) (cmsg + 1) > ((unsigned char *) mhdr->msg_control
                                                + mhdr->msg_controllen)
                || ((unsigned char *) cmsg + CMSG_ALIGN (cmsg->cmsg_len)
                    > ((unsigned char *) mhdr->msg_control + mhdr->msg_controllen)))
                /* No more entries.  */
                return NULL;

            return cmsg;
        }

        template <>
        struct Sockaddr<AddressType::UNIX_ABSTRACT>
        {
            static constexpr int family = AF_UNIX;
            using type = struct sockaddr_un;

            FUNCTION
            struct sockaddr_un pack(UnixAbstractAddress const unixaddr, size_t& size)
            {
                struct sockaddr_un addr;
                String sock_path(addr.sun_path + 1);

                addr.sun_family = AF_UNIX;
                addr.sun_path[0] = '\0';
                String::copy(addr.sun_path + 1, unixaddr.path, sizeof(addr.sun_path) - 1);

                size = sizeof(addr.sun_family) + String::length(unixaddr.path) + 1;
                return addr;
            }
        };

        METHOD
        size_t SocketIO::available_input_bytes()
        {
            size_t nr_bytes = 0;

            Syscall::ioctl(fd, FIONREAD, &nr_bytes);
            return nr_bytes;
        }

        CONSTRUCTOR
        SctpSocket::SctpSocket() : StreamSocket(AF_INET, IPPROTO_SCTP) {}

        CONSTRUCTOR
        Sctp6Socket::Sctp6Socket() : StreamSocket(AF_INET6, IPPROTO_SCTP) {}
    }
}

#endif
<commit_msg>target/linux: export __cmsg_nxthdr<commit_after>#ifndef PICOLIB_SOCKET_IMPL_H_
#define PICOLIB_SOCKET_IMPL_H_

#include <sys/un.h>

namespace Pico {

    namespace Network {

        template <AddressType>
        struct Address;

        template <>
        struct Address<AddressType::UNIX_ABSTRACT>
        {
            char *path;
        };

        using UnixAbstractAddress   = Address<AddressType::UNIX_ABSTRACT>;

        template <>
        struct Sockaddr<AddressType::UNIX_ABSTRACT>
        {
            static constexpr int family = AF_UNIX;
            using type = struct sockaddr_un;

            FUNCTION
            struct sockaddr_un pack(UnixAbstractAddress const unixaddr, size_t& size)
            {
                struct sockaddr_un addr;
                String sock_path(addr.sun_path + 1);

                addr.sun_family = AF_UNIX;
                addr.sun_path[0] = '\0';
                String::copy(addr.sun_path + 1, unixaddr.path, sizeof(addr.sun_path) - 1);

                size = sizeof(addr.sun_family) + String::length(unixaddr.path) + 1;
                return addr;
            }
        };

        METHOD
        size_t SocketIO::available_input_bytes()
        {
            size_t nr_bytes = 0;

            Syscall::ioctl(fd, FIONREAD, &nr_bytes);
            return nr_bytes;
        }

        CONSTRUCTOR
        SctpSocket::SctpSocket() : StreamSocket(AF_INET, IPPROTO_SCTP) {}

        CONSTRUCTOR
        Sctp6Socket::Sctp6Socket() : StreamSocket(AF_INET6, IPPROTO_SCTP) {}
    }
}

extern "C" {
    //
    // From glibc 2.19, sysdeps/unix/sysv/linux/cmsg_nxthdr.c
    // Required by CMSG_NXTHDR.
    //
    EXPORT_ABI_FUNCTION
    struct cmsghdr *__cmsg_nxthdr (struct msghdr *mhdr, struct cmsghdr *cmsg)
    {
        if ((size_t) cmsg->cmsg_len < sizeof (struct cmsghdr))
        /* The kernel header does this so there may be a reason.  */
            return NULL;

        cmsg = (struct cmsghdr *) ((unsigned char *) cmsg
                + CMSG_ALIGN (cmsg->cmsg_len));

        if ((unsigned char *) (cmsg + 1) > ((unsigned char *) mhdr->msg_control
                                            + mhdr->msg_controllen)
            || ((unsigned char *) cmsg + CMSG_ALIGN (cmsg->cmsg_len)
                > ((unsigned char *) mhdr->msg_control + mhdr->msg_controllen)))
            /* No more entries.  */
            return NULL;

        return cmsg;
    }
}

#endif
<|endoftext|>


<commit_before>/*
MIT License

Copyright (c) 2017 Eren Okka

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#include <memory>

#include <windows.h>
#include <winternl.h>

#include "process.h"
#include "util.h"

namespace anisthesia {
namespace win {

using buffer_t = std::unique_ptr<BYTE[]>;

constexpr NTSTATUS STATUS_INFO_LENGTH_MISMATCH = 0xC0000004L;
constexpr NTSTATUS STATUS_SUCCESS = 0x00000000L;

enum {
  SystemExtendedHandleInformation = 64,
};

struct SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX {
  PVOID Object;
  ULONG_PTR UniqueProcessId;
  HANDLE HandleValue;
  ACCESS_MASK GrantedAccess;
  USHORT CreatorBackTraceIndex;
  USHORT ObjectTypeIndex;
  ULONG HandleAttributes;
  ULONG Reserved;
};

struct SYSTEM_HANDLE_INFORMATION_EX {
  ULONG_PTR NumberOfHandles;
  ULONG_PTR Reserved;
  SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1];
};

struct OBJECT_TYPE_INFORMATION {
  UNICODE_STRING TypeName;
  ULONG Reserved[22];
};

////////////////////////////////////////////////////////////////////////////////

PVOID GetLibraryProcAddress(LPCSTR module_name, LPCSTR proc_name) {
  return reinterpret_cast<PVOID>(
      GetProcAddress(GetModuleHandleA(module_name), proc_name));
}

PVOID GetNtProcAddress(LPCSTR proc_name) {
  return GetLibraryProcAddress("ntdll.dll", proc_name);
}

NTSTATUS NtQuerySystemInformation(
    SYSTEM_INFORMATION_CLASS system_information_class,
    PVOID system_information,
    ULONG system_information_length,
    PULONG return_length) {
  static const auto nt_query_system_information =
      reinterpret_cast<decltype(::NtQuerySystemInformation)*>(
          GetNtProcAddress("NtQuerySystemInformation"));
  return nt_query_system_information(system_information_class,
                                     system_information,
                                     system_information_length,
                                     return_length);
}

NTSTATUS NtQueryObject(
    HANDLE handle,
    OBJECT_INFORMATION_CLASS object_information_class,
    PVOID object_information,
    ULONG object_information_length,
    PULONG return_length) {
  static const auto nt_query_object =
      reinterpret_cast<decltype(::NtQueryObject)*>(
          GetNtProcAddress("NtQueryObject"));
  return nt_query_object(handle,
                         object_information_class,
                         object_information,
                         object_information_length,
                         return_length);
}

////////////////////////////////////////////////////////////////////////////////

inline bool NtSuccess(NTSTATUS status) {
  return status >= 0;
}

buffer_t QuerySystemInformation(
      SYSTEM_INFORMATION_CLASS system_information_class) {
  ULONG size = 1 << 20;                //  1 MiB
  constexpr ULONG kMaxSize = 1 << 24;  // 16 MiB

  buffer_t buffer(new BYTE[size]);
  NTSTATUS status = STATUS_SUCCESS;

  do {
    ULONG return_length = 0;
    status = win::NtQuerySystemInformation(
        system_information_class, buffer.get(), size, &return_length);
    if (status == STATUS_INFO_LENGTH_MISMATCH) {
      size = (return_length > size) ? return_length : (size * 2);
      buffer.reset(new BYTE[size]);
    }
  } while (status == STATUS_INFO_LENGTH_MISMATCH && size < kMaxSize);

  if (!NtSuccess(status))
    buffer.reset();

  return buffer;
}

buffer_t QueryObject(HANDLE handle,
                     OBJECT_INFORMATION_CLASS object_information_class,
                     ULONG size) {
  buffer_t buffer(new BYTE[size]);
  ULONG return_length = 0;

  const auto query_object = [&]() {
    return win::NtQueryObject(handle, object_information_class,
                              buffer.get(), size, &return_length);
  };

  auto status = query_object();
  if (status == STATUS_INFO_LENGTH_MISMATCH) {
    size = return_length;
    buffer.reset(new BYTE[size]);
    status = query_object();
  }

  if (!NtSuccess(status))
    buffer.reset();

  return buffer;
}

////////////////////////////////////////////////////////////////////////////////

HANDLE OpenProcess(DWORD process_id) {
  return ::OpenProcess(PROCESS_DUP_HANDLE, false, process_id);
}

HANDLE DuplicateHandle(HANDLE process_handle, HANDLE handle) {
  HANDLE dup_handle = nullptr;
  const auto result = ::DuplicateHandle(process_handle, handle,
                                        GetCurrentProcess(), &dup_handle,
                                        0, false, DUPLICATE_SAME_ACCESS);
  return result ? dup_handle : nullptr;
}

buffer_t GetSystemHandleInformation() {
  return QuerySystemInformation(
      static_cast<SYSTEM_INFORMATION_CLASS>(SystemExtendedHandleInformation));
}

std::wstring GetUnicodeString(const UNICODE_STRING& unicode_string) {
  if (!unicode_string.Length)
    return std::wstring();

  return std::wstring(unicode_string.Buffer,
                      unicode_string.Length / sizeof(WCHAR));
}

std::wstring GetObjectTypeName(HANDLE handle) {
  const auto buffer = QueryObject(handle, ObjectTypeInformation,
                                  sizeof(OBJECT_TYPE_INFORMATION));
  if (!buffer)
    return std::wstring();

  const auto& type_information =
      *reinterpret_cast<OBJECT_TYPE_INFORMATION*>(buffer.get());

  return GetUnicodeString(type_information.TypeName);
}

std::wstring GetFinalPathNameByHandle(HANDLE handle) {
  std::wstring buffer(MAX_PATH, '\0');

  auto get_final_path_name_by_handle = [&]() {
    return ::GetFinalPathNameByHandle(handle, &buffer.front(), buffer.size(),
        FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
  };

  auto result = get_final_path_name_by_handle();
  if (result > buffer.size()) {
    buffer.resize(result, '\0');
    result = get_final_path_name_by_handle();
  }

  if (result < buffer.size())
    buffer.resize(result);

  return buffer;
}

////////////////////////////////////////////////////////////////////////////////

bool VerifyObjectType(HANDLE handle, USHORT object_type_index) {
  // File type index varies between OS versions:
  //
  // - 25: Windows Vista
  // - 28: Windows XP, Windows 7
  // - 30: Windows 8.1
  // - 31: Windows 8, Windows 10
  // - 34: Windows 10 Anniversary Update
  //
  // Here we initialize the value with 0, so that it is determined at run time.
  // This is more reliable than hard-coding the values for each OS version.
  static USHORT file_type_index = 0;

  if (file_type_index)
    return object_type_index == file_type_index;

  if (!handle)
    return true;

  if (GetObjectTypeName(handle) == L"File") {
    file_type_index = object_type_index;
    return true;
  }

  return false;
}

bool VerifyAccessMask(ULONG access_mask) {
  // Skip access masks that may cause certain functions such as NtQueryObject
  // and GetFinalPathNameByHandle to hang. These masks usually belong to named
  // pipes.
  switch (access_mask) {
    case 0x00100000:  // SYNCHRONIZE access
    case 0x0012008d:  // e.g. "\Device\NamedPipe\DropboxDataPipe"
    case 0x00120189:
    case 0x0012019f:
    case 0x0016019f:  // e.g. "\Device\Afd\Endpoint"
    case 0x001a019f:
      return false;
    default:
      return true;
  }

  return true;
}

bool VerifyPathName(const std::wstring& path) {
  if (path.empty())
    return false;

  // Skip files under system directories
  // @TODO: Use %windir% environment variable
  const std::wstring windir = L"C:\\Windows";
  const size_t pos = path.find_first_not_of(L"\\?");
  if (path.substr(pos, windir.size()) == windir)
    return false;

  // Skip invalid files, and directories
  const auto file_attr = ::GetFileAttributes(path.c_str());
  if ((file_attr == INVALID_FILE_ATTRIBUTES) ||
      (file_attr & FILE_ATTRIBUTE_DIRECTORY)) {
    return false;
  }

  return true;
}

bool EnumerateFiles(std::map<DWORD, std::vector<std::wstring>>& files) {
  std::map<DWORD, Handle> process_handles;
  for (const auto pair : files) {
    const auto process_id = pair.first;
    const auto handle = OpenProcess(process_id);
    if (handle)
      process_handles[process_id] = Handle(handle);
  }
  if (process_handles.empty())
    return false;

  auto system_handle_information_buffer = GetSystemHandleInformation();
  if (!system_handle_information_buffer)
    return false;

  const auto& system_handle_information =
      *reinterpret_cast<SYSTEM_HANDLE_INFORMATION_EX*>(
          system_handle_information_buffer.get());
  if (!system_handle_information.NumberOfHandles)
    return false;

  for (size_t i = 0; i < system_handle_information.NumberOfHandles; ++i) {
    const auto& handle = system_handle_information.Handles[i];

    // Skip if this handle does not belong to one of our PIDs
    const auto process_id = static_cast<DWORD>(handle.UniqueProcessId);
    if (!process_handles.count(process_id))
      continue;

    // Skip if this is not a file handle
    if (!VerifyObjectType(nullptr, handle.ObjectTypeIndex))
      continue;

    // Skip access masks that are known to cause trouble
    if (!VerifyAccessMask(handle.GrantedAccess))
      continue;

    // Duplicate the handle so that we can query it
    const auto process_handle = process_handles[process_id].get();
    Handle dup_handle(DuplicateHandle(process_handle, handle.HandleValue));
    if (!dup_handle)
      continue;

    // Skip if this is not a file handle, while determining file type index
    if (!VerifyObjectType(dup_handle.get(), handle.ObjectTypeIndex))
      continue;

    // Skip if this is not a disk file (i.e. it is a character file, a socket,
    // a pipe, or a file of unknown type)
    if (::GetFileType(dup_handle.get()) != FILE_TYPE_DISK)
      continue;

    const auto path = GetFinalPathNameByHandle(dup_handle.get());
    if (VerifyPathName(path))
      files[process_id].push_back(path);
  }

  return true;
}

}  // namespace win
}  // namespace anisthesia
<commit_msg>Add file type verification function<commit_after>/*
MIT License

Copyright (c) 2017 Eren Okka

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#include <memory>

#include <windows.h>
#include <winternl.h>

#include "process.h"
#include "util.h"

namespace anisthesia {
namespace win {

using buffer_t = std::unique_ptr<BYTE[]>;

constexpr NTSTATUS STATUS_INFO_LENGTH_MISMATCH = 0xC0000004L;
constexpr NTSTATUS STATUS_SUCCESS = 0x00000000L;

enum {
  SystemExtendedHandleInformation = 64,
};

struct SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX {
  PVOID Object;
  ULONG_PTR UniqueProcessId;
  HANDLE HandleValue;
  ACCESS_MASK GrantedAccess;
  USHORT CreatorBackTraceIndex;
  USHORT ObjectTypeIndex;
  ULONG HandleAttributes;
  ULONG Reserved;
};

struct SYSTEM_HANDLE_INFORMATION_EX {
  ULONG_PTR NumberOfHandles;
  ULONG_PTR Reserved;
  SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1];
};

struct OBJECT_TYPE_INFORMATION {
  UNICODE_STRING TypeName;
  ULONG Reserved[22];
};

////////////////////////////////////////////////////////////////////////////////

PVOID GetLibraryProcAddress(LPCSTR module_name, LPCSTR proc_name) {
  return reinterpret_cast<PVOID>(
      GetProcAddress(GetModuleHandleA(module_name), proc_name));
}

PVOID GetNtProcAddress(LPCSTR proc_name) {
  return GetLibraryProcAddress("ntdll.dll", proc_name);
}

NTSTATUS NtQuerySystemInformation(
    SYSTEM_INFORMATION_CLASS system_information_class,
    PVOID system_information,
    ULONG system_information_length,
    PULONG return_length) {
  static const auto nt_query_system_information =
      reinterpret_cast<decltype(::NtQuerySystemInformation)*>(
          GetNtProcAddress("NtQuerySystemInformation"));
  return nt_query_system_information(system_information_class,
                                     system_information,
                                     system_information_length,
                                     return_length);
}

NTSTATUS NtQueryObject(
    HANDLE handle,
    OBJECT_INFORMATION_CLASS object_information_class,
    PVOID object_information,
    ULONG object_information_length,
    PULONG return_length) {
  static const auto nt_query_object =
      reinterpret_cast<decltype(::NtQueryObject)*>(
          GetNtProcAddress("NtQueryObject"));
  return nt_query_object(handle,
                         object_information_class,
                         object_information,
                         object_information_length,
                         return_length);
}

////////////////////////////////////////////////////////////////////////////////

inline bool NtSuccess(NTSTATUS status) {
  return status >= 0;
}

buffer_t QuerySystemInformation(
      SYSTEM_INFORMATION_CLASS system_information_class) {
  ULONG size = 1 << 20;                //  1 MiB
  constexpr ULONG kMaxSize = 1 << 24;  // 16 MiB

  buffer_t buffer(new BYTE[size]);
  NTSTATUS status = STATUS_SUCCESS;

  do {
    ULONG return_length = 0;
    status = win::NtQuerySystemInformation(
        system_information_class, buffer.get(), size, &return_length);
    if (status == STATUS_INFO_LENGTH_MISMATCH) {
      size = (return_length > size) ? return_length : (size * 2);
      buffer.reset(new BYTE[size]);
    }
  } while (status == STATUS_INFO_LENGTH_MISMATCH && size < kMaxSize);

  if (!NtSuccess(status))
    buffer.reset();

  return buffer;
}

buffer_t QueryObject(HANDLE handle,
                     OBJECT_INFORMATION_CLASS object_information_class,
                     ULONG size) {
  buffer_t buffer(new BYTE[size]);
  ULONG return_length = 0;

  const auto query_object = [&]() {
    return win::NtQueryObject(handle, object_information_class,
                              buffer.get(), size, &return_length);
  };

  auto status = query_object();
  if (status == STATUS_INFO_LENGTH_MISMATCH) {
    size = return_length;
    buffer.reset(new BYTE[size]);
    status = query_object();
  }

  if (!NtSuccess(status))
    buffer.reset();

  return buffer;
}

////////////////////////////////////////////////////////////////////////////////

HANDLE OpenProcess(DWORD process_id) {
  return ::OpenProcess(PROCESS_DUP_HANDLE, false, process_id);
}

HANDLE DuplicateHandle(HANDLE process_handle, HANDLE handle) {
  HANDLE dup_handle = nullptr;
  const auto result = ::DuplicateHandle(process_handle, handle,
                                        GetCurrentProcess(), &dup_handle,
                                        0, false, DUPLICATE_SAME_ACCESS);
  return result ? dup_handle : nullptr;
}

buffer_t GetSystemHandleInformation() {
  return QuerySystemInformation(
      static_cast<SYSTEM_INFORMATION_CLASS>(SystemExtendedHandleInformation));
}

std::wstring GetUnicodeString(const UNICODE_STRING& unicode_string) {
  if (!unicode_string.Length)
    return std::wstring();

  return std::wstring(unicode_string.Buffer,
                      unicode_string.Length / sizeof(WCHAR));
}

std::wstring GetObjectTypeName(HANDLE handle) {
  const auto buffer = QueryObject(handle, ObjectTypeInformation,
                                  sizeof(OBJECT_TYPE_INFORMATION));
  if (!buffer)
    return std::wstring();

  const auto& type_information =
      *reinterpret_cast<OBJECT_TYPE_INFORMATION*>(buffer.get());

  return GetUnicodeString(type_information.TypeName);
}

std::wstring GetFinalPathNameByHandle(HANDLE handle) {
  std::wstring buffer(MAX_PATH, '\0');

  auto get_final_path_name_by_handle = [&]() {
    return ::GetFinalPathNameByHandle(handle, &buffer.front(), buffer.size(),
        FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
  };

  auto result = get_final_path_name_by_handle();
  if (result > buffer.size()) {
    buffer.resize(result, '\0');
    result = get_final_path_name_by_handle();
  }

  if (result < buffer.size())
    buffer.resize(result);

  return buffer;
}

////////////////////////////////////////////////////////////////////////////////

bool VerifyObjectType(HANDLE handle, USHORT object_type_index) {
  // File type index varies between OS versions:
  //
  // - 25: Windows Vista
  // - 28: Windows XP, Windows 7
  // - 30: Windows 8.1
  // - 31: Windows 8, Windows 10
  // - 34: Windows 10 Anniversary Update
  //
  // Here we initialize the value with 0, so that it is determined at run time.
  // This is more reliable than hard-coding the values for each OS version.
  static USHORT file_type_index = 0;

  if (file_type_index)
    return object_type_index == file_type_index;

  if (!handle)
    return true;

  if (GetObjectTypeName(handle) == L"File") {
    file_type_index = object_type_index;
    return true;
  }

  return false;
}

bool VerifyAccessMask(ULONG access_mask) {
  // Skip access masks that may cause certain functions such as NtQueryObject
  // and GetFinalPathNameByHandle to hang. These masks usually belong to named
  // pipes.
  switch (access_mask) {
    case 0x00100000:  // SYNCHRONIZE access
    case 0x0012008d:  // e.g. "\Device\NamedPipe\DropboxDataPipe"
    case 0x00120189:
    case 0x0012019f:
    case 0x0016019f:  // e.g. "\Device\Afd\Endpoint"
    case 0x001a019f:
      return false;
    default:
      return true;
  }

  return true;
}

bool VerifyFileType(HANDLE handle) {
  // Skip character files, sockets, pipes, and files of unknown type
  return ::GetFileType(handle) == FILE_TYPE_DISK;
}

bool VerifyPathName(const std::wstring& path) {
  if (path.empty())
    return false;

  // Skip files under system directories
  // @TODO: Use %windir% environment variable
  const std::wstring windir = L"C:\\Windows";
  const size_t pos = path.find_first_not_of(L"\\?");
  if (path.substr(pos, windir.size()) == windir)
    return false;

  // Skip invalid files, and directories
  const auto file_attr = ::GetFileAttributes(path.c_str());
  if ((file_attr == INVALID_FILE_ATTRIBUTES) ||
      (file_attr & FILE_ATTRIBUTE_DIRECTORY)) {
    return false;
  }

  return true;
}

bool EnumerateFiles(std::map<DWORD, std::vector<std::wstring>>& files) {
  std::map<DWORD, Handle> process_handles;
  for (const auto pair : files) {
    const auto process_id = pair.first;
    const auto handle = OpenProcess(process_id);
    if (handle)
      process_handles[process_id] = Handle(handle);
  }
  if (process_handles.empty())
    return false;

  auto system_handle_information_buffer = GetSystemHandleInformation();
  if (!system_handle_information_buffer)
    return false;

  const auto& system_handle_information =
      *reinterpret_cast<SYSTEM_HANDLE_INFORMATION_EX*>(
          system_handle_information_buffer.get());
  if (!system_handle_information.NumberOfHandles)
    return false;

  for (size_t i = 0; i < system_handle_information.NumberOfHandles; ++i) {
    const auto& handle = system_handle_information.Handles[i];

    // Skip if this handle does not belong to one of our PIDs
    const auto process_id = static_cast<DWORD>(handle.UniqueProcessId);
    if (!process_handles.count(process_id))
      continue;

    // Skip if this is not a file handle
    if (!VerifyObjectType(nullptr, handle.ObjectTypeIndex))
      continue;

    // Skip access masks that are known to cause trouble
    if (!VerifyAccessMask(handle.GrantedAccess))
      continue;

    // Duplicate the handle so that we can query it
    const auto process_handle = process_handles[process_id].get();
    Handle dup_handle(DuplicateHandle(process_handle, handle.HandleValue));
    if (!dup_handle)
      continue;

    // Skip if this is not a file handle, while determining file type index
    if (!VerifyObjectType(dup_handle.get(), handle.ObjectTypeIndex))
      continue;

    // Skip if this is not a disk file
    if (!VerifyFileType(dup_handle.get()))
      continue;

    const auto path = GetFinalPathNameByHandle(dup_handle.get());
    if (VerifyPathName(path))
      files[process_id].push_back(path);
  }

  return true;
}

}  // namespace win
}  // namespace anisthesia
<|endoftext|>


<commit_before><commit_msg>feat: option to let support be replaced by brim or not<commit_after><|endoftext|>


<commit_before><commit_msg>make /poll flagreset command directly reset the flags, bypassing auth and so on.<commit_after><|endoftext|>


<commit_before><commit_msg>Make m_result_number value available to Schema for appending results, Query String for now, maybe others later.<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License 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 "stdafx.h"

#include <sstream>

#include <zorba/zorba_exception.h>
#include <zorba/xquery_warning.h>

#include "dict.h"

#ifndef NDEBUG
#include <cstdlib>                      /* for abort() */
ZORBA_DLL_PUBLIC bool g_abort_on_error;
#endif /* NDEBUG */

using namespace std;

namespace zorba {

///////////////////////////////////////////////////////////////////////////////

ZorbaException::ZorbaException( Diagnostic const &diagnostic,
                                char const *raise_file, line_type raise_line,
                                char const *message ) :
  diagnostic_( diagnostic.clone() ),
  raise_file_( raise_file ),
  raise_line_( raise_line ),
  message_( message )
{
#ifndef NDEBUG
  if ( g_abort_on_error )
    abort();
#endif /* NDEBUG */
}

ZorbaException::ZorbaException( ZorbaException const &from ) :
  std::exception( from ),
  diagnostic_( from.diagnostic_->clone() ),
  raise_file_( from.raise_file_ ),
  raise_line_( from.raise_line_ ),
  message_( from.message_ )
{
}

ZorbaException::ZorbaException( serialization::Archiver &ar )
{
}

ZorbaException::~ZorbaException() throw() {
  diagnostic_->destroy();
}

ZorbaException& ZorbaException::operator=( ZorbaException const &from ) {
  if ( &from != this ) {
    std::exception::operator=( from );
    diagnostic_->destroy();
    diagnostic_ = from.diagnostic_->clone();
    raise_file_ = from.raise_file_;
    raise_line_ = from.raise_line_;
    message_    = from.message_;
  }
  return *this;
}

unique_ptr<ZorbaException> ZorbaException::clone() const {
  return unique_ptr<ZorbaException>( new ZorbaException( *this ) );
}

int ZorbaException::get_ios_format_index() {
  static int const index = ios_base::xalloc();
  return index;
}

void ZorbaException::polymorphic_throw() const {
  throw *this;
}

ostream& ZorbaException::print( ostream& o ) const {
  bool const as_xml = get_print_format( o ) == format_xml;
  if ( as_xml )
    o << "<exception>";
  print_impl( o );
  if ( as_xml )
    o << "<exception>";
  return o;
}

ostream& ZorbaException::print_impl( ostream &o ) const {
  //
  // We need to create an error phrase (e.g., "static error") and look that up
  // as a unit rather than looking up the error kind word and "error"
  // separately because many languages have the word order reversed (e.g.,
  // "static error" becomes "erreur statique" in French).
  //
  ostringstream oss;
  oss << ZED_PREFIX;

  streampos pos = oss.tellp();
  Diagnostic const &d = diagnostic();
  oss << d.category();
  if ( oss.tellp() != pos )             // emit ' ' only if non-empty category
    oss << ' ';

  if ( diagnostic::kind const k = d.kind() )
    oss << k << ' ';

  oss << (dynamic_cast<ZorbaWarningCode const*>( &d ) ? "warning" : "error");

  bool const as_xml = get_print_format( o ) == format_xml;
  if ( as_xml )
    o << "<kind>";

  o << diagnostic::dict::lookup( oss.str() );

  if ( as_xml )
    o << "</kind>" << d.qname();
  else
    o << " [" << d.qname() << ']';

  if ( as_xml )
    o << "";

  if ( char const *const w = what() )
    if ( *w ) {
      if ( as_xml )
        o << "<description>";
      else
        o << ": ";

      o << w;

      if ( as_xml )
        o << "</description>";
    }

#ifndef NDEBUG
  if ( !as_xml )
    o << "; raised at " << raise_file() << ':' << raise_line();
#endif

  return o;
}

char const* ZorbaException::what() const throw() {
  return message_.c_str();
}

///////////////////////////////////////////////////////////////////////////////

ZorbaException
make_zorba_exception( char const *raise_file,
                      ZorbaException::line_type raise_line,
                      Diagnostic const &diagnostic,
                      internal::diagnostic::parameters const &params ) {
  internal::diagnostic::parameters::value_type message( diagnostic.message() );
  params.substitute( &message );
  return ZorbaException( diagnostic, raise_file, raise_line, message.c_str() );
}

ZorbaException*
new_zorba_exception( char const *raise_file,
                     ZorbaException::line_type raise_line,
                     Diagnostic const &diagnostic,
                     internal::diagnostic::parameters const &params ) {
  internal::diagnostic::parameters::value_type message( diagnostic.message() );
  params.substitute( &message );
  return new ZorbaException(
    diagnostic, raise_file, raise_line, message.c_str()
  );
}

///////////////////////////////////////////////////////////////////////////////

} // namespace zorba
/* vim:set et sw=2 ts=2: */
<commit_msg>More clean-up.<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License 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 "stdafx.h"

#include <sstream>

#include <zorba/zorba_exception.h>
#include <zorba/xquery_warning.h>

#include "dict.h"

#ifndef NDEBUG
#include <cstdlib>                      /* for abort() */
ZORBA_DLL_PUBLIC bool g_abort_on_error;
#endif /* NDEBUG */

using namespace std;

namespace zorba {

///////////////////////////////////////////////////////////////////////////////

ZorbaException::ZorbaException( Diagnostic const &diagnostic,
                                char const *raise_file, line_type raise_line,
                                char const *message ) :
  diagnostic_( diagnostic.clone() ),
  raise_file_( raise_file ),
  raise_line_( raise_line ),
  message_( message )
{
#ifndef NDEBUG
  if ( g_abort_on_error )
    abort();
#endif /* NDEBUG */
}

ZorbaException::ZorbaException( ZorbaException const &from ) :
  std::exception( from ),
  diagnostic_( from.diagnostic_->clone() ),
  raise_file_( from.raise_file_ ),
  raise_line_( from.raise_line_ ),
  message_( from.message_ )
{
}

ZorbaException::ZorbaException( serialization::Archiver &ar )
{
}

ZorbaException::~ZorbaException() throw() {
  diagnostic_->destroy();
}

ZorbaException& ZorbaException::operator=( ZorbaException const &from ) {
  if ( &from != this ) {
    std::exception::operator=( from );
    diagnostic_->destroy();
    diagnostic_ = from.diagnostic_->clone();
    raise_file_ = from.raise_file_;
    raise_line_ = from.raise_line_;
    message_    = from.message_;
  }
  return *this;
}

unique_ptr<ZorbaException> ZorbaException::clone() const {
  return unique_ptr<ZorbaException>( new ZorbaException( *this ) );
}

int ZorbaException::get_ios_format_index() {
  static int const index = ios_base::xalloc();
  return index;
}

void ZorbaException::polymorphic_throw() const {
  throw *this;
}

ostream& ZorbaException::print( ostream& o ) const {
  bool const as_xml = get_print_format( o ) == format_xml;
  if ( as_xml )
    o << "<exception>";
  print_impl( o );
  if ( as_xml )
    o << "<exception>";
  return o;
}

ostream& ZorbaException::print_impl( ostream &o ) const {
  //
  // We need to create an error phrase (e.g., "static error") and look that up
  // as a unit rather than looking up the error kind word and "error"
  // separately because many languages have the word order reversed (e.g.,
  // "static error" becomes "erreur statique" in French).
  //
  ostringstream oss;
  oss << ZED_PREFIX;

  streampos pos = oss.tellp();
  Diagnostic const &d = diagnostic();
  oss << d.category();
  if ( oss.tellp() != pos )             // emit ' ' only if non-empty category
    oss << ' ';

  if ( diagnostic::kind const k = d.kind() )
    oss << k << ' ';

  oss << (dynamic_cast<ZorbaWarningCode const*>( &d ) ? "warning" : "error");

  bool const as_xml = get_print_format( o ) == format_xml;
  if ( as_xml )
    o << "<kind>";

  o << diagnostic::dict::lookup( oss.str() );

  if ( as_xml )
    o << "</kind>" << d.qname() << "";
  else
    o << " [" << d.qname() << ']';

  if ( char const *const w = what() )
    if ( *w ) {
      if ( as_xml )
        o << "<description>";
      else
        o << ": ";

      o << w;

      if ( as_xml )
        o << "</description>";
    }

#ifndef NDEBUG
  if ( !as_xml )
    o << "; raised at " << raise_file() << ':' << raise_line();
#endif

  return o;
}

char const* ZorbaException::what() const throw() {
  return message_.c_str();
}

///////////////////////////////////////////////////////////////////////////////

ZorbaException
make_zorba_exception( char const *raise_file,
                      ZorbaException::line_type raise_line,
                      Diagnostic const &diagnostic,
                      internal::diagnostic::parameters const &params ) {
  internal::diagnostic::parameters::value_type message( diagnostic.message() );
  params.substitute( &message );
  return ZorbaException( diagnostic, raise_file, raise_line, message.c_str() );
}

ZorbaException*
new_zorba_exception( char const *raise_file,
                     ZorbaException::line_type raise_line,
                     Diagnostic const &diagnostic,
                     internal::diagnostic::parameters const &params ) {
  internal::diagnostic::parameters::value_type message( diagnostic.message() );
  params.substitute( &message );
  return new ZorbaException(
    diagnostic, raise_file, raise_line, message.c_str()
  );
}

///////////////////////////////////////////////////////////////////////////////

} // namespace zorba
/* vim:set et sw=2 ts=2: */
<|endoftext|>


<commit_before><commit_msg>accept_rep(NodeId, const MsgAppendEntriesRep& r) should check term before checking current_idx.<commit_after><|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (C) 2015 Mark Charl. All rights reserved.
 *   Copyright (C) 2017 Fan.zhang. All rights reserved. 421395590@qq.com
 *   Copyright (C) 2016 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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 OWNER 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.
 *
 ****************************************************************************/
#include "rpi_rc_in.h"

using namespace rpi_rc_in;
//---------------------------------------------------------------------------------------------------------//
int RcInput::rpi_rc_init()
{
	int i;

	//--------------初始化共享内存映射----------------------------//
	if ((this->shmid = shmget(this->key, sizeof(int) * this->_channels, 0666))
	    < 0) {
		PX4_WARN("无法访问共享内存。Faild to access shared memory");
		return -1;
	}

	if ((this->mem = (int *) shmat(this->shmid, NULL, 0)) == (void *) - 1) {
		PX4_WARN("无法映射共享内存。Faild to mapping shared memory");
		return -1;
	}

	//--------------发布所有通道的数据------------------------//
	for (i = 0; i < input_rc_s::RC_INPUT_MAX_CHANNELS; ++i) {
		_data.values[i] = UINT16_MAX;
	}

	_rcinput_pub = orb_advertise(ORB_ID(input_rc), &_data);

	if (_rcinput_pub == nullptr) {
		PX4_WARN("error: advertise failed");
		return -1;
	}

	return 0;
}
//---------------------------------------------------------------------------------------------------------//
int RcInput::start()
{
	int result = 0;

	result = rpi_rc_init();

	if (result != 0) {
		PX4_WARN("error: RC initialization failed");
		return -1;
	}

	_isRunning = true;
	result = work_queue(HPWORK, &_work, (worker_t) & RcInput::cycle_trampoline,
			    this, 0);

	if (result == -1) {
		_isRunning = false;
	}

	return result;
}
//---------------------------------------------------------------------------------------------------------//
void RcInput::stop()
{
	_shouldExit = true;
}
//---------------------------------------------------------------------------------------------------------//
void RcInput::cycle_trampoline(void *arg)
{
	RcInput *dev = reinterpret_cast<RcInput *>(arg);
	dev->_cycle();
}
//---------------------------------------------------------------------------------------------------------//
void RcInput::_cycle()
{
	_measure();

	if (!_shouldExit) {
		work_queue(HPWORK, &_work, (worker_t) & RcInput::cycle_trampoline, this,
			   USEC2TICK(RCINPUT_MEASURE_INTERVAL_US));
	}
}
//---------------------------------------------------------------------------------------------------------//
void RcInput::_measure(void)
{
	uint64_t ts;
	// PWM数据发布
	// read pwm value from shared memory
	int i = 0;

	for (i = 0; i < _channels; ++i) {
		_data.values[i] = (*(this->mem + i) <= 0) ? UINT16_MAX : *(this->mem + i);
	}

	ts = hrt_absolute_time();
	_data.timestamp = ts;
	_data.timestamp_last_signal = ts;
	_data.channel_count = _channels;
	_data.rssi = 100;
	_data.rc_lost_frame_count = 0;
	_data.rc_total_frame_count = 1;
	_data.rc_ppm_frame_length = 100;
	_data.rc_failsafe = false;
	_data.rc_lost = false;
	_data.input_source = input_rc_s::RC_INPUT_SOURCE_PX4IO_PPM;

	orb_publish(ORB_ID(input_rc), _rcinput_pub, &_data);
}
//---------------------------------------------------------------------------------------------------------//
/**
 * Print the correct usage.
 */

static void rpi_rc_in::usage(const char *reason)
{
	if (reason) {
		PX4_ERR("%s", reason);
	}

	PX4_INFO("用法: rpi_rc_in {start|stop|status}");
}
//---------------------------------------------------------------------------------------------------------//
int rpi_rc_in_main(int argc, char **argv)
{
	if (argc < 2) {
		usage("missing command");
		return 1;
	}

	if (!strcmp(argv[1], "start")) {

		if (rc_input != nullptr && rc_input->isRunning()) {
			PX4_WARN("运行中。running");
			/* this is not an error */
			return 0;
		}

		rc_input = new RcInput();

		// Check if alloc worked.
		if (nullptr == rc_input) {
			PX4_ERR("遥控输入模块初始化错误。Rc input moduel  initialization faild");
			return -1;
		}

		int ret = rc_input->start();

		if (ret != 0) {
			PX4_ERR("遥控输入模块未能启动。 Rc input module failure");
		}

		return 0;
	}

	if (!strcmp(argv[1], "stop")) {

		if (rc_input == nullptr || !rc_input->isRunning()) {
			PX4_WARN("模块未运行。 Not runing");
			/* this is not an error */
			return 0;
		}

		rc_input->stop();

		// Wait for task to die
		int i = 0;

		do {
			/* wait up to 3s */
			usleep(100000);

		} while (rc_input->isRunning() && ++i < 30);

		delete rc_input;
		rc_input = nullptr;

		return 0;
	}

	if (!strcmp(argv[1], "status")) {
		if (rc_input != nullptr && rc_input->isRunning()) {
			PX4_INFO("运行中。 running");

		} else {
			PX4_INFO("未运行。 Not runing\n");
		}

		return 0;
	}

	usage("不知道你要做什么。 rpi_rc_in start|stop|status");
	return 1;

}
//---------------------------------------------------------------------------------------------------------//
<commit_msg>Check _rcinput_pub is null.<commit_after>/****************************************************************************
 *
 *   Copyright (C) 2015 Mark Charl. All rights reserved.
 *   Copyright (C) 2017 Fan.zhang. All rights reserved. 421395590@qq.com
 *   Copyright (C) 2016 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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 OWNER 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.
 *
 ****************************************************************************/
#include "rpi_rc_in.h"

using namespace rpi_rc_in;
//---------------------------------------------------------------------------------------------------------//
int RcInput::rpi_rc_init()
{
	int i;

	//--------------初始化共享内存映射----------------------------//
	if ((this->shmid = shmget(this->key, sizeof(int) * this->_channels, 0666))
	    < 0) {
		PX4_WARN("无法访问共享内存。Faild to access shared memory");
		return -1;
	}

	if ((this->mem = (int *) shmat(this->shmid, NULL, 0)) == (void *) - 1) {
		PX4_WARN("无法映射共享内存。Faild to mapping shared memory");
		return -1;
	}

	//--------------发布所有通道的数据------------------------//
	for (i = 0; i < input_rc_s::RC_INPUT_MAX_CHANNELS; ++i) {
		_data.values[i] = UINT16_MAX;
	}

	_rcinput_pub = orb_advertise(ORB_ID(input_rc), &_data);

	if (_rcinput_pub == nullptr) {
		PX4_WARN("error: advertise failed");
		return -1;
	}

	return 0;
}
//---------------------------------------------------------------------------------------------------------//
int RcInput::start()
{
	int result = 0;

	result = rpi_rc_init();

	if (result != 0) {
		PX4_WARN("error: RC initialization failed");
		return -1;
	}

	_isRunning = true;
	result = work_queue(HPWORK, &_work, (worker_t) & RcInput::cycle_trampoline,
			    this, 0);

	if (result == -1) {
		_isRunning = false;
	}

	return result;
}
//---------------------------------------------------------------------------------------------------------//
void RcInput::stop()
{
	_shouldExit = true;
}
//---------------------------------------------------------------------------------------------------------//
void RcInput::cycle_trampoline(void *arg)
{
	RcInput *dev = reinterpret_cast<RcInput *>(arg);
	dev->_cycle();
}
//---------------------------------------------------------------------------------------------------------//
void RcInput::_cycle()
{
	_measure();

	if (!_shouldExit) {
		work_queue(HPWORK, &_work, (worker_t) & RcInput::cycle_trampoline, this,
			   USEC2TICK(RCINPUT_MEASURE_INTERVAL_US));
	}
}
//---------------------------------------------------------------------------------------------------------//
void RcInput::_measure(void)
{
	uint64_t ts;
	// PWM数据发布
	// read pwm value from shared memory
	int i = 0;

	for (i = 0; i < _channels; ++i) {
		_data.values[i] = (*(this->mem + i) <= 0) ? UINT16_MAX : *(this->mem + i);
	}

	ts = hrt_absolute_time();
	_data.timestamp = ts;
	_data.timestamp_last_signal = ts;
	_data.channel_count = _channels;
	_data.rssi = 100;
	_data.rc_lost_frame_count = 0;
	_data.rc_total_frame_count = 1;
	_data.rc_ppm_frame_length = 100;
	_data.rc_failsafe = false;
	_data.rc_lost = false;
	_data.input_source = input_rc_s::RC_INPUT_SOURCE_PX4IO_PPM;

	if (nullptr == _rcinput_pub) {
		int instance;
		_rcinput_pub = orb_advertise_multi(ORB_ID(input_rc), &_data, &instance, ORB_PRIO_DEFAULT);

	} else {
		orb_publish(ORB_ID(input_rc), _rcinput_pub, &_data);
	}
}
//---------------------------------------------------------------------------------------------------------//
/**
 * Print the correct usage.
 */

static void rpi_rc_in::usage(const char *reason)
{
	if (reason) {
		PX4_ERR("%s", reason);
	}

	PX4_INFO("用法: rpi_rc_in {start|stop|status}");
}
//---------------------------------------------------------------------------------------------------------//
int rpi_rc_in_main(int argc, char **argv)
{
	if (argc < 2) {
		usage("missing command");
		return 1;
	}

	if (!strcmp(argv[1], "start")) {

		if (rc_input != nullptr && rc_input->isRunning()) {
			PX4_WARN("运行中。running");
			/* this is not an error */
			return 0;
		}

		rc_input = new RcInput();

		// Check if alloc worked.
		if (nullptr == rc_input) {
			PX4_ERR("遥控输入模块初始化错误。Rc input moduel  initialization faild");
			return -1;
		}

		int ret = rc_input->start();

		if (ret != 0) {
			PX4_ERR("遥控输入模块未能启动。 Rc input module failure");
		}

		return 0;
	}

	if (!strcmp(argv[1], "stop")) {

		if (rc_input == nullptr || !rc_input->isRunning()) {
			PX4_WARN("模块未运行。 Not runing");
			/* this is not an error */
			return 0;
		}

		rc_input->stop();

		// Wait for task to die
		int i = 0;

		do {
			/* wait up to 3s */
			usleep(100000);

		} while (rc_input->isRunning() && ++i < 30);

		delete rc_input;
		rc_input = nullptr;

		return 0;
	}

	if (!strcmp(argv[1], "status")) {
		if (rc_input != nullptr && rc_input->isRunning()) {
			PX4_INFO("运行中。 running");

		} else {
			PX4_INFO("未运行。 Not runing\n");
		}

		return 0;
	}

	usage("不知道你要做什么。 rpi_rc_in start|stop|status");
	return 1;

}
//---------------------------------------------------------------------------------------------------------//
<|endoftext|>


<commit_before><commit_msg>update: Setting for SCI/I2C port<commit_after><|endoftext|>