<commit_before>#ifndef FIXED_BASIC_STRING_HPP
#define FIXED_BASIC_STRING_HPP

#include <string>
#include <type_traits>

#include "fixed/allocation_pattern.hpp"
#include "fixed/impl/fixed_def.hpp"
#include "fixed/impl/fixed_type_traits.hpp"
#include "fixed/vector.hpp"

namespace fixed
{
namespace _impl
{
    template <typename CHAR_T, size_t SIZE,
        typename Traits = std::char_traits<CHAR_T>,
        template <typename, size_t> typename Alloc_pattern
        = fixed::stack_allocator>
    class basic_string
    {
    public:
        typedef Traits traits_type;

        template <typename T, size_t ASIZE>
        using allocator_type = Alloc_pattern<T, ASIZE>;

    private:
        typedef allocator_type<CHAR_T, SIZE + 1> data_type;

    public:
        typedef typename data_type::value_type value_type;
        typedef typename data_type::aligned_type aligned_type;
        typedef typename data_type::size_type size_type;
        typedef typename data_type::difference_type difference_type;
        typedef typename data_type::reference reference;
        typedef typename data_type::const_reference const_reference;
        typedef typename data_type::pointer pointer;
        typedef typename data_type::const_pointer const_pointer;
        typedef typename data_type::iterator iterator;
        typedef typename data_type::const_iterator const_iterator;

        typedef std::reverse_iterator<iterator> reverse_iterator;
        typedef std::reverse_iterator<const_iterator> const_reverse_iterator;

    private:
        data_type _data;
        size_type _size;

        static_assert(std::is_trivial<CHAR_T>::value,
            "character type required to be trivial");
        static_assert(fixed::_impl::is_alloc_pattern_contiguous_v<data_type>,
            "Alloc_pattern required to be continuous for this container");

    public:
        constexpr basic_string() noexcept(
            is_nothrow_default_constructible_v<data_type>)
            : _data()
        {
        }

        template <typename Alloc_source,
            std::enable_if_t<is_allocation_source_v<Alloc_source>, int> = 0>
        constexpr basic_string(Alloc_source& source) noexcept(
            std::is_nothrow_constructible<data_type, Alloc_source&>::value)
            : _data(source)
        {
        }

        constexpr basic_string(size_type count, value_type ch)
            : _data()
        {
            assign(count, ch);
        }

        template <typename Alloc_source,
            std::enable_if_t<is_allocation_source_v<Alloc_source>, int> = 0>
        constexpr basic_string(
            size_type count, value_type ch, Alloc_source& source)
            : _data(source)
        {
            assign(count, ch);
        }

        constexpr basic_string& assign(size_type count, value_type ch)
        {
            FIXED_CHECK_FULL(count <= max_size());

            auto itbeg = _data.begin();
            for(size_type i = 0; i < count; i++)
            {
                *itbeg = ch;
                ++itbeg;
            }
            *itbeg = '\0';
            _size = count;
            return *this;
        }

		constexpr basic_string(const basic_string& str)
			: basic_string()
		{
			std::copy(str.begin(), str.end(), _data.begin());
		}

		constexpr basic_string& operator=(const basic_string& str)
		{
			if (this != &other)
			{
				std::copy(str.begin(), str.end(), _data.begin());
			}
			return *this;
		}

		constexpr basic_string(basic_string&& str) noexcept(
			is_nothrow_default_constructible_v<data_type>
			&& (is_nothrow_move_constructible_v<data_type>
				|| (is_nothrow_allocator_iterator_v<data_type> && (is_nothrow_move_constructible_v<CHAR_T> || is_nothrow_copy_constructible_v<CHAR_T>))))
			: basic_string()
		{
			if (this != &other)
			{
				fixed::astd::constexpr_if<
					std::is_nothrow_move_constructible<data_type>::value>(
						[this, &other]() {
					std::swap(_data, other._data);
					std::swap(_size, other._size);
				})
					._else([this, &other]() {
					for (auto& val : other)
					{
						push_back(std::move_if_noexcept(val));
					}
					other.clear();
				});
			}
		}

		constexpr basic_string& operator=(basic_string&& str) noexcept(
			is_nothrow_default_constructible_v<data_type>
			&& (is_nothrow_move_constructible_v<data_type>
				|| (is_nothrow_allocator_iterator_v<data_type> && (is_nothrow_move_constructible_v<CHAR_T> || is_nothrow_copy_constructible_v<CHAR_T>))))
		{
			if (this != &other)
			{
				fixed::astd::constexpr_if<
					std::is_nothrow_move_constructible<data_type>::value>(
						[this, &other]() {
					std::swap(_data, other._data);
					std::swap(_size, other._size);
				})
					._else([this, &other]() {
					clear();
					for (auto& val : other)
					{
						push_back(std::move_if_noexcept(val));
					}
					other.clear();
				});
			}
			return *this;
		}

		//Iterators
        constexpr iterator begin() noexcept { return _data.begin(); }

        constexpr const_iterator begin() const noexcept { return cbegin(); }

        constexpr const_iterator cbegin() const noexcept { return _data.begin(); }

        constexpr iterator end() noexcept { return _data.begin() + _size; }

        constexpr const_iterator end() const noexcept { return cend(); }

        constexpr const_iterator cend() noexcept { return _data.begin() + _size; }

		constexpr reverse_iterator rbegin() noexcept {
			return reverse_iterator(end());
		}

		constexpr reverse_iterator rend() noexcept {
			return reverse_iterator(begin());
		}

		constexpr const_reverse_iterator rbegin() const noexcept {
			return const_reverse_iterator(cend());
		}

		constexpr const_reverse_iterator rend() const noexcept {
			return const_reverse_iterator(cbegin());
		}

		constexpr const_reverse_iterator crbegin() const noexcept {
			return const_reverse_iterator(cend());
		}

		constexpr const_reverse_iterator crend() const noexcept {
			return const_reverse_iterator(cbegin());
		}

		//Capacity
        constexpr size_type size() const noexcept { return _size; }

		constexpr size_type length() const noexcept { return size(); }

        constexpr size_type max_size() const noexcept { return _data.max_size() - 1; }

		void resize(size_type s)
		{
			resize(s, T());
		}

		void resize(size_type s, const CHAR_T& val)
		{
			while(_size > n)
			{
				pop_back();
			}

			while(_size < n)
			{
				push_back(val);
			}
		}

		constexpr size_type capacity() const noexcept
		{
			return max_size() - size();
		}

		constexpr void clear() const noexcept
		{
			while (_size)
			{
				pop_back();
			}
		}

		constexpr bool empty() const noexcept
		{
			return size() == 0;
		}

		constexpr void shrink_to_fit() const noexcept
		{
		//nop
		}

		//String operations
		constexpr aligned_type* data() { return _data.data(); }

		constexpr const aligned_type* data() const { return _data.data(); }

	};
}
}

#endif //! FIXED_BASIC_STRING_HPP
<commit_msg>Fixing compilation<commit_after>#ifndef FIXED_BASIC_STRING_HPP
#define FIXED_BASIC_STRING_HPP

#include <string>
#include <type_traits>

#include "fixed/allocation_pattern.hpp"
#include "fixed/impl/fixed_def.hpp"
#include "fixed/impl/fixed_type_traits.hpp"
#include "fixed/vector.hpp"

namespace fixed
{
namespace _impl
{
    template <typename CHAR_T, size_t SIZE,
        typename Traits = std::char_traits<CHAR_T>,
        template <typename, size_t> typename Alloc_pattern
        = fixed::stack_allocator>
    class basic_string
    {
    public:
        typedef Traits traits_type;

        template <typename T, size_t ASIZE>
        using allocator_type = Alloc_pattern<T, ASIZE>;

    private:
        typedef allocator_type<CHAR_T, SIZE + 1> data_type;

    public:
        typedef typename data_type::value_type value_type;
        typedef typename data_type::aligned_type aligned_type;
        typedef typename data_type::size_type size_type;
        typedef typename data_type::difference_type difference_type;
        typedef typename data_type::reference reference;
        typedef typename data_type::const_reference const_reference;
        typedef typename data_type::pointer pointer;
        typedef typename data_type::const_pointer const_pointer;
        typedef typename data_type::iterator iterator;
        typedef typename data_type::const_iterator const_iterator;

        typedef std::reverse_iterator<iterator> reverse_iterator;
        typedef std::reverse_iterator<const_iterator> const_reverse_iterator;

    private:
        data_type _data;
        size_type _size;

        static_assert(std::is_trivial<CHAR_T>::value,
            "character type required to be trivial");
        static_assert(fixed::_impl::is_alloc_pattern_contiguous_v<data_type>,
            "Alloc_pattern required to be continuous for this container");

    public:
        constexpr basic_string() noexcept(
            is_nothrow_default_constructible_v<data_type>)
            : _data()
        {
        }

        template <typename Alloc_source,
            std::enable_if_t<is_allocation_source_v<Alloc_source>, int> = 0>
        constexpr basic_string(Alloc_source& source) noexcept(
            std::is_nothrow_constructible<data_type, Alloc_source&>::value)
            : _data(source)
        {
        }

        constexpr basic_string(size_type count, value_type ch)
            : _data()
        {
            assign(count, ch);
        }

        template <typename Alloc_source,
            std::enable_if_t<is_allocation_source_v<Alloc_source>, int> = 0>
        constexpr basic_string(
            size_type count, value_type ch, Alloc_source& source)
            : _data(source)
        {
            assign(count, ch);
        }

        constexpr basic_string& assign(size_type count, value_type ch)
        {
            FIXED_CHECK_FULL(count <= max_size());

            auto itbeg = _data.begin();
            for(size_type i = 0; i < count; i++)
            {
                *itbeg = ch;
                ++itbeg;
            }
            *itbeg = '\0';
            _size = count;
            return *this;
        }

		constexpr basic_string(const basic_string& str)
			: basic_string()
		{
			std::copy(str.begin(), str.end(), _data.begin());
		}

		constexpr basic_string& operator=(const basic_string& str)
		{
			if (this != &other)
			{
				std::copy(str.begin(), str.end(), _data.begin());
			}
			return *this;
		}

		constexpr basic_string(basic_string&& other) noexcept(
			is_nothrow_default_constructible_v<data_type>
			&& (is_nothrow_move_constructible_v<data_type>
				|| (is_nothrow_allocator_iterator_v<data_type> && (is_nothrow_move_constructible_v<CHAR_T> || is_nothrow_copy_constructible_v<CHAR_T>))))
			: basic_string()
		{
			operator=(std::forward(other));
		}

		constexpr basic_string& operator=(basic_string&& other) noexcept(
			is_nothrow_default_constructible_v<data_type>
			&& (is_nothrow_move_constructible_v<data_type>
				|| (is_nothrow_allocator_iterator_v<data_type> && (is_nothrow_move_constructible_v<CHAR_T> || is_nothrow_copy_constructible_v<CHAR_T>))))
		{
			if (this != &other)
			{
				fixed::astd::constexpr_if<
					std::is_nothrow_move_constructible<data_type>::value>(
						[this, &other]() {
					std::swap(_data, other._data);
					std::swap(_size, other._size);
				})
					._else([this, &other]() {
					clear();
					for (auto& val : other)
					{
						push_back(std::move_if_noexcept(val));
					}
					other.clear();
				});
			}
			return *this;
		}

		//Iterators
        constexpr iterator begin() noexcept { return _data.begin(); }

        constexpr const_iterator begin() const noexcept { return cbegin(); }

        constexpr const_iterator cbegin() const noexcept { return _data.begin(); }

        constexpr iterator end() noexcept { return _data.begin() + _size; }

        constexpr const_iterator end() const noexcept { return cend(); }

        constexpr const_iterator cend() noexcept { return _data.begin() + _size; }

		constexpr reverse_iterator rbegin() noexcept {
			return reverse_iterator(end());
		}

		constexpr reverse_iterator rend() noexcept {
			return reverse_iterator(begin());
		}

		constexpr const_reverse_iterator rbegin() const noexcept {
			return const_reverse_iterator(cend());
		}

		constexpr const_reverse_iterator rend() const noexcept {
			return const_reverse_iterator(cbegin());
		}

		constexpr const_reverse_iterator crbegin() const noexcept {
			return const_reverse_iterator(cend());
		}

		constexpr const_reverse_iterator crend() const noexcept {
			return const_reverse_iterator(cbegin());
		}

		//Capacity
        constexpr size_type size() const noexcept { return _size; }

		constexpr size_type length() const noexcept { return size(); }

        constexpr size_type max_size() const noexcept { return _data.max_size() - 1; }

		void resize(size_type s)
		{
			resize(s, T());
		}

		void resize(size_type s, const CHAR_T& val)
		{
			while(_size > n)
			{
				pop_back();
			}

			while(_size < n)
			{
				push_back(val);
			}
		}

		constexpr size_type capacity() const noexcept
		{
			return max_size() - size();
		}

		constexpr void clear() const noexcept
		{
			while (_size)
			{
				pop_back();
			}
		}

		constexpr bool empty() const noexcept
		{
			return size() == 0;
		}

		constexpr void shrink_to_fit() const noexcept
		{
		//nop
		}

		//String operations
		constexpr aligned_type* data() { return _data.data(); }

		constexpr const aligned_type* data() const { return _data.data(); }

	};
}
}

#endif //! FIXED_BASIC_STRING_HPP
<|endoftext|>


<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 "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();

  const SupportWindowImageType * supportWindowImage = this->GetSupportWindowImage();
  const MetaDataDictionary & dict = supportWindowImage->GetMetaDataDictionary();
  FFT1DSizeType fft1DSize = 32;
  ExposeMetaData< FFT1DSizeType >( dict, "FFT1DSize", fft1DSize );

  OutputImageType * output = this->GetOutput();
  output->SetVectorLength( fft1DSize );
}

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 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 );
    perThreadData.SpectraVector.set_size( fft1DSize );
    perThreadData.LineImageRegionSize.Fill( 1 );
    perThreadData.LineImageRegionSize[0] = fft1DSize;
    }
}

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();
  const ScalarType twopi = 2 * vnl_math::pi;
  for( FFT1DSizeType sample = 0; sample < length; ++sample )
    {
    window[sample] = 0.54 + 0.46 * std::cos( (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 >
typename Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >::SpectraLineType
Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >
::ComputeSpectra( const IndexType & lineIndex, ThreadIdType threadId )
{
  const InputImageType * input = this->GetInput();
  PerThreadData & perThreadData = this->m_PerThreadDataContainer[threadId];

  const FFT1DSizeType fft1DSize = static_cast< FFT1DSizeType >( perThreadData.SpectraVector.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();
  typename SpectraVectorType::const_iterator windowIt = perThreadData.LineWindowMap[fft1DSize].begin();
  while( !inputIt.IsAtEnd() )
    {
    *complexVectorIt = inputIt.Value() * *windowIt;
    ++inputIt;
    ++complexVectorIt;
    ++windowIt;
    }
  FFT1DType fft1D( fft1DSize );
  fft1D.bwd_transform( perThreadData.ComplexVector );
  typename ComplexVectorType::const_iterator complexVectorConstIt = perThreadData.ComplexVector.begin();
  typename SpectraVectorType::iterator spectraVectorIt = perThreadData.SpectraVector.begin();
  const typename SpectraVectorType::iterator spectraVectorItEnd = perThreadData.SpectraVector.end();
  while( spectraVectorIt != spectraVectorItEnd )
    {
    *spectraVectorIt = std::real(*complexVectorConstIt * std::conj(*complexVectorConstIt));
    ++spectraVectorIt;
    ++complexVectorConstIt;
    }
  return std::make_pair( lineIndex, 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();
  FFT1DSizeType fft1DSize = 32;
  ExposeMetaData< FFT1DSizeType >( dict, "FFT1DSize", fft1DSize );
  PerThreadData & perThreadData = this->m_PerThreadDataContainer[threadId];
  this->AddLineWindow( fft1DSize, perThreadData.LineWindowMap );

  ComplexVectorType complexVector( fft1DSize );
  SpectraVectorType spectraVector( fft1DSize );
  typename InputImageType::SizeType lineImageRegionSize;
  lineImageRegionSize.Fill( 1 );
  lineImageRegionSize[0] = fft1DSize;
  vnl_fft_1d< ScalarType > fft1D( fft1DSize );
  SpectraLinesContainerType spectraLines;

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

  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;
          const SpectraLineType & spectraLine = this->ComputeSpectra( lineIndex, threadId );
          spectraLines.push_back( spectraLine );
          }
        }
      else // subsequent window along a line
        {
        const IndexValueType desiredFirstLine = supportWindow[0][1];
        while( spectraLines[0].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
            {
            const SpectraLineType & spectraLine = this->ComputeSpectra( lineIndex, threadId );
            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] )
              {
              const SpectraLineType & spectraLine = this->ComputeSpectra( lineIndex, threadId );
              *spectraLinesIt = spectraLine;
              }
            ++spectraLinesIt;
            }
          else
            {
            itkExceptionMacro( "Unexpected line" );
            }
          }
        }

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

      ++outputIt;
      ++supportWindowIt;
      }
    }
}

} // end namespace itk

#endif
<commit_msg>ENH: Discard DC and redundant spectral components.<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 "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();

  const SupportWindowImageType * supportWindowImage = this->GetSupportWindowImage();
  const MetaDataDictionary & dict = supportWindowImage->GetMetaDataDictionary();
  FFT1DSizeType fft1DSize = 32;
  ExposeMetaData< FFT1DSizeType >( dict, "FFT1DSize", fft1DSize );
  const FFT1DSizeType spectraComponents = fft1DSize / 2 - 1;

  OutputImageType * output = this->GetOutput();
  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 - 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 );
    perThreadData.SpectraVector.set_size( spectraComponents );
    perThreadData.LineImageRegionSize.Fill( 1 );
    perThreadData.LineImageRegionSize[0] = fft1DSize;
    }
}

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();
  const ScalarType twopi = 2 * vnl_math::pi;
  for( FFT1DSizeType sample = 0; sample < length; ++sample )
    {
    window[sample] = 0.54 + 0.46 * std::cos( (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 >
typename Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >::SpectraLineType
Spectra1DImageFilter< TInputImage, TSupportWindowImage, TOutputImage >
::ComputeSpectra( const IndexType & lineIndex, ThreadIdType threadId )
{
  const InputImageType * input = this->GetInput();
  PerThreadData & perThreadData = this->m_PerThreadDataContainer[threadId];

  const FFT1DSizeType fft1DSize = 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();
  typename SpectraVectorType::const_iterator windowIt = perThreadData.LineWindowMap[fft1DSize].begin();
  while( !inputIt.IsAtEnd() )
    {
    *complexVectorIt = inputIt.Value() * *windowIt;
    ++inputIt;
    ++complexVectorIt;
    ++windowIt;
    }
  FFT1DType fft1D( fft1DSize );
  fft1D.bwd_transform( perThreadData.ComplexVector );
  typename ComplexVectorType::const_iterator complexVectorConstIt = perThreadData.ComplexVector.begin();
  typename SpectraVectorType::iterator spectraVectorIt = perThreadData.SpectraVector.begin();
  // drop DC component
  ++complexVectorConstIt;
  const size_t highFreq = perThreadData.SpectraVector.size();
  for( size_t freq = 0; freq < highFreq; ++freq )
    {
    spectraVectorIt[freq] = std::real(*complexVectorConstIt * std::conj(*complexVectorConstIt));
    ++complexVectorConstIt;
    }
  return std::make_pair( lineIndex, 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();
  FFT1DSizeType fft1DSize = 32;
  ExposeMetaData< FFT1DSizeType >( dict, "FFT1DSize", fft1DSize );
  PerThreadData & perThreadData = this->m_PerThreadDataContainer[threadId];
  this->AddLineWindow( fft1DSize, perThreadData.LineWindowMap );

  ComplexVectorType complexVector( fft1DSize );
  SpectraVectorType spectraVector( fft1DSize );
  typename InputImageType::SizeType lineImageRegionSize;
  lineImageRegionSize.Fill( 1 );
  lineImageRegionSize[0] = fft1DSize;
  vnl_fft_1d< ScalarType > fft1D( fft1DSize );
  SpectraLinesContainerType spectraLines;

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

  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;
          const SpectraLineType & spectraLine = this->ComputeSpectra( lineIndex, threadId );
          spectraLines.push_back( spectraLine );
          }
        }
      else // subsequent window along a line
        {
        const IndexValueType desiredFirstLine = supportWindow[0][1];
        while( spectraLines[0].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
            {
            const SpectraLineType & spectraLine = this->ComputeSpectra( lineIndex, threadId );
            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] )
              {
              const SpectraLineType & spectraLine = this->ComputeSpectra( lineIndex, threadId );
              *spectraLinesIt = spectraLine;
              }
            ++spectraLinesIt;
            }
          else
            {
            itkExceptionMacro( "Unexpected line" );
            }
          }
        }

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

      ++outputIt;
      ++supportWindowIt;
      }
    }
}

} // end namespace itk

#endif
<|endoftext|>


<commit_before>/*

Copyright (c) 2003-2008, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author 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.

*/

#ifndef TORRENT_TORRENT_INFO_HPP_INCLUDED
#define TORRENT_TORRENT_INFO_HPP_INCLUDED

#include <string>
#include <vector>
#include <iosfwd>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/optional.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/shared_array.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/entry.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/time.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/file_storage.hpp"

namespace libtorrent
{
	namespace pt = boost::posix_time;
	namespace gr = boost::gregorian;
	namespace fs = boost::filesystem;

	enum
	{
		// wait 60 seconds before retrying a failed tracker
		tracker_retry_delay_min = 10
		// when tracker_failed_max trackers
		// has failed, wait 60 minutes instead
		, tracker_retry_delay_max = 60 * 60
	};

	struct TORRENT_EXPORT announce_entry
	{
		announce_entry(std::string const& u)
			: url(u)
			, tier(0)
			, fail_limit(3)
			, fails(0)
			, source(0)
			, verified(false)
			, updating(false)
			, start_sent(false)
			, complete_sent(false)
		{}

		std::string url;

		// the time of next tracker announce
		ptime next_announce;

		boost::uint8_t tier;
		// the number of times this tracker can fail
		// in a row before it's removed. 0 means unlimited
		boost::uint8_t fail_limit;

		// the number of times in a row this tracker has failed
		boost::uint8_t fails;

		enum tracker_source
		{
			source_torrent = 1,
			source_client = 2,
			source_magnet_link = 4,
			source_tex = 8
		};
		// where did we get this tracker from
		boost::uint8_t source;

		// is set to true if we have ever received a response from
		// this tracker
		bool verified:1;

		// true if we're currently trying to announce with
		// this tracker
		bool updating:1;

		// this is true if event start has been sent to the tracker
		bool start_sent:1;

		// this is true if event completed has been sent to the tracker
		bool complete_sent:1;

		void reset()
		{
			start_sent = false;
			next_announce = min_time();
		}

		void failed()
		{
			++fails;
			int delay = (std::min)(tracker_retry_delay_min + int(fails) * int(fails) * tracker_retry_delay_min
				, int(tracker_retry_delay_max));
			next_announce = time_now() + seconds(delay);
			updating = false;
		}

		bool can_announce(ptime now) const
		{
			return now >= next_announce
				&& (fails < fail_limit || fail_limit == 0)
				&& !updating;
		}

		bool is_working() const
		{
			return fails == 0;
		}
	};

#ifndef BOOST_NO_EXCEPTIONS
	struct TORRENT_EXPORT invalid_torrent_file: std::exception
	{
		virtual const char* what() const throw() { return "invalid torrent file"; }
	};
#endif

	int TORRENT_EXPORT load_file(fs::path const& filename, std::vector<char>& v);

	class TORRENT_EXPORT torrent_info : public intrusive_ptr_base<torrent_info>
	{
	public:

		torrent_info(sha1_hash const& info_hash);
		torrent_info(lazy_entry const& torrent_file);
		torrent_info(char const* buffer, int size);
		torrent_info(fs::path const& filename);
		torrent_info(fs::wpath const& filename);
		~torrent_info();

		file_storage const& files() const { return m_files; }
		file_storage const& orig_files() const { return m_orig_files ? *m_orig_files : m_files; }

		void rename_file(int index, std::string const& new_filename)
		{
			copy_on_write();
			m_files.rename_file(index, new_filename);
		}

		void rename_file(int index, std::wstring const& new_filename)
		{
			copy_on_write();
			m_files.rename_file(index, new_filename);
		}

		void add_tracker(std::string const& url, int tier = 0);
		std::vector<announce_entry> const& trackers() const { return m_urls; }

		std::vector<std::string> const& url_seeds() const
		{ return m_url_seeds; }
		void add_url_seed(std::string const& url)
		{ m_url_seeds.push_back(url); }

		std::vector<std::string> const& http_seeds() const
		{ return m_http_seeds; }
		void add_http_seed(std::string const& url)
		{ m_http_seeds.push_back(url); }

		size_type total_size() const { return m_files.total_size(); }
		int piece_length() const { return m_files.piece_length(); }
		int num_pieces() const { return m_files.num_pieces(); }
		const sha1_hash& info_hash() const { return m_info_hash; }
		const std::string& name() const { return m_files.name(); }

		typedef file_storage::iterator file_iterator;
		typedef file_storage::reverse_iterator reverse_file_iterator;

		file_iterator begin_files() const { return m_files.begin(); }
		file_iterator end_files() const { return m_files.end(); }
		reverse_file_iterator rbegin_files() const { return m_files.rbegin(); }
		reverse_file_iterator rend_files() const { return m_files.rend(); }
		int num_files() const { return m_files.num_files(); }
		file_entry const& file_at(int index) const { return m_files.at(index); }

		file_iterator file_at_offset(size_type offset) const
		{ return m_files.file_at_offset(offset); }
		std::vector<file_slice> map_block(int piece, size_type offset, int size) const
		{ return m_files.map_block(piece, offset, size); }
		peer_request map_file(int file, size_type offset, int size) const
		{ return m_files.map_file(file, offset, size); }

#ifndef TORRENT_NO_DEPRECATE
// ------- start deprecation -------
// these functions will be removed in a future version
		torrent_info(entry const& torrent_file) TORRENT_DEPRECATED;
		void print(std::ostream& os) const TORRENT_DEPRECATED;
		file_storage& files() TORRENT_DEPRECATED { return m_files; }
// ------- end deprecation -------
#endif

		bool is_valid() const { return m_files.is_valid(); }

		bool priv() const { return m_private; }

		int piece_size(int index) const { return m_files.piece_size(index); }

		sha1_hash hash_for_piece(int index) const
		{ return sha1_hash(hash_for_piece_ptr(index)); }

		char const* hash_for_piece_ptr(int index) const
		{
			TORRENT_ASSERT(index >= 0);
			TORRENT_ASSERT(index < m_files.num_pieces());
			TORRENT_ASSERT(m_piece_hashes);
			TORRENT_ASSERT(m_piece_hashes >= m_info_section.get());
			TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size);
			return &m_piece_hashes[index*20];
		}

		boost::optional<pt::ptime> creation_date() const;

		const std::string& creator() const
		{ return m_created_by; }

		const std::string& comment() const
		{ return m_comment; }

		// dht nodes to add to the routing table/bootstrap from
		typedef std::vector<std::pair<std::string, int> > nodes_t;

		nodes_t const& nodes() const
		{ return m_nodes; }
		void add_node(std::pair<std::string, int> const& node)
		{ m_nodes.push_back(node); }

		bool parse_info_section(lazy_entry const& e, std::string& error);

		lazy_entry const* info(char const* key) const
		{
			if (m_info_dict.type() == lazy_entry::none_t)
				lazy_bdecode(m_info_section.get(), m_info_section.get()
					+ m_info_section_size, m_info_dict);
			return m_info_dict.dict_find(key);
		}

		void swap(torrent_info& ti);

		boost::shared_array<char> metadata() const
		{ return m_info_section; }

		int metadata_size() const { return m_info_section_size; }

	private:

		void copy_on_write();
		bool parse_torrent_file(lazy_entry const& libtorrent, std::string& error);

		file_storage m_files;

		// if m_files is modified, it is first copied into
		// m_orig_files so that the original name and
		// filenames are preserved.
		boost::shared_ptr<const file_storage> m_orig_files;

		// the urls to the trackers
		std::vector<announce_entry> m_urls;
		std::vector<std::string> m_url_seeds;
		std::vector<std::string> m_http_seeds;
		nodes_t m_nodes;

		// the hash that identifies this torrent
		sha1_hash m_info_hash;

		// if a creation date is found in the torrent file
		// this will be set to that, otherwise it'll be
		// 1970, Jan 1
		pt::ptime m_creation_date;

		// if a comment is found in the torrent file
		// this will be set to that comment
		std::string m_comment;

		// an optional string naming the software used
		// to create the torrent file
		std::string m_created_by;

		// this is used when creating a torrent. If there's
		// only one file there are cases where it's impossible
		// to know if it should be written as a multifile torrent
		// or not. e.g. test/test  there's one file and one directory
		// and they have the same name.
		bool m_multifile;

		// this is true if the torrent is private. i.e., is should not
		// be announced on the dht
		bool m_private;

		// this is a copy of the info section from the torrent.
		// it use maintained in this flat format in order to
		// make it available through the metadata extension
		boost::shared_array<char> m_info_section;
		int m_info_section_size;

		// this is a pointer into the m_info_section buffer
		// pointing to the first byte of the first sha-1 hash
		char const* m_piece_hashes;

		// the info section parsed. points into m_info_section
		// parsed lazily
		mutable lazy_entry m_info_dict;
	};

}

#endif // TORRENT_TORRENT_INFO_HPP_INCLUDED

<commit_msg>remove (deprecated) non-const files() from torrent_info since it opens a loop-hole to modifying the filenames without preserving the original ones<commit_after>/*

Copyright (c) 2003-2008, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author 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.

*/

#ifndef TORRENT_TORRENT_INFO_HPP_INCLUDED
#define TORRENT_TORRENT_INFO_HPP_INCLUDED

#include <string>
#include <vector>
#include <iosfwd>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/optional.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/shared_array.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/entry.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/time.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/file_storage.hpp"

namespace libtorrent
{
	namespace pt = boost::posix_time;
	namespace gr = boost::gregorian;
	namespace fs = boost::filesystem;

	enum
	{
		// wait 60 seconds before retrying a failed tracker
		tracker_retry_delay_min = 10
		// when tracker_failed_max trackers
		// has failed, wait 60 minutes instead
		, tracker_retry_delay_max = 60 * 60
	};

	struct TORRENT_EXPORT announce_entry
	{
		announce_entry(std::string const& u)
			: url(u)
			, tier(0)
			, fail_limit(3)
			, fails(0)
			, source(0)
			, verified(false)
			, updating(false)
			, start_sent(false)
			, complete_sent(false)
		{}

		std::string url;

		// the time of next tracker announce
		ptime next_announce;

		boost::uint8_t tier;
		// the number of times this tracker can fail
		// in a row before it's removed. 0 means unlimited
		boost::uint8_t fail_limit;

		// the number of times in a row this tracker has failed
		boost::uint8_t fails;

		enum tracker_source
		{
			source_torrent = 1,
			source_client = 2,
			source_magnet_link = 4,
			source_tex = 8
		};
		// where did we get this tracker from
		boost::uint8_t source;

		// is set to true if we have ever received a response from
		// this tracker
		bool verified:1;

		// true if we're currently trying to announce with
		// this tracker
		bool updating:1;

		// this is true if event start has been sent to the tracker
		bool start_sent:1;

		// this is true if event completed has been sent to the tracker
		bool complete_sent:1;

		void reset()
		{
			start_sent = false;
			next_announce = min_time();
		}

		void failed()
		{
			++fails;
			int delay = (std::min)(tracker_retry_delay_min + int(fails) * int(fails) * tracker_retry_delay_min
				, int(tracker_retry_delay_max));
			next_announce = time_now() + seconds(delay);
			updating = false;
		}

		bool can_announce(ptime now) const
		{
			return now >= next_announce
				&& (fails < fail_limit || fail_limit == 0)
				&& !updating;
		}

		bool is_working() const
		{
			return fails == 0;
		}
	};

#ifndef BOOST_NO_EXCEPTIONS
	struct TORRENT_EXPORT invalid_torrent_file: std::exception
	{
		virtual const char* what() const throw() { return "invalid torrent file"; }
	};
#endif

	int TORRENT_EXPORT load_file(fs::path const& filename, std::vector<char>& v);

	class TORRENT_EXPORT torrent_info : public intrusive_ptr_base<torrent_info>
	{
	public:

		torrent_info(sha1_hash const& info_hash);
		torrent_info(lazy_entry const& torrent_file);
		torrent_info(char const* buffer, int size);
		torrent_info(fs::path const& filename);
		torrent_info(fs::wpath const& filename);
		~torrent_info();

		file_storage const& files() const { return m_files; }
		file_storage const& orig_files() const { return m_orig_files ? *m_orig_files : m_files; }

		void rename_file(int index, std::string const& new_filename)
		{
			copy_on_write();
			m_files.rename_file(index, new_filename);
		}

		void rename_file(int index, std::wstring const& new_filename)
		{
			copy_on_write();
			m_files.rename_file(index, new_filename);
		}

		void add_tracker(std::string const& url, int tier = 0);
		std::vector<announce_entry> const& trackers() const { return m_urls; }

		std::vector<std::string> const& url_seeds() const
		{ return m_url_seeds; }
		void add_url_seed(std::string const& url)
		{ m_url_seeds.push_back(url); }

		std::vector<std::string> const& http_seeds() const
		{ return m_http_seeds; }
		void add_http_seed(std::string const& url)
		{ m_http_seeds.push_back(url); }

		size_type total_size() const { return m_files.total_size(); }
		int piece_length() const { return m_files.piece_length(); }
		int num_pieces() const { return m_files.num_pieces(); }
		const sha1_hash& info_hash() const { return m_info_hash; }
		const std::string& name() const { return m_files.name(); }

		typedef file_storage::iterator file_iterator;
		typedef file_storage::reverse_iterator reverse_file_iterator;

		file_iterator begin_files() const { return m_files.begin(); }
		file_iterator end_files() const { return m_files.end(); }
		reverse_file_iterator rbegin_files() const { return m_files.rbegin(); }
		reverse_file_iterator rend_files() const { return m_files.rend(); }
		int num_files() const { return m_files.num_files(); }
		file_entry const& file_at(int index) const { return m_files.at(index); }

		file_iterator file_at_offset(size_type offset) const
		{ return m_files.file_at_offset(offset); }
		std::vector<file_slice> map_block(int piece, size_type offset, int size) const
		{ return m_files.map_block(piece, offset, size); }
		peer_request map_file(int file, size_type offset, int size) const
		{ return m_files.map_file(file, offset, size); }

#ifndef TORRENT_NO_DEPRECATE
// ------- start deprecation -------
// these functions will be removed in a future version
		torrent_info(entry const& torrent_file) TORRENT_DEPRECATED;
		void print(std::ostream& os) const TORRENT_DEPRECATED;
// ------- end deprecation -------
#endif

		bool is_valid() const { return m_files.is_valid(); }

		bool priv() const { return m_private; }

		int piece_size(int index) const { return m_files.piece_size(index); }

		sha1_hash hash_for_piece(int index) const
		{ return sha1_hash(hash_for_piece_ptr(index)); }

		char const* hash_for_piece_ptr(int index) const
		{
			TORRENT_ASSERT(index >= 0);
			TORRENT_ASSERT(index < m_files.num_pieces());
			TORRENT_ASSERT(m_piece_hashes);
			TORRENT_ASSERT(m_piece_hashes >= m_info_section.get());
			TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size);
			return &m_piece_hashes[index*20];
		}

		boost::optional<pt::ptime> creation_date() const;

		const std::string& creator() const
		{ return m_created_by; }

		const std::string& comment() const
		{ return m_comment; }

		// dht nodes to add to the routing table/bootstrap from
		typedef std::vector<std::pair<std::string, int> > nodes_t;

		nodes_t const& nodes() const
		{ return m_nodes; }
		void add_node(std::pair<std::string, int> const& node)
		{ m_nodes.push_back(node); }

		bool parse_info_section(lazy_entry const& e, std::string& error);

		lazy_entry const* info(char const* key) const
		{
			if (m_info_dict.type() == lazy_entry::none_t)
				lazy_bdecode(m_info_section.get(), m_info_section.get()
					+ m_info_section_size, m_info_dict);
			return m_info_dict.dict_find(key);
		}

		void swap(torrent_info& ti);

		boost::shared_array<char> metadata() const
		{ return m_info_section; }

		int metadata_size() const { return m_info_section_size; }

	private:

		void copy_on_write();
		bool parse_torrent_file(lazy_entry const& libtorrent, std::string& error);

		file_storage m_files;

		// if m_files is modified, it is first copied into
		// m_orig_files so that the original name and
		// filenames are preserved.
		boost::shared_ptr<const file_storage> m_orig_files;

		// the urls to the trackers
		std::vector<announce_entry> m_urls;
		std::vector<std::string> m_url_seeds;
		std::vector<std::string> m_http_seeds;
		nodes_t m_nodes;

		// the hash that identifies this torrent
		sha1_hash m_info_hash;

		// if a creation date is found in the torrent file
		// this will be set to that, otherwise it'll be
		// 1970, Jan 1
		pt::ptime m_creation_date;

		// if a comment is found in the torrent file
		// this will be set to that comment
		std::string m_comment;

		// an optional string naming the software used
		// to create the torrent file
		std::string m_created_by;

		// this is used when creating a torrent. If there's
		// only one file there are cases where it's impossible
		// to know if it should be written as a multifile torrent
		// or not. e.g. test/test  there's one file and one directory
		// and they have the same name.
		bool m_multifile;

		// this is true if the torrent is private. i.e., is should not
		// be announced on the dht
		bool m_private;

		// this is a copy of the info section from the torrent.
		// it use maintained in this flat format in order to
		// make it available through the metadata extension
		boost::shared_array<char> m_info_section;
		int m_info_section_size;

		// this is a pointer into the m_info_section buffer
		// pointing to the first byte of the first sha-1 hash
		char const* m_piece_hashes;

		// the info section parsed. points into m_info_section
		// parsed lazily
		mutable lazy_entry m_info_dict;
	};

}

#endif // TORRENT_TORRENT_INFO_HPP_INCLUDED

<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: textapi.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _SD_TEXTAPI_HXX_
#define _SD_TEXTAPI_HXX_

#include <svx/unoedsrc.hxx>
#include <svx/unotext.hxx>
#include <svx/eeitem.hxx>
#include <rtl/ref.hxx>

class SdDrawDocument;

namespace sd {

class TextAPIEditSource;

class TextApiObject : public SvxUnoText
{
public:
    static rtl::Reference< TextApiObject > create( SdDrawDocument* pDoc );

    virtual             ~TextApiObject() throw();

    virtual void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);

    OutlinerParaObject* CreateText();
    void                SetString( const String& rText );
    void                SetText( OutlinerParaObject& rText );
    String              GetText();

    static TextApiObject* getImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::text::XText >& );

private:
    TextAPIEditSource*  mpSource;
    TextApiObject( TextAPIEditSource* pEditSource );
};

} // namespace sd

#endif // _SD_TEXTAPI_HXX_
<commit_msg>#i107450#: changes caused by header cleanup in svx<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: textapi.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _SD_TEXTAPI_HXX_
#define _SD_TEXTAPI_HXX_

#include <svx/unoedsrc.hxx>
#include <svx/unotext.hxx>
#include <svx/eeitem.hxx>
#include <rtl/ref.hxx>
#include <svx/outliner.hxx>
#include <svx/unoprnms.hxx>
#include <svx/unoforou.hxx>
#include <svx/unoipset.hxx>

class SdDrawDocument;

namespace sd {

class TextAPIEditSource;

class TextApiObject : public SvxUnoText
{
public:
    static rtl::Reference< TextApiObject > create( SdDrawDocument* pDoc );

    virtual             ~TextApiObject() throw();

    virtual void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);

    OutlinerParaObject* CreateText();
    void                SetString( const String& rText );
    void                SetText( OutlinerParaObject& rText );
    String              GetText();

    static TextApiObject* getImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::text::XText >& );

private:
    TextAPIEditSource*  mpSource;
    TextApiObject( TextAPIEditSource* pEditSource );
};

} // namespace sd

#endif // _SD_TEXTAPI_HXX_
<|endoftext|>


<commit_before>#ifndef _SDD_HOM_REWRITING_HH_
#define _SDD_HOM_REWRITING_HH_

#include <algorithm> // partition
#include <deque>
#include <tuple>

#include "sdd/hom/context_fwd.hh"
#include "sdd/hom/definition_fwd.hh"
#include "sdd/hom/fixpoint.hh"
#include "sdd/hom/local.hh"
#include "sdd/hom/saturation_fixpoint.hh"
#include "sdd/hom/saturation_sum.hh"
#include "sdd/hom/sum.hh"

namespace sdd {

/*------------------------------------------------------------------------------------------------*/

// Forward declaration for recursive call by rewriter.
template <typename C>
homomorphism<C>
rewrite(const homomorphism<C>&, const order<C>&);

/*-------------------------------------------------------------------------------------------*/

namespace hom {

/*-------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Concrete implementation of the rewriting process.
template <typename C>
struct rewriter
{
  /// @brief Needed by variant.
  typedef homomorphism<C> result_type;

  /// @brief A variable type.
  typedef typename C::Variable variable_type;

  /// @brief The type of a list of homomorphisms.
  typedef std::deque<homomorphism<C>> hom_list_type;

  /// @internal
  /// @brief Tell if an homomorphism is Local.
  struct is_local
  {
    typedef bool result_type;

    constexpr bool
    operator()(const local<C>&)
    const
    {
      return true;
    }

    template <typename T>
    constexpr bool
    operator()(const T&)
    const
    {
      return false;
    }
  };

  /// @internal
  /// @brief Tell if an homomorphism is Sum.
  struct is_sum
  {
    typedef bool result_type;

    constexpr bool
    operator()(const sum<C>&)
    const
    {
      return true;
    }

    template <typename T>
    constexpr bool
    operator()(const T&)
    const
    {
      return false;
    }
  };

  /// @brief Get the F, G and L parts of a set of homomorphisms.
  template <typename InputIterator>
  static
  std::tuple<hom_list_type, hom_list_type, hom_list_type, bool>
  partition(const order<C>& o, InputIterator begin, InputIterator end)
  {
    bool has_id = false;
    hom_list_type F;
    hom_list_type G;
    hom_list_type L;
    for (; begin != end; ++begin)
    {
      if (*begin == Id<C>())
      {
        has_id = true;
      }
      else if (begin->skip(o))
      {
        F.push_back(*begin);
      }
      else if (apply_visitor(is_local(), (*begin)->data()))
      {
        const local<C>& l = mem::variant_cast<const local<C>>((*begin)->data());
        L.push_back(l.hom());
      }
      else
      {
        G.push_back(*begin);
      }
    }
    return std::make_tuple(std::move(F), std::move(G), std::move(L), has_id);
  }

  /// @brief Rewrite Sum into a Saturation Sum, if possible.
  homomorphism<C>
  operator()( const sum<C>& s
            , const homomorphism<C>& h, const order<C>& o)
  const
  {
    auto&& p = partition(o, s.begin(), s.end());
    auto& F = std::get<0>(p);
    auto& G = std::get<1>(p);
    auto& L = std::get<2>(p);
    const bool has_id = std::get<3>(p);

    if (F.size() == 0 and L.size() == 0)
    {
      return h;
    }

    if (has_id)
    {
      F.push_back(Id<C>());
    }

    typedef typename saturation_sum<C>::optional_type optional;
    return SaturationSum<C>( o.variable()
                           , F.size() > 0 ? rewrite(Sum<C>(o.next(), F.begin(), F.end()), o.next())
                                          : optional()
                           , G.begin(), G.end()
                           , L.size() > 0 ? Local( o.identifier()
                                                 , o
                                                 , rewrite( Sum<C>(o.nested(), L.begin(), L.end())
                                                          , o.nested()))
                                          : optional()
                           );
  }

  /// @brief Rewrite a Fixpoint into a Saturation Fixpoint, if possible.
  homomorphism<C>
  operator()( const fixpoint<C>& f
            , const homomorphism<C>& h, const order<C>& o)
  const
  {
    if (not apply_visitor(is_sum(), f.hom()->data()))
    {
      return h;
    }

    const sum<C>& s = mem::variant_cast<const sum<C>>(f.hom()->data());

    auto&& p = partition(o, s.begin(), s.end());
    auto& F = std::get<0>(p);
    auto& G = std::get<1>(p);
    auto& L = std::get<2>(p);
    const bool has_id = std::get<3>(p);

    if ((not has_id) or (F.empty() and L.empty()))
    {
      return h;
    }

    // Don't forget to add id to F and L parts!.
    F.push_back(Id<C>());
    L.push_back(Id<C>());

    // Put selectors in front. It might help cut paths sooner in the Saturation Fixpoint's
    // evaluation.
    std::partition(G.begin(), G.end(), [](const homomorphism<C>& g){return g.selector();});

    return SaturationFixpoint( o.variable()
                             , rewrite(Fixpoint(Sum<C>(o.next(), F.begin(), F.end())), o.next())
                             , G.begin(), G.end()
                             , Local( o.identifier()
                                    , o
                                    , rewrite( Fixpoint(Sum<C>(o.nested(), L.begin(), L.end()))
                                             , o.nested())
                                    )
                             );
  }

  /// @brief General case.
  ///
  /// Any other homomorphism is not rewritten.
  template <typename T>
  homomorphism<C>
  operator()(const T&, const homomorphism<C>& h, const order<C>&)
  const
  {
    return h;
  }
};

} // namespace hom

/*------------------------------------------------------------------------------------------------*/

/// @brief Rewrite an homomorphism to enable saturation.
template <typename C>
homomorphism<C>
rewrite(const homomorphism<C>& h, const order<C>& o)
{
  if (o.empty())
  {
    return h;
  }
  else
  {
    return apply_visitor(hom::rewriter<C>(), h->data(), h, o);
  }
}

/*------------------------------------------------------------------------------------------------*/

} // namespace sdd

#endif // _SDD_HOM_REWRITING_HH_
<commit_msg>Whitespaces.<commit_after>#ifndef _SDD_HOM_REWRITING_HH_
#define _SDD_HOM_REWRITING_HH_

#include <algorithm> // partition
#include <deque>
#include <tuple>

#include "sdd/hom/context_fwd.hh"
#include "sdd/hom/definition_fwd.hh"
#include "sdd/hom/fixpoint.hh"
#include "sdd/hom/local.hh"
#include "sdd/hom/saturation_fixpoint.hh"
#include "sdd/hom/saturation_sum.hh"
#include "sdd/hom/sum.hh"

namespace sdd {

/*------------------------------------------------------------------------------------------------*/

// Forward declaration for recursive call by rewriter.
template <typename C>
homomorphism<C>
rewrite(const homomorphism<C>&, const order<C>&);

/*-------------------------------------------------------------------------------------------*/

namespace hom {

/*-------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Concrete implementation of the rewriting process.
template <typename C>
struct rewriter
{
  /// @brief Needed by variant.
  typedef homomorphism<C> result_type;

  /// @brief A variable type.
  typedef typename C::Variable variable_type;

  /// @brief The type of a list of homomorphisms.
  typedef std::deque<homomorphism<C>> hom_list_type;

  /// @internal
  /// @brief Tell if an homomorphism is Local.
  struct is_local
  {
    typedef bool result_type;

    constexpr bool
    operator()(const local<C>&)
    const
    {
      return true;
    }

    template <typename T>
    constexpr bool
    operator()(const T&)
    const
    {
      return false;
    }
  };

  /// @internal
  /// @brief Tell if an homomorphism is Sum.
  struct is_sum
  {
    typedef bool result_type;

    constexpr bool
    operator()(const sum<C>&)
    const
    {
      return true;
    }

    template <typename T>
    constexpr bool
    operator()(const T&)
    const
    {
      return false;
    }
  };

  /// @brief Get the F, G and L parts of a set of homomorphisms.
  template <typename InputIterator>
  static
  std::tuple<hom_list_type, hom_list_type, hom_list_type, bool>
  partition(const order<C>& o, InputIterator begin, InputIterator end)
  {
    bool has_id = false;
    hom_list_type F;
    hom_list_type G;
    hom_list_type L;
    for (; begin != end; ++begin)
    {
      if (*begin == Id<C>())
      {
        has_id = true;
      }
      else if (begin->skip(o))
      {
        F.push_back(*begin);
      }
      else if (apply_visitor(is_local(), (*begin)->data()))
      {
        const local<C>& l = mem::variant_cast<const local<C>>((*begin)->data());
        L.push_back(l.hom());
      }
      else
      {
        G.push_back(*begin);
      }
    }
    return std::make_tuple(std::move(F), std::move(G), std::move(L), has_id);
  }

  /// @brief Rewrite Sum into a Saturation Sum, if possible.
  homomorphism<C>
  operator()(const sum<C>& s, const homomorphism<C>& h, const order<C>& o)
  const
  {
    auto&& p = partition(o, s.begin(), s.end());
    auto& F = std::get<0>(p);
    auto& G = std::get<1>(p);
    auto& L = std::get<2>(p);
    const bool has_id = std::get<3>(p);

    if (F.size() == 0 and L.size() == 0)
    {
      return h;
    }

    if (has_id)
    {
      F.push_back(Id<C>());
    }

    typedef typename saturation_sum<C>::optional_type optional;
    return SaturationSum<C>( o.variable()
                           , F.size() > 0 ? rewrite(Sum<C>(o.next(), F.begin(), F.end()), o.next())
                                          : optional()
                           , G.begin(), G.end()
                           , L.size() > 0 ? Local( o.identifier()
                                                 , o
                                                 , rewrite( Sum<C>(o.nested(), L.begin(), L.end())
                                                          , o.nested()))
                                          : optional()
                           );
  }

  /// @brief Rewrite a Fixpoint into a Saturation Fixpoint, if possible.
  homomorphism<C>
  operator()(const fixpoint<C>& f, const homomorphism<C>& h, const order<C>& o)
  const
  {
    if (not apply_visitor(is_sum(), f.hom()->data()))
    {
      return h;
    }

    const sum<C>& s = mem::variant_cast<const sum<C>>(f.hom()->data());

    auto&& p = partition(o, s.begin(), s.end());
    auto& F = std::get<0>(p);
    auto& G = std::get<1>(p);
    auto& L = std::get<2>(p);
    const bool has_id = std::get<3>(p);

    if ((not has_id) or (F.empty() and L.empty()))
    {
      return h;
    }

    // Don't forget to add id to F and L parts!.
    F.push_back(Id<C>());
    L.push_back(Id<C>());

    // Put selectors in front. It might help cut paths sooner in the Saturation Fixpoint's
    // evaluation.
    std::partition(G.begin(), G.end(), [](const homomorphism<C>& g){return g.selector();});

    return SaturationFixpoint( o.variable()
                             , rewrite(Fixpoint(Sum<C>(o.next(), F.begin(), F.end())), o.next())
                             , G.begin(), G.end()
                             , Local( o.identifier()
                                    , o
                                    , rewrite( Fixpoint(Sum<C>(o.nested(), L.begin(), L.end()))
                                             , o.nested())
                                    )
                             );
  }

  /// @brief General case.
  ///
  /// Any other homomorphism is not rewritten.
  template <typename T>
  homomorphism<C>
  operator()(const T&, const homomorphism<C>& h, const order<C>&)
  const
  {
    return h;
  }
};

} // namespace hom

/*------------------------------------------------------------------------------------------------*/

/// @brief Rewrite an homomorphism to enable saturation.
template <typename C>
homomorphism<C>
rewrite(const homomorphism<C>& h, const order<C>& o)
{
  if (o.empty())
  {
    return h;
  }
  else
  {
    return apply_visitor(hom::rewriter<C>(), h->data(), h, o);
  }
}

/*------------------------------------------------------------------------------------------------*/

} // namespace sdd

#endif // _SDD_HOM_REWRITING_HH_
<|endoftext|>


<commit_before>// Copyright 2016-2017 Francesco Biscani (bluescarni@gmail.com)
//
// This file is part of the mp++ library.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef MPPP_DETAIL_TYPE_TRAITS_HPP
#define MPPP_DETAIL_TYPE_TRAITS_HPP

#include <type_traits>

namespace mppp
{

inline namespace detail
{

// A bunch of useful utilities from C++14/C++17.

// http://en.cppreference.com/w/cpp/types/void_t
#if MPPP_CPLUSPLUS >= 201703L

template <typename... Ts>
using void_t = std::void_t<Ts...>;

#else

template <typename... Ts>
struct make_void {
    typedef void type;
};

template <typename... Ts>
using void_t = typename make_void<Ts...>::type;

#endif

// http://en.cppreference.com/w/cpp/experimental/is_detected
template <class Default, class AlwaysVoid, template <class...> class Op, class... Args>
struct detector {
    using value_t = std::false_type;
    using type = Default;
};

template <class Default, template <class...> class Op, class... Args>
struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
    using value_t = std::true_type;
    using type = Op<Args...>;
};

// http://en.cppreference.com/w/cpp/experimental/nonesuch
struct nonesuch {
    nonesuch() = delete;
    ~nonesuch() = delete;
    nonesuch(nonesuch const &) = delete;
    void operator=(nonesuch const &) = delete;
};

template <template <class...> class Op, class... Args>
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;

template <template <class...> class Op, class... Args>
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;

// http://en.cppreference.com/w/cpp/types/conjunction
// http://en.cppreference.com/w/cpp/types/disjunction
// http://en.cppreference.com/w/cpp/types/negation
#if MPPP_CPLUSPLUS >= 201703L

template <typename... Ts>
using conjunction = std::conjunction<Ts...>;

template <typename... Ts>
using disjunction = std::disjunction<Ts...>;

template <typename T>
using negation = std::negation<T>;

#else

template <class...>
struct conjunction : std::true_type {
};

template <class B1>
struct conjunction<B1> : B1 {
};

template <class B1, class... Bn>
struct conjunction<B1, Bn...> : std::conditional<B1::value != false, conjunction<Bn...>, B1>::type {
};

template <class...>
struct disjunction : std::false_type {
};

template <class B1>
struct disjunction<B1> : B1 {
};

template <class B1, class... Bn>
struct disjunction<B1, Bn...> : std::conditional<B1::value != false, B1, disjunction<Bn...>>::type {
};

template <class B>
struct negation : std::integral_constant<bool, !B::value> {
};

#endif

// Some handy aliases.
template <typename T>
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;

// Small helpers, like C++14.
template <bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;

template <typename T>
using make_unsigned = typename std::make_unsigned<T>::type;
}
}

#endif
<commit_msg>Add another type trait as implementation detail.<commit_after>// Copyright 2016-2017 Francesco Biscani (bluescarni@gmail.com)
//
// This file is part of the mp++ library.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef MPPP_DETAIL_TYPE_TRAITS_HPP
#define MPPP_DETAIL_TYPE_TRAITS_HPP

#include <type_traits>

namespace mppp
{

inline namespace detail
{

// A bunch of useful utilities from C++14/C++17.

// http://en.cppreference.com/w/cpp/types/void_t
#if MPPP_CPLUSPLUS >= 201703L

template <typename... Ts>
using void_t = std::void_t<Ts...>;

#else

template <typename... Ts>
struct make_void {
    typedef void type;
};

template <typename... Ts>
using void_t = typename make_void<Ts...>::type;

#endif

// http://en.cppreference.com/w/cpp/experimental/is_detected
template <class Default, class AlwaysVoid, template <class...> class Op, class... Args>
struct detector {
    using value_t = std::false_type;
    using type = Default;
};

template <class Default, template <class...> class Op, class... Args>
struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
    using value_t = std::true_type;
    using type = Op<Args...>;
};

// http://en.cppreference.com/w/cpp/experimental/nonesuch
struct nonesuch {
    nonesuch() = delete;
    ~nonesuch() = delete;
    nonesuch(nonesuch const &) = delete;
    void operator=(nonesuch const &) = delete;
};

template <template <class...> class Op, class... Args>
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;

template <template <class...> class Op, class... Args>
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;

// http://en.cppreference.com/w/cpp/types/conjunction
// http://en.cppreference.com/w/cpp/types/disjunction
// http://en.cppreference.com/w/cpp/types/negation
#if MPPP_CPLUSPLUS >= 201703L

template <typename... Ts>
using conjunction = std::conjunction<Ts...>;

template <typename... Ts>
using disjunction = std::disjunction<Ts...>;

template <typename T>
using negation = std::negation<T>;

#else

template <class...>
struct conjunction : std::true_type {
};

template <class B1>
struct conjunction<B1> : B1 {
};

template <class B1, class... Bn>
struct conjunction<B1, Bn...> : std::conditional<B1::value != false, conjunction<Bn...>, B1>::type {
};

template <class...>
struct disjunction : std::false_type {
};

template <class B1>
struct disjunction<B1> : B1 {
};

template <class B1, class... Bn>
struct disjunction<B1, Bn...> : std::conditional<B1::value != false, B1, disjunction<Bn...>>::type {
};

template <class B>
struct negation : std::integral_constant<bool, !B::value> {
};

#endif

// Some handy aliases.
template <typename T>
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;

// Small helpers, like C++14.
template <bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;

template <typename T>
using make_unsigned = typename std::make_unsigned<T>::type;

// Detect non-const non-volatile rvalue references.
template <typename T>
using is_ncvrvr
    = conjunction<std::is_rvalue_reference<T>, negation<std::is_const<typename std::remove_reference<T>::type>>,
                  negation<std::is_volatile<typename std::remove_reference<T>::type>>>;
}
}

#endif
<|endoftext|>